diff --git a/.github/actions/oidc/action.yaml b/.github/actions/oidc/action.yaml new file mode 100644 index 000000000..119cf9e9a --- /dev/null +++ b/.github/actions/oidc/action.yaml @@ -0,0 +1,45 @@ +--- +name: AWS OIDC Credentials via Role Assume Chaining +description: Retrieve AWS credentials by chaining role assumes +inputs: + role-for-oidc: + description: The role that should be used for GitHub OIDC authentication + required: true + role-to-assume: + description: The role that should be finally assumed + required: true + role-session-name: + description: The session name that should be used when assuming roles + required: true + default: github-actions + role-duration-seconds: + description: duration of the credentials validity + required: true + default: "3600" + aws-region: + description: The AWS region + required: false + default: us-east-1 + +runs: + using: composite + steps: + - name: assume oidc role + uses: aws-actions/configure-aws-credentials@ececac1a45f3b08a01d2dd070d28d111c5fe6722 # v4.1.0 + with: + aws-region: us-east-1 + role-to-assume: ${{ inputs.role-for-oidc }} + role-session-name: ${{ inputs.role-session-name }} + role-duration-seconds: 900 + - name: assume target role + uses: aws-actions/configure-aws-credentials@ececac1a45f3b08a01d2dd070d28d111c5fe6722 # v4.1.0 + id: assume-target-role + with: + aws-access-key-id: ${{ env.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ env.AWS_SECRET_ACCESS_KEY }} + aws-session-token: ${{ env.AWS_SESSION_TOKEN }} + aws-region: ${{ inputs.aws-region }} + role-chaining: true + role-to-assume: ${{ inputs.role-to-assume }} + role-session-name: ${{ inputs.role-session-name }} + role-duration-seconds: ${{ inputs.role-duration-seconds }} \ No newline at end of file diff --git a/.github/workflows/docker-prod.yaml b/.github/workflows/docker-prod.yaml new file mode 100644 index 000000000..2999448b8 --- /dev/null +++ b/.github/workflows/docker-prod.yaml @@ -0,0 +1,133 @@ +# This workflow runs whenever a release is created. +# The image is tagged with latest and the release version. +name: (Production) Build and Push Docker Images + +on: + release: + types: [published] + +permissions: + contents: read + +jobs: + build-and-push: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: read + packages: write + attestations: write + security-events: write + env: + REGISTRY: ${{ secrets.RESEARCH_ACCOUNT_ID }}.dkr.ecr.us-east-1.amazonaws.com + ROLE_FOR_OIDC: 'arn:aws:iam::${{ secrets.ROOT_ACCOUNT_ID }}:role/github-actions-research-account-oidc-role' + ROLE_TO_ASSUME: 'arn:aws:iam::${{ secrets.RESEARCH_ACCOUNT_ID }}:role/GithubOIDCResearchAccountRole' + steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0 + with: + egress-policy: audit + + - uses: actions/create-github-app-token@af35edadc00be37caa72ed9f3e6d5f7801bfdf09 # v1.11.7 + id: gh-app-token + with: + app-id: ${{ vars.GH_APP_ID }} + private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} + + - name: Checkout Repo + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + token: ${{ steps.gh-app-token.outputs.token }} + fetch-depth: 0 + + - name: Setup pre-requisites + uses: ./.github/actions/setup + with: + token: ${{ steps.gh-app-token.outputs.token }} + + - name: Set up QEMU + uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0 + with: + platforms: 'arm64' + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 + + - name: Set up AWS credentials via OIDC and role chaining + uses: ./.github/actions/oidc + with: + role-for-oidc: ${{ env.ROLE_FOR_OIDC }} + role-to-assume: ${{ env.ROLE_TO_ASSUME }} + + - name: Login to Amazon ECR + uses: aws-actions/amazon-ecr-login@062b18b96a7aff071d4dc91bc00c4c1a7945b076 # v2.0.1 + + - name: Build Stellar API Docker image + uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6.15.0 + id: build + with: + context: . + platforms: linux/amd64 # linux/arm64 causes anchore/scan-action to fail + tags: | + ${{ env.REGISTRY }}/wizard-stellar-api-prod:latest + ${{ env.REGISTRY }}/wizard-stellar-api-prod:${{ github.sha }} + cache-from: type=gha + cache-to: type=gha,mode=max + load: true + + - name: Scan Stellar API Docker image + uses: anchore/scan-action@df395807f4554463d4455b8047cf58e37b6acaae # v6.5.0 + id: scan + with: + image: ${{ env.REGISTRY }}/wizard-stellar-api-prod:${{ github.sha }} + fail-build: false + + - name: Upload Anchore scan SARIF report + uses: github/codeql-action/upload-sarif@51f77329afa6477de8c49fc9c7046c15b9a4e79d # v3.29.5 + with: + sarif_file: ${{ steps.scan.outputs.sarif }} + + - name: Build and push Stellar API Docker image + uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6.15.0 + id: push + with: + context: packages/ui/api/stellar + file: Dockerfile.prod + platforms: linux/amd64,linux/arm64 + push: true + tags: | + ${{ env.REGISTRY }}/wizard-stellar-api-prod:latest + ${{ env.REGISTRY }}/wizard-stellar-api-prod:${{ github.sha }} + cache-from: type=gha + cache-to: type=gha,mode=max + + deploy: + runs-on: ubuntu-latest + needs: build-and-push + env: + ROLE_FOR_OIDC: 'arn:aws:iam::${{ secrets.ROOT_ACCOUNT_ID }}:role/github-actions-research-account-oidc-role' + ROLE_TO_ASSUME: 'arn:aws:iam::${{ secrets.RESEARCH_ACCOUNT_ID }}:role/GithubOIDCResearchAccountRole' + ECS_CLUSTER: 'wizard-prod-cluster' + ECS_SERVICE: 'wizard-prod-service' + AWS_REGION: 'us-east-1' + permissions: + contents: read + id-token: write + steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0 + with: + egress-policy: audit + + - name: Checkout code + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - name: Set up AWS credentials via OIDC and role chaining + uses: ./.github/actions/oidc + with: + role-for-oidc: ${{ env.ROLE_FOR_OIDC }} + role-to-assume: ${{ env.ROLE_TO_ASSUME }} + + - name: AWS ECS force new deployment + run: | + aws ecs update-service --cluster $ECS_CLUSTER --service $ECS_SERVICE --force-new-deployment --region $AWS_REGION \ No newline at end of file diff --git a/.github/workflows/docker-stg.yaml b/.github/workflows/docker-stg.yaml new file mode 100644 index 000000000..66897aa1c --- /dev/null +++ b/.github/workflows/docker-stg.yaml @@ -0,0 +1,126 @@ +# This workflow runs whenever a release is created. +# The image is tagged with latest and the release version. +name: (Staging) Build and Push Docker Images + +on: + push: + branches: [staging] + workflow_dispatch: + inputs: + branch: + description: 'Branch to build from' + required: true + default: 'ci-cd' + type: string + +permissions: + contents: read + +jobs: + build-and-push: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: read + packages: write + attestations: write + security-events: write + env: + REGISTRY: ${{ secrets.RESEARCH_ACCOUNT_ID }}.dkr.ecr.us-east-1.amazonaws.com + ROLE_FOR_OIDC: 'arn:aws:iam::${{ secrets.ROOT_ACCOUNT_ID }}:role/github-actions-research-account-oidc-role' + ROLE_TO_ASSUME: 'arn:aws:iam::${{ secrets.RESEARCH_ACCOUNT_ID }}:role/GithubOIDCResearchAccountRole' + steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0 + with: + egress-policy: audit + + - name: Checkout code + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - name: Set up QEMU + uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0 + with: + platforms: 'arm64' + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 + + - name: Set up AWS credentials via OIDC and role chaining + uses: ./.github/actions/oidc + with: + role-for-oidc: ${{ env.ROLE_FOR_OIDC }} + role-to-assume: ${{ env.ROLE_TO_ASSUME }} + + - name: Login to Amazon ECR + uses: aws-actions/amazon-ecr-login@062b18b96a7aff071d4dc91bc00c4c1a7945b076 # v2.0.1 + + - name: Build Stellar API Docker image + uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6.15.0 + id: build + with: + context: ./packages/ui/api/stellar + platforms: linux/amd64 # linux/arm64 causes anchore/scan-action to fail + tags: | + ${{ env.REGISTRY }}/wizard-stellar-api-stg:latest + ${{ env.REGISTRY }}/wizard-stellar-api-stg:${{ github.sha }} + cache-from: type=gha + cache-to: type=gha,mode=max + load: true + + - name: Scan Stellar API Docker image + uses: anchore/scan-action@df395807f4554463d4455b8047cf58e37b6acaae # v6.5.0 + id: scan + with: + image: ${{ env.REGISTRY }}/wizard-stellar-api-stg:${{ github.sha }} + fail-build: false + + - name: Upload Anchore scan SARIF report + uses: github/codeql-action/upload-sarif@51f77329afa6477de8c49fc9c7046c15b9a4e79d # v3.29.5 + with: + sarif_file: ${{ steps.scan.outputs.sarif }} + + - name: Build and push Stellar API Docker image + uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6.15.0 + id: push + with: + context: packages/ui/api/stellar + file: Dockerfile.prod + platforms: linux/amd64,linux/arm64 + push: true + tags: | + ${{ env.REGISTRY }}/wizard-stellar-api-stg:latest + ${{ env.REGISTRY }}/wizard-stellar-api-stg:${{ github.sha }} + cache-from: type=gha + cache-to: type=gha,mode=max + + deploy: + runs-on: ubuntu-latest + needs: build-and-push + env: + ROLE_FOR_OIDC: 'arn:aws:iam::${{ secrets.ROOT_ACCOUNT_ID }}:role/github-actions-research-account-oidc-role' + ROLE_TO_ASSUME: 'arn:aws:iam::${{ secrets.RESEARCH_ACCOUNT_ID }}:role/GithubOIDCResearchAccountRole' + ECS_CLUSTER: 'wizard-stg-cluster' + ECS_SERVICE: 'wizard-stg-service' + AWS_REGION: 'us-east-1' + permissions: + contents: read + id-token: write + steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0 + with: + egress-policy: audit + + - name: Checkout code + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - name: Set up AWS credentials via OIDC and role chaining + uses: ./.github/actions/oidc + with: + role-for-oidc: ${{ env.ROLE_FOR_OIDC }} + role-to-assume: ${{ env.ROLE_TO_ASSUME }} + + - name: AWS ECS force new deployment + run: | + aws ecs update-service --cluster $ECS_CLUSTER --service $ECS_SERVICE --force-new-deployment --region $AWS_REGION \ No newline at end of file diff --git a/.gitignore b/.gitignore index baf29d25e..10090a014 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,9 @@ node_modules .env .env.local .vscode/settings.json +.qodo/ + +# Generated by Cargo +# will have compiled files and executables +debug/ +target/ diff --git a/.prettierignore b/.prettierignore index d49d96ac6..5ef2de522 100644 --- a/.prettierignore +++ b/.prettierignore @@ -15,4 +15,5 @@ build/ public/ remappings.txt *.cairo -*.sh \ No newline at end of file +*.sh +*.rs \ No newline at end of file diff --git a/.vscode/example.settings.json b/.vscode/example.settings.json index 1adf5de86..21bf43bc6 100644 --- a/.vscode/example.settings.json +++ b/.vscode/example.settings.json @@ -4,5 +4,13 @@ "deno.enable": true, "deno.enablePaths": [ "packages/ui/scripts/deno/" - ] + ], + "[rust]": { + "editor.defaultFormatter": "rust-lang.rust-analyzer" + }, + "rust-analyzer.linkedProjects": [ + "packages/ui/stellar/Cargo.toml" + ], + "rust-analyzer.check.command": "clippy", + "rust-analyzer.checkOnSave": true } \ No newline at end of file diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 14c228ba3..4edda7e30 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -2,6 +2,7 @@ "recommendations": [ "esbenp.prettier-vscode", "dbaeumer.vscode-eslint", - "denoland.vscode-deno" - ] + "denoland.vscode-deno", + "rust-lang.rust-analyzer" + ], } \ No newline at end of file diff --git a/netlify.toml b/netlify.toml index aba54c949..9b029ac67 100644 --- a/netlify.toml +++ b/netlify.toml @@ -2,11 +2,11 @@ command = "yarn --cwd packages/ui build" publish = "packages/ui/public" -edge_functions = "packages/ui/api" +edge_functions = "packages/ui/api/ai/paths" [functions] - deno_import_map = "packages/ui/import_map.json" +deno_import_map = "packages/ui/api/ai/import_map.json" [[edge_functions]] - path = "/ai" - function = "ai" \ No newline at end of file +path = "/ai" +function = "ai" diff --git a/package.json b/package.json index f26a4e00c..8882c3c07 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "type:check:api": "yarn --cwd ./packages/ui type:check:api", "dev:ui": "yarn --cwd ./packages/ui dev", "dev:api": "yarn --cwd ./packages/ui dev:api", + "dev:api:build": "yarn --cwd ./packages/ui dev:api:build", "dev": "concurrently --kill-others-on-fail --names \"UI,API\" --prefix-colors \"magenta.bold,green.bold\" \"yarn dev:ui\" \"yarn dev:api\"", "run:core": "node ./scripts/run-command.mjs", "version": "bash scripts/release/version.sh", @@ -41,4 +42,4 @@ "@changesets/cli": "^2.29.2", "@changesets/changelog-github": "^0.5.1" } -} +} \ No newline at end of file diff --git a/packages/core/stellar/src/zip-rust.ts b/packages/core/stellar/src/zip-rust.ts index 01bf1b106..520560d64 100644 --- a/packages/core/stellar/src/zip-rust.ts +++ b/packages/core/stellar/src/zip-rust.ts @@ -43,3 +43,6 @@ const addRustProjectReadme = (zip: JSZip) => zip.file('README.md', readme); export const zipRustProject = async (c: Contract, opts: GenericOptions) => addRustProjectReadme(createRustZipEnvironment(c, opts)); + +export const zipRustProjectBlob = async (c: Contract, opts: GenericOptions) => + await (await zipRustProject(c, opts)).generateAsync({ type: 'blob', compression: 'DEFLATE' }); diff --git a/packages/ui/.env.example b/packages/ui/.env.example new file mode 100644 index 000000000..233e8c6ab --- /dev/null +++ b/packages/ui/.env.example @@ -0,0 +1,4 @@ +ENV="dev" + +API_HOST=http://localhost:3000 +FARGATE_HOST=http://localhost:8888 \ No newline at end of file diff --git a/packages/ui/api/ai/.env.example b/packages/ui/api/ai/.env.example new file mode 100644 index 000000000..65cc4cea1 --- /dev/null +++ b/packages/ui/api/ai/.env.example @@ -0,0 +1,2 @@ +API_PORT=3000 +OPENAI_API_KEY= \ No newline at end of file diff --git a/packages/ui/api/ai/Dockerfile.dev b/packages/ui/api/ai/Dockerfile.dev new file mode 100644 index 000000000..1d2b791e9 --- /dev/null +++ b/packages/ui/api/ai/Dockerfile.dev @@ -0,0 +1,11 @@ +# Match netlify version environment +FROM denoland/deno:1.46.3 + +COPY . /app/ui/api/ai +COPY ../../common /app/common + +WORKDIR /app/ui/api/ai + +EXPOSE 3000 + +CMD ["deno","task","dev"] \ No newline at end of file diff --git a/packages/ui/api/ai-assistant/function-definitions/cairo-alpha-shared.ts b/packages/ui/api/ai/ai-assistant/function-definitions/cairo-alpha-shared.ts similarity index 89% rename from packages/ui/api/ai-assistant/function-definitions/cairo-alpha-shared.ts rename to packages/ui/api/ai/ai-assistant/function-definitions/cairo-alpha-shared.ts index c05b58a9f..d04615a59 100644 --- a/packages/ui/api/ai-assistant/function-definitions/cairo-alpha-shared.ts +++ b/packages/ui/api/ai/ai-assistant/function-definitions/cairo-alpha-shared.ts @@ -1,7 +1,10 @@ import type { AiFunctionPropertyDefinition } from '../types/function-definition.ts'; import type { CairoAlphaCommonContractOptions, CairoAlphaRoyaltyInfoOptions } from '../types/languages.ts'; -import { infoDescriptions } from '../../../../common/src/ai/descriptions/common.ts'; -import { cairoCommonDescriptions, cairoRoyaltyInfoDescriptions } from '../../../../common/src/ai/descriptions/cairo.ts'; +import { infoDescriptions } from '../../../../../common/src/ai/descriptions/common.ts'; +import { + cairoCommonDescriptions, + cairoRoyaltyInfoDescriptions, +} from '../../../../../common/src/ai/descriptions/cairo.ts'; const commonContractFunctionDescription = { upgradeable: { diff --git a/packages/ui/api/ai-assistant/function-definitions/cairo-alpha.ts b/packages/ui/api/ai/ai-assistant/function-definitions/cairo-alpha.ts similarity index 99% rename from packages/ui/api/ai-assistant/function-definitions/cairo-alpha.ts rename to packages/ui/api/ai/ai-assistant/function-definitions/cairo-alpha.ts index 0940c1a01..da163dd25 100644 --- a/packages/ui/api/ai-assistant/function-definitions/cairo-alpha.ts +++ b/packages/ui/api/ai/ai-assistant/function-definitions/cairo-alpha.ts @@ -10,7 +10,7 @@ import { cairoGovernorDescriptions, cairoMultisigDescriptions, cairoVestingDescriptions, -} from '../../../../common/src/ai/descriptions/cairo.ts'; +} from '../../../../../common/src/ai/descriptions/cairo.ts'; export const cairoAlphaERC20AIFunctionDefinition = { name: 'ERC20', diff --git a/packages/ui/api/ai-assistant/function-definitions/cairo-shared.ts b/packages/ui/api/ai/ai-assistant/function-definitions/cairo-shared.ts similarity index 89% rename from packages/ui/api/ai-assistant/function-definitions/cairo-shared.ts rename to packages/ui/api/ai/ai-assistant/function-definitions/cairo-shared.ts index 805620d8c..9befc748e 100644 --- a/packages/ui/api/ai-assistant/function-definitions/cairo-shared.ts +++ b/packages/ui/api/ai/ai-assistant/function-definitions/cairo-shared.ts @@ -1,7 +1,10 @@ import type { AiFunctionPropertyDefinition } from '../types/function-definition.ts'; import type { CairoCommonContractOptions, CairoRoyaltyInfoOptions } from '../types/languages.ts'; -import { infoDescriptions } from '../../../../common/src/ai/descriptions/common.ts'; -import { cairoCommonDescriptions, cairoRoyaltyInfoDescriptions } from '../../../../common/src/ai/descriptions/cairo.ts'; +import { infoDescriptions } from '../../../../../common/src/ai/descriptions/common.ts'; +import { + cairoCommonDescriptions, + cairoRoyaltyInfoDescriptions, +} from '../../../../../common/src/ai/descriptions/cairo.ts'; const commonContractFunctionDescription = { upgradeable: { diff --git a/packages/ui/api/ai-assistant/function-definitions/cairo.ts b/packages/ui/api/ai/ai-assistant/function-definitions/cairo.ts similarity index 99% rename from packages/ui/api/ai-assistant/function-definitions/cairo.ts rename to packages/ui/api/ai/ai-assistant/function-definitions/cairo.ts index 4a0dddbcd..3b62f3698 100644 --- a/packages/ui/api/ai-assistant/function-definitions/cairo.ts +++ b/packages/ui/api/ai/ai-assistant/function-definitions/cairo.ts @@ -9,7 +9,7 @@ import { cairoGovernorDescriptions, cairoMultisigDescriptions, cairoVestingDescriptions, -} from '../../../../common/src/ai/descriptions/cairo.ts'; +} from '../../../../../common/src/ai/descriptions/cairo.ts'; export const cairoERC20AIFunctionDefinition = { name: 'ERC20', diff --git a/packages/ui/api/ai-assistant/function-definitions/polkadot.ts b/packages/ui/api/ai/ai-assistant/function-definitions/polkadot.ts similarity index 100% rename from packages/ui/api/ai-assistant/function-definitions/polkadot.ts rename to packages/ui/api/ai/ai-assistant/function-definitions/polkadot.ts diff --git a/packages/ui/api/ai-assistant/function-definitions/shared.ts b/packages/ui/api/ai/ai-assistant/function-definitions/shared.ts similarity index 93% rename from packages/ui/api/ai-assistant/function-definitions/shared.ts rename to packages/ui/api/ai/ai-assistant/function-definitions/shared.ts index ae762b2ed..b21527d02 100644 --- a/packages/ui/api/ai-assistant/function-definitions/shared.ts +++ b/packages/ui/api/ai/ai-assistant/function-definitions/shared.ts @@ -1,5 +1,5 @@ import type { AiFunctionPropertyDefinition } from '../types/function-definition.ts'; -import { commonDescriptions } from '../../../../common/src/ai/descriptions/common.ts'; +import { commonDescriptions } from '../../../../../common/src/ai/descriptions/common.ts'; const sharedFunctionDescription = { name: { type: 'string', description: commonDescriptions.name }, diff --git a/packages/ui/api/ai-assistant/function-definitions/solidity-shared.ts b/packages/ui/api/ai/ai-assistant/function-definitions/solidity-shared.ts similarity index 84% rename from packages/ui/api/ai-assistant/function-definitions/solidity-shared.ts rename to packages/ui/api/ai/ai-assistant/function-definitions/solidity-shared.ts index 512c38832..ec5342c62 100644 --- a/packages/ui/api/ai-assistant/function-definitions/solidity-shared.ts +++ b/packages/ui/api/ai/ai-assistant/function-definitions/solidity-shared.ts @@ -1,7 +1,7 @@ import type { AiFunctionPropertyDefinition } from '../types/function-definition.ts'; import type { SolidityCommonOptions } from '../types/languages.ts'; -import { infoDescriptions } from '../../../../common/src/ai/descriptions/common.ts'; -import { solidityCommonDescriptions } from '../../../../common/src/ai/descriptions/solidity.ts'; +import { infoDescriptions } from '../../../../../common/src/ai/descriptions/common.ts'; +import { solidityCommonDescriptions } from '../../../../../common/src/ai/descriptions/solidity.ts'; export const commonFunctionDescription = { access: { diff --git a/packages/ui/api/ai-assistant/function-definitions/solidity.ts b/packages/ui/api/ai/ai-assistant/function-definitions/solidity.ts similarity index 99% rename from packages/ui/api/ai-assistant/function-definitions/solidity.ts rename to packages/ui/api/ai/ai-assistant/function-definitions/solidity.ts index 81cc84a4f..e7a3a86d6 100644 --- a/packages/ui/api/ai-assistant/function-definitions/solidity.ts +++ b/packages/ui/api/ai/ai-assistant/function-definitions/solidity.ts @@ -9,7 +9,7 @@ import { solidityERC1155Descriptions, solidityStablecoinDescriptions, solidityGovernorDescriptions, -} from '../../../../common/src/ai/descriptions/solidity.ts'; +} from '../../../../../common/src/ai/descriptions/solidity.ts'; export const solidityERC20AIFunctionDefinition = { name: 'ERC20', diff --git a/packages/ui/api/ai-assistant/function-definitions/stellar-shared.ts b/packages/ui/api/ai/ai-assistant/function-definitions/stellar-shared.ts similarity index 82% rename from packages/ui/api/ai-assistant/function-definitions/stellar-shared.ts rename to packages/ui/api/ai/ai-assistant/function-definitions/stellar-shared.ts index 6c030b1bc..b9920523c 100644 --- a/packages/ui/api/ai-assistant/function-definitions/stellar-shared.ts +++ b/packages/ui/api/ai/ai-assistant/function-definitions/stellar-shared.ts @@ -1,7 +1,7 @@ import type { AiFunctionPropertyDefinition } from '../types/function-definition.ts'; import type { StellarCommonContractOptions } from '../types/languages.ts'; -import { infoDescriptions } from '../../../../common/src/ai/descriptions/common.ts'; -import { stellarCommonDescriptions } from '../../../../common/src/ai/descriptions/stellar.ts'; +import { infoDescriptions } from '../../../../../common/src/ai/descriptions/common.ts'; +import { stellarCommonDescriptions } from '../../../../../common/src/ai/descriptions/stellar.ts'; export const stellarCommonFunctionDescription = { access: { diff --git a/packages/ui/api/ai-assistant/function-definitions/stellar.ts b/packages/ui/api/ai/ai-assistant/function-definitions/stellar.ts similarity index 97% rename from packages/ui/api/ai-assistant/function-definitions/stellar.ts rename to packages/ui/api/ai/ai-assistant/function-definitions/stellar.ts index 61b415283..a08ab0bc8 100644 --- a/packages/ui/api/ai-assistant/function-definitions/stellar.ts +++ b/packages/ui/api/ai/ai-assistant/function-definitions/stellar.ts @@ -7,7 +7,7 @@ import { stellarFungibleDescriptions, stellarNonFungibleDescriptions, stellarStablecoinDescriptions, -} from '../../../../common/src/ai/descriptions/stellar.ts'; +} from '../../../../../common/src/ai/descriptions/stellar.ts'; export const stellarFungibleAIFunctionDefinition = { name: 'Fungible', diff --git a/packages/ui/api/ai-assistant/function-definitions/stylus-shared.ts b/packages/ui/api/ai/ai-assistant/function-definitions/stylus-shared.ts similarity index 92% rename from packages/ui/api/ai-assistant/function-definitions/stylus-shared.ts rename to packages/ui/api/ai/ai-assistant/function-definitions/stylus-shared.ts index be4570d6d..e4a10fe0c 100644 --- a/packages/ui/api/ai-assistant/function-definitions/stylus-shared.ts +++ b/packages/ui/api/ai/ai-assistant/function-definitions/stylus-shared.ts @@ -1,6 +1,6 @@ import type { AiFunctionPropertyDefinition } from '../types/function-definition.ts'; import type { StylusCommonContractOptions } from '../types/languages.ts'; -import { infoDescriptions } from '../../../../common/src/ai/descriptions/common.ts'; +import { infoDescriptions } from '../../../../../common/src/ai/descriptions/common.ts'; export const stylusCommonFunctionDescription = { access: { diff --git a/packages/ui/api/ai-assistant/function-definitions/stylus.ts b/packages/ui/api/ai/ai-assistant/function-definitions/stylus.ts similarity index 96% rename from packages/ui/api/ai-assistant/function-definitions/stylus.ts rename to packages/ui/api/ai/ai-assistant/function-definitions/stylus.ts index 5d6b52c11..2c8255be2 100644 --- a/packages/ui/api/ai-assistant/function-definitions/stylus.ts +++ b/packages/ui/api/ai/ai-assistant/function-definitions/stylus.ts @@ -6,7 +6,7 @@ import { stylusERC20Descriptions, stylusERC721Descriptions, stylusERC1155Descriptions, -} from '../../../../common/src/ai/descriptions/stylus.ts'; +} from '../../../../../common/src/ai/descriptions/stylus.ts'; export const stylusERC20AIFunctionDefinition = { name: 'ERC20', diff --git a/packages/ui/api/ai-assistant/types/assistant.ts b/packages/ui/api/ai/ai-assistant/types/assistant.ts similarity index 100% rename from packages/ui/api/ai-assistant/types/assistant.ts rename to packages/ui/api/ai/ai-assistant/types/assistant.ts diff --git a/packages/ui/api/ai-assistant/types/function-definition.ts b/packages/ui/api/ai/ai-assistant/types/function-definition.ts similarity index 100% rename from packages/ui/api/ai-assistant/types/function-definition.ts rename to packages/ui/api/ai/ai-assistant/types/function-definition.ts diff --git a/packages/ui/api/ai-assistant/types/helpers.ts b/packages/ui/api/ai/ai-assistant/types/helpers.ts similarity index 100% rename from packages/ui/api/ai-assistant/types/helpers.ts rename to packages/ui/api/ai/ai-assistant/types/helpers.ts diff --git a/packages/ui/api/ai-assistant/types/languages.ts b/packages/ui/api/ai/ai-assistant/types/languages.ts similarity index 85% rename from packages/ui/api/ai-assistant/types/languages.ts rename to packages/ui/api/ai/ai-assistant/types/languages.ts index 2a87463fa..8a33891dd 100644 --- a/packages/ui/api/ai-assistant/types/languages.ts +++ b/packages/ui/api/ai/ai-assistant/types/languages.ts @@ -1,23 +1,23 @@ // Solidity -import type { KindedOptions as SolidityKindedOptions } from '../../../../core/solidity/dist'; -export type { CommonOptions as SolidityCommonOptions } from '../../../../core/solidity/dist/common-options'; +import type { KindedOptions as SolidityKindedOptions } from '../../../../../core/solidity/dist'; +export type { CommonOptions as SolidityCommonOptions } from '../../../../../core/solidity/dist/common-options'; // Cairo -import type { KindedOptions as CairoKindedOptions } from '../../../../core/cairo/dist'; -export type { CommonContractOptions as CairoCommonContractOptions } from '../../../../core/cairo/dist/common-options'; -export type { RoyaltyInfoOptions as CairoRoyaltyInfoOptions } from '../../../../core/cairo/dist/set-royalty-info'; +import type { KindedOptions as CairoKindedOptions } from '../../../../../core/cairo/dist'; +export type { CommonContractOptions as CairoCommonContractOptions } from '../../../../../core/cairo/dist/common-options'; +export type { RoyaltyInfoOptions as CairoRoyaltyInfoOptions } from '../../../../../core/cairo/dist/set-royalty-info'; // Cairo-alpha -import type { KindedOptions as CairoAlphaKindedOptions } from '../../../../core/cairo_alpha/dist'; -export type { CommonContractOptions as CairoAlphaCommonContractOptions } from '../../../../core/cairo_alpha/dist/common-options'; -export type { RoyaltyInfoOptions as CairoAlphaRoyaltyInfoOptions } from '../../../../core/cairo_alpha/dist/set-royalty-info'; +import type { KindedOptions as CairoAlphaKindedOptions } from '../../../../../core/cairo_alpha/dist'; +export type { CommonContractOptions as CairoAlphaCommonContractOptions } from '../../../../../core/cairo_alpha/dist/common-options'; +export type { RoyaltyInfoOptions as CairoAlphaRoyaltyInfoOptions } from '../../../../../core/cairo_alpha/dist/set-royalty-info'; //Stellar -import type { KindedOptions as StellarKindedOptions } from '../../../../core/stellar/dist'; -import type { CommonContractOptions as StellarCommonContractOptionsBase } from '../../../../core/stellar/dist/common-options'; +import type { KindedOptions as StellarKindedOptions } from '../../../../../core/stellar/dist'; +import type { CommonContractOptions as StellarCommonContractOptionsBase } from '../../../../../core/stellar/dist/common-options'; export type StellarCommonContractOptions = Omit & { upgradeable?: false; }; // Stylus -import type { KindedOptions as StylusKindedOptions } from '../../../../core/stylus/dist'; -import type { CommonContractOptions as StylusCommonContractOptionsBase } from '../../../../core/stylus/dist/common-options'; +import type { KindedOptions as StylusKindedOptions } from '../../../../../core/stylus/dist'; +import type { CommonContractOptions as StylusCommonContractOptionsBase } from '../../../../../core/stylus/dist/common-options'; export type StylusCommonContractOptions = Omit & { access?: false }; type SolidityContractsOptions = Omit< diff --git a/packages/ui/deno.json b/packages/ui/api/ai/deno.json similarity index 74% rename from packages/ui/deno.json rename to packages/ui/api/ai/deno.json index e5823b49c..5b738b7dc 100644 --- a/packages/ui/deno.json +++ b/packages/ui/api/ai/deno.json @@ -11,7 +11,7 @@ }, "importMap": "./import_map.json", "tasks": { - "dev": "deno run --allow-all --env-file --watch --no-clear-screen scripts/deno/development-server.ts ", - "type:check": "deno check ./api --unstable-sloppy-imports" + "dev": "deno run --allow-all --env-file --watch --no-clear-screen development-server.ts ", + "type:check": "deno check ./paths/ai.ts --unstable-sloppy-imports" } } \ No newline at end of file diff --git a/packages/ui/deno.lock b/packages/ui/api/ai/deno.lock similarity index 52% rename from packages/ui/deno.lock rename to packages/ui/api/ai/deno.lock index f107df782..0b4dcdc1d 100644 --- a/packages/ui/deno.lock +++ b/packages/ui/api/ai/deno.lock @@ -2,9 +2,7 @@ "version": "3", "redirects": { "https://deno.land/std/fmt/colors.ts": "https://deno.land/std@0.224.0/fmt/colors.ts", - "https://deno.land/std/path/mod.ts": "https://deno.land/std@0.224.0/path/mod.ts", - "https://esm.sh/crypto-js@^4.2.0/enc-hex?target=denonext": "https://esm.sh/crypto-js@4.2.0/enc-hex?target=denonext", - "https://esm.sh/crypto-js@^4.2.0/sha1?target=denonext": "https://esm.sh/crypto-js@4.2.0/sha1?target=denonext" + "https://deno.land/std/path/mod.ts": "https://deno.land/std@0.224.0/path/mod.ts" }, "remote": { "https://deno.land/std@0.224.0/assert/assert.ts": "09d30564c09de846855b7b071e62b5974b001bb72a4b797958fe0660e7849834", @@ -86,106 +84,6 @@ "https://deno.land/std@0.224.0/path/windows/relative.ts": "3e1abc7977ee6cc0db2730d1f9cb38be87b0ce4806759d271a70e4997fc638d7", "https://deno.land/std@0.224.0/path/windows/resolve.ts": "8dae1dadfed9d46ff46cc337c9525c0c7d959fb400a6308f34595c45bdca1972", "https://deno.land/std@0.224.0/path/windows/to_file_url.ts": "40e560ee4854fe5a3d4d12976cef2f4e8914125c81b11f1108e127934ced502e", - "https://deno.land/std@0.224.0/path/windows/to_namespaced_path.ts": "4ffa4fb6fae321448d5fe810b3ca741d84df4d7897e61ee29be961a6aac89a4c", - "https://esm.sh/@upstash/redis@1.25.2": "b9400ffe20e12237188f35ee3658f02e273ecd1abd421106af12f6ea916c81b0", - "https://esm.sh/@upstash/redis@1.25.2/denonext/redis.mjs": "d8487c833ec520cc90f52b680b172282e91941b937bc9ea879b8347e407833cc", - "https://esm.sh/crypto-js@4.2.0/denonext/enc-hex.mjs": "d9b57ee9b036cb023e8c87f0063f616405c34f166327e6bc561ce36059eabfa6", - "https://esm.sh/crypto-js@4.2.0/denonext/sha1.mjs": "7c20a11f45d6390bfd5babfb769457ad42775bca38d140dc497e548a94f7745b", - "https://esm.sh/crypto-js@4.2.0/enc-hex?target=denonext": "e7bbfb366ad3cbea21a865f646e2dd1109398362c4779291bffb03bb6332310f", - "https://esm.sh/crypto-js@4.2.0/sha1?target=denonext": "60b6e4ce5897826e9f61dcc2a0cbf11a9431ef81cad376f7f1f2810c615e4e68", - "https://esm.sh/openai@5.13.1": "0ef5984cbbec5b8576ed2f93a37a6bd2af3d44e5b4d57a2a3c9d3db0e255774a", - "https://esm.sh/openai@5.13.1/denonext/azure.mjs": "a5f84bdea43b3d1441e66403a911493655dfe2bca8633b5f23b56f6ad0447a02", - "https://esm.sh/openai@5.13.1/denonext/client.mjs": "ef7f5b489fcdfc3e85ddced228a8757f56327b77304391f9353f6b8ca7914996", - "https://esm.sh/openai@5.13.1/denonext/core/api-promise.mjs": "f2b9f873c0693759d61ac65d3471168d23b385517aa702c49185127e3f336f9d", - "https://esm.sh/openai@5.13.1/denonext/core/error.mjs": "db7552d1a49e3af9213dc478db1b47ca1213b4ad1a2384fd32d9d6dca90eea16", - "https://esm.sh/openai@5.13.1/denonext/core/pagination.mjs": "773b932f5a5facfa153fa22c70b2d1e4d454b4b8ab19f7771a822568730770cf", - "https://esm.sh/openai@5.13.1/denonext/core/resource.mjs": "a08cd4b13a929147617d5c2678cbfccead392ef21217d7ed0a2e13926f7e2d9a", - "https://esm.sh/openai@5.13.1/denonext/core/streaming.mjs": "89040d5a51c73c3f364fccbd765f142a397e82bec2bd58600e51651436df25b6", - "https://esm.sh/openai@5.13.1/denonext/core/uploads.mjs": "2d5ec7af9e56b9914b9f5c5096d0d09c0d9ba264d912a79a645d692cccbb39b7", - "https://esm.sh/openai@5.13.1/denonext/error.mjs": "cd83291ff8b6bc4e9d31b7c2b4ee45db53545612f979db1ab5fac0b7c77e7ae3", - "https://esm.sh/openai@5.13.1/denonext/internal/errors.mjs": "7efa493ca59d198b9abe1e8d9bd4001ecee8548d46c766060bf77ca78d6493d0", - "https://esm.sh/openai@5.13.1/denonext/internal/headers.mjs": "2bfe04de2b66bbd94827b1fa21e3747db6ea9181861cbbdbdb1953bc749014d2", - "https://esm.sh/openai@5.13.1/denonext/internal/parse.mjs": "033ef4f652d5bfe4aa69599fa363e3b163db898baf89ab873090c3016b8c4fdb", - "https://esm.sh/openai@5.13.1/denonext/internal/shims.mjs": "78d5c4eccf71378816ec4da183529ba8f63ee833e2808e79c9ffabab2a28c595", - "https://esm.sh/openai@5.13.1/denonext/internal/tslib.mjs": "e7182a864434772816b3d27b742d35130efcff76056dbe28b2b74101c6e09285", - "https://esm.sh/openai@5.13.1/denonext/internal/uploads.mjs": "2d85efe5f7e0597d8246759d38a79c4cc6663ba09982f700cff376410ef1c0bf", - "https://esm.sh/openai@5.13.1/denonext/internal/utils.mjs": "672514567bc3da8b1f7cd691116fec9dd60b5ea9e09b4ac6287fef6ce47afa8b", - "https://esm.sh/openai@5.13.1/denonext/internal/utils/bytes.mjs": "c30b8941a4aa532f38a0b72287f8a6318f86bdbd30c3e7c908567b3e1c8fa805", - "https://esm.sh/openai@5.13.1/denonext/internal/utils/env.mjs": "078c604a2a55246be7c739ee608b6e6cb70b4491c5382fba721b4497c67f9c8f", - "https://esm.sh/openai@5.13.1/denonext/internal/utils/log.mjs": "0965efa431861632a667bc2c4d32f41a6f38eb5b66d8269b20bbac492aee0ee9", - "https://esm.sh/openai@5.13.1/denonext/internal/utils/path.mjs": "714a975f77667499f36a155b30bb52b900f37e4aabb5a99a46a028204a5e0afe", - "https://esm.sh/openai@5.13.1/denonext/internal/utils/sleep.mjs": "2597885e3620eeef19721533d83c2f1e747bc88e5ae3dc7cd2aa1e0742c9458c", - "https://esm.sh/openai@5.13.1/denonext/internal/utils/uuid.mjs": "c40e5330d84a5c739383334cc0e26e084bef58f09572735b9f8dd0d434d0770b", - "https://esm.sh/openai@5.13.1/denonext/internal/utils/values.mjs": "305a4e3bc6b2c6bcc6c3f417004148093a2e035fa8d321b0634c3f12d86427ae", - "https://esm.sh/openai@5.13.1/denonext/lib/AbstractChatCompletionRunner.mjs": "e2ca6bf5110b8b4b28d1a1d31468cd300368bae400e72a52d0a020854297f44f", - "https://esm.sh/openai@5.13.1/denonext/lib/EventStream.mjs": "214937b2afc3bc5542b96b1a00060054ff1af3cef36593035a8bf9bc9c781c42", - "https://esm.sh/openai@5.13.1/denonext/lib/RunnableFunction.mjs": "aef7b3beccc10adb6870659c25669aa4451f03670b163b88d97ee1aa27e7625e", - "https://esm.sh/openai@5.13.1/denonext/lib/chatCompletionUtils.mjs": "a92757b94fc9b19b688a5acb71b38df7164141e3b54240b4cd79cedea26bcec5", - "https://esm.sh/openai@5.13.1/denonext/lib/parser.mjs": "3a696f5568b5634b00ce1d91afc7eadf1160612bfa51e0102d8050444ce7d83a", - "https://esm.sh/openai@5.13.1/denonext/openai.mjs": "ce1bc4e1a91d8f98cb60f5d8e8ec6420a303115d77308573f5989d99df0aeaf7", - "https://esm.sh/openai@5.13.1/denonext/resources/audio/audio.mjs": "15035939336dc5d7a67619e4ae7e0537dad039e5eb61f302c451d73a0244b0ec", - "https://esm.sh/openai@5.13.1/denonext/resources/batches.mjs": "0b76a5f8e6804cf9e49e4e7260df7ee94faf2c12735bd77280e63a46f15fe5d9", - "https://esm.sh/openai@5.13.1/denonext/resources/beta/beta.mjs": "a7a7449874d7fd543314f31106c737178532bb1ba5b78c7b8a046726b2efa062", - "https://esm.sh/openai@5.13.1/denonext/resources/chat/chat.mjs": "b1bbdfc35994fd5a3d40a7691b1a046d173b7cdccff774062c4a3916aee7e610", - "https://esm.sh/openai@5.13.1/denonext/resources/chat/completions/index.mjs": "489a67b461a0e7633edf2107dc213bc41d6814053cbec2760f15b454cb78ffc8", - "https://esm.sh/openai@5.13.1/denonext/resources/completions.mjs": "eb12a46f01c0b12bcf86a08aa114e2116d271aabdd151b776d44d8e78e360ec5", - "https://esm.sh/openai@5.13.1/denonext/resources/containers/containers.mjs": "0a30f5b2acfa5c6469c7ff4a0857aebd98d631b616440e05d0b7f0422aa97513", - "https://esm.sh/openai@5.13.1/denonext/resources/embeddings.mjs": "7e472c96e4b2f0d1b1f11577dfaed2fa375ebb13284458583fba97ca7c297fac", - "https://esm.sh/openai@5.13.1/denonext/resources/evals/evals.mjs": "6e717414ff8dafe8712bda64df50e3533ef1580121470227122d20f45ba4eb47", - "https://esm.sh/openai@5.13.1/denonext/resources/files.mjs": "0dd7368a1715a004e708aa2c5f8e220d157cc93b80928e5ad8efe6222191bd1f", - "https://esm.sh/openai@5.13.1/denonext/resources/fine-tuning/fine-tuning.mjs": "bdd625a72c3f5b6da5b91b2ca082c1f6785f8f5c1f8f1b51c1b4c22fc0347cd6", - "https://esm.sh/openai@5.13.1/denonext/resources/graders/graders.mjs": "2b88c29d8ff51a57b167f01f068c96ee87a6a35e1fb610290f0b8a0455c01c32", - "https://esm.sh/openai@5.13.1/denonext/resources/images.mjs": "e6c1f3e7f2e3723ffe01cba8e3ab0d520bffd775cfb283f721b1f3fc1c00dd32", - "https://esm.sh/openai@5.13.1/denonext/resources/index.mjs": "b3d2cf61c18fddf26a39b722fed58ef5a2bcf52957a34711072174ba9de20da6", - "https://esm.sh/openai@5.13.1/denonext/resources/models.mjs": "39a7e848a14b53bfe5930ec726dc10f2837ffe318e2d25fa2419b63ec80d3651", - "https://esm.sh/openai@5.13.1/denonext/resources/moderations.mjs": "c9c99b985109090bd7bbb623db0fd20f539a2027bf531ca762830a52dfcbcad0", - "https://esm.sh/openai@5.13.1/denonext/resources/responses/responses.mjs": "0a091a55c0dcc830a68b91d5741614c180be96687f71c2726d55b805a0764673", - "https://esm.sh/openai@5.13.1/denonext/resources/uploads/uploads.mjs": "b19b323a36618003ada0b0168b33662f43d67820baf96a6388f3ecc2ccf76a54", - "https://esm.sh/openai@5.13.1/denonext/resources/vector-stores/vector-stores.mjs": "92dfd761eb4d88bd2ae78ffd2e8d04f6d6067b1e22946f56310e52ac8bbc8518", - "https://esm.sh/openai@5.13.1/denonext/resources/webhooks.mjs": "20db2401be99bbc5225a4e7c90db2f4e7d5bb7e29700e8041f2244c200a902ed", - "https://esm.sh/openai@5.13.1/denonext/streaming.mjs": "9eb0a252d1fb6e345b1b1a802b1e98dd61f063b4f4929d9673c9d8dea1c62702", - "https://esm.sh/openai@5.13.1/denonext/version.mjs": "882faa862a3c0b55f59198719bd3b66cd7d1e0934fe4ce571ff7664b343e7f73", - "https://esm.sh/openai@5.13.1/lib/ChatCompletionStream.mjs": "5e893f12c80efe27ea3585280237c97dc5f77ff93e13a4b7ff36dc9be945970b" - }, - "workspace": { - "packageJson": { - "dependencies": [ - "npm:@rollup/plugin-alias@^5.0.0", - "npm:@rollup/plugin-commonjs@^28.0.0", - "npm:@rollup/plugin-json@^6.0.0", - "npm:@rollup/plugin-node-resolve@^16.0.0", - "npm:@rollup/plugin-replace@^6.0.0", - "npm:@rollup/plugin-typescript@^12.0.0", - "npm:@types/file-saver@^2.0.1", - "npm:@types/node@^20.0.0", - "npm:@types/resize-observer-browser@^0.1.5", - "npm:@types/semver@^7.5.7", - "npm:@upstash/redis@1.25.2", - "npm:autoprefixer@^10.4.2", - "npm:file-saver@^2.0.5", - "npm:highlight.js@^11.0.0", - "npm:highlightjs-cairo@^0.4.0", - "npm:highlightjs-solidity@^2.0.0", - "npm:openai@5.13.1", - "npm:path-browserify@^1.0.1", - "npm:postcss-load-config@^6.0.0", - "npm:postcss@^8.2.8", - "npm:rollup-plugin-livereload@^2.0.0", - "npm:rollup-plugin-styles@^4.0.0", - "npm:rollup-plugin-svelte@^7.0.0", - "npm:rollup-plugin-terser@^7.0.0", - "npm:rollup@^4.0.0", - "npm:semver@^7.6.0", - "npm:sirv-cli@^3.0.0", - "npm:svelte-check@^3.0.1", - "npm:svelte-preprocess@^5.0.0", - "npm:svelte@^3.55.0", - "npm:tailwindcss@^3.0.15", - "npm:tippy.js@^6.3.1", - "npm:tslib@^2.0.0", - "npm:typescript@^5.0.0", - "npm:util@^0.12.4" - ] - } + "https://deno.land/std@0.224.0/path/windows/to_namespaced_path.ts": "4ffa4fb6fae321448d5fe810b3ca741d84df4d7897e61ee29be961a6aac89a4c" } } diff --git a/packages/ui/scripts/deno/development-server.ts b/packages/ui/api/ai/development-server.ts similarity index 66% rename from packages/ui/scripts/deno/development-server.ts rename to packages/ui/api/ai/development-server.ts index 9d5239865..56cbf0db3 100644 --- a/packages/ui/scripts/deno/development-server.ts +++ b/packages/ui/api/ai/development-server.ts @@ -1,8 +1,20 @@ /// /// -import './log.ts'; -import { getEnvironmentVariableOr } from '../../api/utils/env.ts'; +import './utils/log.ts'; +import { getEnvironmentVariableOr } from './utils/env.ts'; import { dirname } from 'https://deno.land/std/path/mod.ts'; +import { join } from 'https://deno.land/std@0.224.0/path/mod.ts'; + +const listAll = async (dirPath: string) => { + for await (const entry of Deno.readDir(dirPath)) { + const fullPath = join(dirPath, entry.name); + console.log(fullPath); + + if (entry.isDirectory) { + await listAll(fullPath); + } + } +}; const developmentCors = new Response(undefined, { status: 200, @@ -21,8 +33,12 @@ Deno.serve( const calledEndpoint = new URL(request.url).pathname; try { + console.log(`file://${dirname(Deno.cwd())}/ai/paths/${calledEndpoint}.ts`); + + await listAll('.'); + // Dynamically import the route handler - const module = await import(`file://${dirname(Deno.cwd())}/ui/api${calledEndpoint}.ts`); + const module = await import(`file://${dirname(Deno.cwd())}/ai/paths${calledEndpoint}.ts`); if (module.default) { return module.default(request); diff --git a/packages/ui/import_map.json b/packages/ui/api/ai/import_map.json similarity index 100% rename from packages/ui/import_map.json rename to packages/ui/api/ai/import_map.json diff --git a/packages/ui/api/ai.ts b/packages/ui/api/ai/paths/ai.ts similarity index 71% rename from packages/ui/api/ai.ts rename to packages/ui/api/ai/paths/ai.ts index 5cf9e5ff4..b264204d5 100644 --- a/packages/ui/api/ai.ts +++ b/packages/ui/api/ai/paths/ai.ts @@ -1,19 +1,19 @@ -import * as solidityFunctions from './ai-assistant/function-definitions/solidity.ts'; -import * as polkadotFunctions from './ai-assistant/function-definitions/polkadot.ts'; -import * as cairoFunctions from './ai-assistant/function-definitions/cairo.ts'; -import * as cairoAlphaFunctions from './ai-assistant/function-definitions/cairo-alpha.ts'; -import * as stellarFunctions from './ai-assistant/function-definitions/stellar.ts'; -import * as stylusFunctions from './ai-assistant/function-definitions/stylus.ts'; -import { saveChatInRedisIfDoesNotExist } from './services/redis.ts'; -import type { ChatMessages } from './services/open-ai.ts'; -import { createOpenAiCompletionStream } from './services/open-ai.ts'; -import type { AiChatBodyRequest } from './ai-assistant/types/assistant.ts'; -import type { SupportedLanguage } from './ai-assistant/types/languages.ts'; +import * as solidityFunctions from '../ai-assistant/function-definitions/solidity.ts'; +import * as polkadotFunctions from '../ai-assistant/function-definitions/polkadot.ts'; +import * as cairoFunctions from '../ai-assistant/function-definitions/cairo.ts'; +import * as cairoAlphaFunctions from '../ai-assistant/function-definitions/cairo-alpha.ts'; +import * as stellarFunctions from '../ai-assistant/function-definitions/stellar.ts'; +import * as stylusFunctions from '../ai-assistant/function-definitions/stylus.ts'; +import { saveChatInRedisIfDoesNotExist } from '../services/redis.ts'; +import type { ChatMessages } from '../services/open-ai.ts'; +import { createOpenAiCompletionStream } from '../services/open-ai.ts'; +import type { AiChatBodyRequest } from '../ai-assistant/types/assistant.ts'; +import type { SupportedLanguage } from '../ai-assistant/types/languages.ts'; import type { AllContractsAIFunctionDefinitions, SimpleAiFunctionDefinition, -} from './ai-assistant/types/function-definition.ts'; -import { Cors } from './utils/cors.ts'; +} from '../ai-assistant/types/function-definition.ts'; +import { Cors } from '../utils/cors.ts'; const getFunctionsContext = ( language: TLanguage, diff --git a/packages/ui/api/services/dev-mocks/redis.ts b/packages/ui/api/ai/services/dev-mocks/redis.ts similarity index 100% rename from packages/ui/api/services/dev-mocks/redis.ts rename to packages/ui/api/ai/services/dev-mocks/redis.ts diff --git a/packages/ui/api/services/open-ai.ts b/packages/ui/api/ai/services/open-ai.ts similarity index 100% rename from packages/ui/api/services/open-ai.ts rename to packages/ui/api/ai/services/open-ai.ts diff --git a/packages/ui/api/services/redis.ts b/packages/ui/api/ai/services/redis.ts similarity index 100% rename from packages/ui/api/services/redis.ts rename to packages/ui/api/ai/services/redis.ts diff --git a/packages/ui/api/utils/cors.ts b/packages/ui/api/ai/utils/cors.ts similarity index 100% rename from packages/ui/api/utils/cors.ts rename to packages/ui/api/ai/utils/cors.ts diff --git a/packages/ui/api/utils/env.ts b/packages/ui/api/ai/utils/env.ts similarity index 100% rename from packages/ui/api/utils/env.ts rename to packages/ui/api/ai/utils/env.ts diff --git a/packages/ui/scripts/deno/log.ts b/packages/ui/api/ai/utils/log.ts similarity index 100% rename from packages/ui/scripts/deno/log.ts rename to packages/ui/api/ai/utils/log.ts diff --git a/packages/ui/api/docker-compose.yaml b/packages/ui/api/docker-compose.yaml new file mode 100644 index 000000000..bbb053a28 --- /dev/null +++ b/packages/ui/api/docker-compose.yaml @@ -0,0 +1,50 @@ +services: + stellar-api: + container_name: stellar-api + build: + context: ./stellar + dockerfile: Dockerfile.dev + volumes: + - ./stellar:/usr/src/stellar-api + - stellar-cargo-target:/usr/src/stellar-api/target + - stellar-cargo-cache:/usr/local/cargo/registry + - stellar-cargo-git:/usr/local/cargo/git + - stellar-tmp:/tmp + environment: + - RUSTFLAGS=-C debuginfo=0 + - CFLAGS=-g0 + - CXXFLAGS=-g0 + env_file: + - ./stellar/.env + ports: + - "8888:8888" + command: ["cargo", "watch", "-x", "run"] + tty: true + stdin_open: true + + deno-api: + container_name: deno-api + build: + context: ../.. + dockerfile: ui/api/ai/Dockerfile.dev + volumes: + - ./ai:/app/ui/api/ai + - ../../common:/app/common + - deno-cache:/deno-dir + env_file: + - ./ai/.env + environment: + - DENO_DIR=/deno-dir + - ENV=dev + ports: + - "3000:3000" + command: ["deno", "task", "dev"] + tty: true + stdin_open: true + +volumes: + stellar-cargo-target: + stellar-cargo-cache: + stellar-cargo-git: + stellar-tmp: + deno-cache: diff --git a/packages/ui/api/stellar/.dockerignore b/packages/ui/api/stellar/.dockerignore new file mode 100644 index 000000000..4d4b65263 --- /dev/null +++ b/packages/ui/api/stellar/.dockerignore @@ -0,0 +1,6 @@ +target +.git +.DS_Store + +.env +.env.* \ No newline at end of file diff --git a/packages/ui/api/stellar/.env.example b/packages/ui/api/stellar/.env.example new file mode 100644 index 000000000..fbfb3aa7b --- /dev/null +++ b/packages/ui/api/stellar/.env.example @@ -0,0 +1,2 @@ +RUST_LOG=debug +WIZARD_ORIGIN=http://localhost:8080 \ No newline at end of file diff --git a/packages/ui/api/stellar/Cargo.lock b/packages/ui/api/stellar/Cargo.lock new file mode 100644 index 000000000..63310e4e9 --- /dev/null +++ b/packages/ui/api/stellar/Cargo.lock @@ -0,0 +1,2384 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "actix-codec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a" +dependencies = [ + "bitflags", + "bytes", + "futures-core", + "futures-sink", + "memchr", + "pin-project-lite", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "actix-cors" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daa239b93927be1ff123eebada5a3ff23e89f0124ccb8609234e5103d5a5ae6d" +dependencies = [ + "actix-utils", + "actix-web", + "derive_more", + "futures-util", + "log", + "once_cell", + "smallvec", +] + +[[package]] +name = "actix-governor" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a0cb8586d3fa368d00ef643e8ef77f5d3d5dfe5c7b333415a556bc12eb1c41a" +dependencies = [ + "actix-http", + "actix-web", + "futures", + "governor", +] + +[[package]] +name = "actix-http" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44dfe5c9e0004c623edc65391dfd51daa201e7e30ebd9c9bedf873048ec32bc2" +dependencies = [ + "actix-codec", + "actix-rt", + "actix-service", + "actix-utils", + "base64", + "bitflags", + "brotli", + "bytes", + "bytestring", + "derive_more", + "encoding_rs", + "flate2", + "foldhash", + "futures-core", + "h2", + "http", + "httparse", + "httpdate", + "itoa", + "language-tags", + "local-channel", + "mime", + "percent-encoding", + "pin-project-lite", + "rand", + "sha1", + "smallvec", + "tokio", + "tokio-util", + "tracing", + "zstd", +] + +[[package]] +name = "actix-macros" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "actix-router" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13d324164c51f63867b57e73ba5936ea151b8a41a1d23d1031eeb9f70d0236f8" +dependencies = [ + "bytestring", + "cfg-if", + "http", + "regex", + "regex-lite", + "serde", + "tracing", +] + +[[package]] +name = "actix-rt" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24eda4e2a6e042aa4e55ac438a2ae052d3b5da0ecf83d7411e1a368946925208" +dependencies = [ + "futures-core", + "tokio", +] + +[[package]] +name = "actix-server" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a65064ea4a457eaf07f2fba30b4c695bf43b721790e9530d26cb6f9019ff7502" +dependencies = [ + "actix-rt", + "actix-service", + "actix-utils", + "futures-core", + "futures-util", + "mio", + "socket2 0.5.10", + "tokio", + "tracing", +] + +[[package]] +name = "actix-service" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e46f36bf0e5af44bdc4bdb36fbbd421aa98c79a9bce724e1edeb3894e10dc7f" +dependencies = [ + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "actix-utils" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88a1dcdff1466e3c2488e1cb5c36a71822750ad43839937f85d2f4d9f8b705d8" +dependencies = [ + "local-waker", + "pin-project-lite", +] + +[[package]] +name = "actix-web" +version = "4.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a597b77b5c6d6a1e1097fddde329a83665e25c5437c696a3a9a4aa514a614dea" +dependencies = [ + "actix-codec", + "actix-http", + "actix-macros", + "actix-router", + "actix-rt", + "actix-server", + "actix-service", + "actix-utils", + "actix-web-codegen", + "bytes", + "bytestring", + "cfg-if", + "cookie", + "derive_more", + "encoding_rs", + "foldhash", + "futures-core", + "futures-util", + "impl-more", + "itoa", + "language-tags", + "log", + "mime", + "once_cell", + "pin-project-lite", + "regex", + "regex-lite", + "serde", + "serde_json", + "serde_urlencoded", + "smallvec", + "socket2 0.5.10", + "time", + "tracing", + "url", +] + +[[package]] +name = "actix-web-codegen" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f591380e2e68490b5dfaf1dd1aa0ebe78d84ba7067078512b4ea6e4492d622b8" +dependencies = [ + "actix-router", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "alloc-no-stdlib" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" + +[[package]] +name = "alloc-stdlib" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" +dependencies = [ + "alloc-no-stdlib", +] + +[[package]] +name = "anstream" +version = "0.6.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.59.0", +] + +[[package]] +name = "arbitrary" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" +dependencies = [ + "derive_arbitrary", +] + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "backtrace" +version = "0.3.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets 0.52.6", +] + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bitflags" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "brotli" +version = "8.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9991eea70ea4f293524138648e41ee89b0b2b12ddef3b255effa43c8056e0e0d" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "874bb8112abecc98cbd6d81ea4fa7e94fb9449648c93cc89aa40c81c24d7de03" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + +[[package]] +name = "bstr" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "bumpalo" +version = "3.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + +[[package]] +name = "bytes" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" + +[[package]] +name = "bytestring" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e465647ae23b2823b0753f50decb2d5a86d2bb2cac04788fafd1f80e45378e5f" +dependencies = [ + "bytes", +] + +[[package]] +name = "bzip2" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bea8dcd42434048e4f7a304411d9273a411f647446c1234a65ce0554923f4cff" +dependencies = [ + "libbz2-rs-sys", +] + +[[package]] +name = "cc" +version = "1.2.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "deec109607ca693028562ed836a5f1c4b8bd77755c4e132fc5ce11b0b6211ae7" +dependencies = [ + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + +[[package]] +name = "constant_time_eq" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" + +[[package]] +name = "cookie" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb" +dependencies = [ + "percent-encoding", + "time", + "version_check", +] + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crc" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "dashmap" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "deflate64" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da692b8d1080ea3045efaab14434d40468c3d8657e42abddfffca87b428f4c1b" + +[[package]] +name = "deranged" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "derive_arbitrary" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "derive_more" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "unicode-xid", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "dotenvy" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "env_filter" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "jiff", + "log", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" +dependencies = [ + "libc", + "windows-sys 0.60.2", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "flate2" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" +dependencies = [ + "crc32fast", + "libz-rs-sys", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-timer" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", + "wasm-bindgen", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "globset" +version = "0.4.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54a1028dfc5f5df5da8a56a73e6c153c9a9708ec57232470703592a3f18e49f5" +dependencies = [ + "aho-corasick", + "bstr", + "log", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "governor" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be93b4ec2e4710b04d9264c0c7350cdd62a8c20e5e4ac732552ebb8f0debe8eb" +dependencies = [ + "cfg-if", + "dashmap", + "futures-sink", + "futures-timer", + "futures-util", + "getrandom", + "no-std-compat", + "nonzero_ext", + "parking_lot", + "portable-atomic", + "quanta", + "rand", + "smallvec", + "spinning_top", + "web-time", +] + +[[package]] +name = "h2" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0beca50380b1fc32983fc1cb4587bfa4bb9e78fc259aad4a0032d2080309222d" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hashbrown" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "icu_collections" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" + +[[package]] +name = "icu_properties" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "potential_utf", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" + +[[package]] +name = "icu_provider" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +dependencies = [ + "displaydoc", + "icu_locale_core", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "idna" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "impl-more" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8a5a9a0ff0086c7a148acb942baaabeadf9504d10400b5a05645853729b9cd2" + +[[package]] +name = "indexmap" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" +dependencies = [ + "equivalent", + "hashbrown 0.15.4", +] + +[[package]] +name = "inout" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +dependencies = [ + "generic-array", +] + +[[package]] +name = "io-uring" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4" +dependencies = [ + "bitflags", + "cfg-if", + "libc", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "jiff" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be1f93b8b1eb69c77f24bbb0afdf66f54b632ee39af40ca21c4365a1d7347e49" +dependencies = [ + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde", +] + +[[package]] +name = "jiff-static" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "jobserver" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" +dependencies = [ + "getrandom", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "language-tags" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" + +[[package]] +name = "libbz2-rs-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c4a545a15244c7d945065b5d392b2d2d7f21526fba56ce51467b06ed445e8f7" + +[[package]] +name = "libc" +version = "0.2.175" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" + +[[package]] +name = "libz-rs-sys" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "172a788537a2221661b480fee8dc5f96c580eb34fa88764d3205dc356c7e4221" +dependencies = [ + "zlib-rs", +] + +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + +[[package]] +name = "litemap" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" + +[[package]] +name = "local-channel" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6cbc85e69b8df4b8bb8b89ec634e7189099cea8927a276b7384ce5488e53ec8" +dependencies = [ + "futures-core", + "futures-sink", + "local-waker", +] + +[[package]] +name = "local-waker" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d873d7c67ce09b42110d801813efbc9364414e356be9935700d368351657487" + +[[package]] +name = "lock_api" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" + +[[package]] +name = "lzma-rust2" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c60a23ffb90d527e23192f1246b14746e2f7f071cb84476dd879071696c18a4a" +dependencies = [ + "crc", + "sha2", +] + +[[package]] +name = "memchr" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +dependencies = [ + "libc", + "log", + "wasi 0.11.1+wasi-snapshot-preview1", + "windows-sys 0.59.0", +] + +[[package]] +name = "no-std-compat" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c" + +[[package]] +name = "nonzero_ext" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38bf9645c8b145698bb0b18a4637dcacbc421ea49bef2317e4fd8065a387cf21" + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "object" +version = "0.36.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" + +[[package]] +name = "parking_lot" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.6", +] + +[[package]] +name = "pbkdf2" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" +dependencies = [ + "digest", + "hmac", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "portable-atomic" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" + +[[package]] +name = "portable-atomic-util" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "potential_utf" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +dependencies = [ + "zerovec", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppmd-rust" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c834641d8ad1b348c9ee86dec3b9840d805acd5f24daa5f90c788951a52ff59b" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro2" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quanta" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3ab5a9d756f0d97bdc89019bd2e4ea098cf9cde50ee7564dde6b81ccc8f06c7" +dependencies = [ + "crossbeam-utils", + "libc", + "once_cell", + "raw-cpuid", + "wasi 0.11.1+wasi-snapshot-preview1", + "web-sys", + "winapi", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom", +] + +[[package]] +name = "raw-cpuid" +version = "11.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6df7ab838ed27997ba19a4664507e6f82b41fe6e20be42929332156e5e85146" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_syscall" +version = "0.5.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-lite" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "rustc-demangle" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" + +[[package]] +name = "rustix" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.60.2", +] + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.141" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b9eff21ebe718216c6ec64e1d9ac57087aad11efc64e32002bce4a0d4c03d3" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook-registry" +version = "1.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" +dependencies = [ + "libc", +] + +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "slab" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "socket2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "socket2" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "spinning_top" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d96d2d1d716fb500937168cc09353ffdc7a012be8475ac7308e1bdf0e3923300" +dependencies = [ + "lock_api", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "stellar-api" +version = "0.1.0" +dependencies = [ + "actix-cors", + "actix-governor", + "actix-web", + "dotenvy", + "env_logger", + "globset", + "libc", + "log", + "tempfile", + "walkdir", + "zip", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "2.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tempfile" +version = "3.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15b61f8f20e3a6f7e0649d825294eaf317edce30f82cf6026e7e4cb9222a7d1e" +dependencies = [ + "fastrand", + "getrandom", + "once_cell", + "rustix", + "windows-sys 0.60.2", +] + +[[package]] +name = "time" +version = "0.3.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" + +[[package]] +name = "time-macros" +version = "0.2.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tinystr" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tokio" +version = "1.47.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" +dependencies = [ + "backtrace", + "bytes", + "io-uring", + "libc", + "mio", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "slab", + "socket2 0.6.0", + "windows-sys 0.59.0", +] + +[[package]] +name = "tokio-util" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +dependencies = [ + "once_cell", +] + +[[package]] +name = "typenum" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "url" +version = "2.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.3", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags", +] + +[[package]] +name = "writeable" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" + +[[package]] +name = "yoke" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zerotrie" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zip" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f852905151ac8d4d06fdca66520a661c09730a74c6d4e2b0f27b436b382e532" +dependencies = [ + "aes", + "arbitrary", + "bzip2", + "constant_time_eq", + "crc32fast", + "deflate64", + "flate2", + "getrandom", + "hmac", + "indexmap", + "lzma-rust2", + "memchr", + "pbkdf2", + "ppmd-rust", + "sha1", + "time", + "zeroize", + "zopfli", + "zstd", +] + +[[package]] +name = "zlib-rs" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "626bd9fa9734751fc50d6060752170984d7053f5a39061f524cda68023d4db8a" + +[[package]] +name = "zopfli" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edfc5ee405f504cd4984ecc6f14d02d55cfda60fa4b689434ef4102aae150cd7" +dependencies = [ + "bumpalo", + "crc32fast", + "log", + "simd-adler32", +] + +[[package]] +name = "zstd" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.15+zstd.1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/packages/ui/api/stellar/Cargo.toml b/packages/ui/api/stellar/Cargo.toml new file mode 100644 index 000000000..32679a418 --- /dev/null +++ b/packages/ui/api/stellar/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "stellar-api" +version = "0.1.0" +edition = "2021" + + +[dependencies] +actix-web = "4.11.0" +actix-cors = "0.7.1" +actix-governor = "0.8" +env_logger = "0.11.8" +dotenvy = "0.15.7" +log = "0.4.28" +zip = "^5.1.1" +walkdir = "^2.5.0" +tempfile = "^3.21.0" +globset = "^0.4.16" +libc = "^0.2.175" + +[package.metadata.tools] +stellar_cli = "23.0.1" +stellar_scaffold_cli = "0.0.8" + +[[bin]] +name = "stellar-api" +path = "src/main.rs" diff --git a/packages/ui/api/stellar/Dockerfile.dev b/packages/ui/api/stellar/Dockerfile.dev new file mode 100644 index 000000000..ebd42b23c --- /dev/null +++ b/packages/ui/api/stellar/Dockerfile.dev @@ -0,0 +1,42 @@ +FROM rust:latest + +WORKDIR /usr/src/stellar-api + +RUN apt-get update && apt-get install -y \ + build-essential \ + pkg-config \ + libssl-dev \ + libdbus-1-dev \ + libudev-dev \ + libusb-1.0-0-dev \ + curl \ + jq \ + gdb\ + lldb \ + && rm -rf /var/lib/apt/lists/* + +ENV CFLAGS=-g0 \ + CXXFLAGS=-g0 + +RUN mkdir -p /opt/tmp && chmod 1777 /opt/tmp + +RUN cargo install cargo-watch + +RUN rustup update \ + && rustup target add wasm32v1-none + +COPY Cargo.toml Cargo.lock ./ +RUN cargo fetch + +# Install CLI tools with versions pinned from Cargo metadata +RUN set -eux; \ + STELLAR_CLI_VERSION=$(cargo metadata -q --format-version=1 | jq -r '.packages[] | select(.name=="stellar-api") | .metadata.tools.stellar_cli'); \ + TMPDIR=/opt/tmp cargo install --locked stellar-cli --version "${STELLAR_CLI_VERSION}" -j 1 + +RUN set -eux; \ + STELLAR_SCAFFOLD_CLI_VERSION=$(cargo metadata -q --format-version=1 | jq -r '.packages[] | select(.name=="stellar-api") | .metadata.tools.stellar_scaffold_cli'); \ + TMPDIR=/opt/tmp cargo install --locked stellar-scaffold-cli --version "${STELLAR_SCAFFOLD_CLI_VERSION}" -j 1 + +EXPOSE 8888 + +CMD ["cargo", "watch", "-x", "run"] diff --git a/packages/ui/api/stellar/Dockerfile.prod b/packages/ui/api/stellar/Dockerfile.prod new file mode 100644 index 000000000..344ca1b50 --- /dev/null +++ b/packages/ui/api/stellar/Dockerfile.prod @@ -0,0 +1,96 @@ +FROM rust:bookworm AS builder +ENV DEBIAN_FRONTEND=noninteractive +ENV TMPDIR=/opt/tmp +RUN mkdir -p /opt/tmp /opt/target +ENV CARGO_TARGET_DIR=/opt/target + +WORKDIR /usr/src/stellar-api + +RUN apt-get update && apt-get install -y --no-install-recommends \ + build-essential pkg-config libssl-dev libdbus-1-dev libudev-dev libusb-1.0-0-dev ca-certificates jq \ + && rm -rf /var/lib/apt/lists/* + +RUN rustup update stable && rustup target add wasm32v1-none + +COPY Cargo.toml Cargo.lock ./ +RUN --mount=type=cache,target=/usr/local/cargo/registry \ + --mount=type=cache,target=/usr/local/cargo/git \ + cargo fetch + +# Install CLI tools with versions pinned from Cargo metadata +RUN set -eux; \ + STELLAR_CLI_VERSION=$(cargo metadata -q --format-version=1 | jq -r '.packages[] | select(.name=="stellar-api") | .metadata.tools.stellar_cli'); \ + TMPDIR=/opt/tmp cargo install --locked stellar-cli --version "${STELLAR_CLI_VERSION}" -j 1 + +RUN set -eux; \ + STELLAR_SCAFFOLD_CLI_VERSION=$(cargo metadata -q --format-version=1 | jq -r '.packages[] | select(.name=="stellar-api") | .metadata.tools.stellar_scaffold_cli'); \ + TMPDIR=/opt/tmp cargo install --locked stellar-scaffold-cli --version "${STELLAR_SCAFFOLD_CLI_VERSION}" -j 1 + +COPY . . +RUN TMPDIR=/opt/tmp cargo build --release + +RUN strip /opt/target/release/stellar-api || true + +FROM rust:bookworm AS runtime +ENV DEBIAN_FRONTEND=noninteractive +WORKDIR /usr/local/bin + +RUN apt-get purge -y --auto-remove \ + build-essential pkg-config libssl-dev +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates libssl3 libdbus-1-3 libudev1 libusb-1.0-0 \ + && rm -rf /var/lib/apt/lists/* + +RUN useradd -u 10001 -m -s /usr/sbin/nologin appuser + +COPY --chown=appuser:appuser --from=builder /opt/target/release/stellar-api /usr/local/bin/stellar-api +COPY --from=builder /usr/local/cargo/bin/stellar /usr/local/bin/stellar +COPY --from=builder /usr/local/cargo/bin/stellar-scaffold /usr/local/bin/stellar-scaffold +RUN chmod 0755 /usr/local/bin/stellar-api /usr/local/bin/stellar /usr/local/bin/stellar-scaffold + +ENV CARGO_HOME=/home/appuser/.cargo +ENV RUSTUP_HOME=/home/appuser/.rustup +ENV PATH=/usr/local/cargo/bin:/usr/local/rustup/toolchains/stable-x86_64-unknown-linux-gnu/bin:$PATH + +RUN mkdir -p $CARGO_HOME $RUSTUP_HOME && chown -R appuser:appuser /home/appuser + +USER appuser + +EXPOSE 8888 +ENV RUST_LOG=info + +ENTRYPOINT ["stellar-api"] + +# ENV DEBIAN_FRONTEND=noninteractive +# WORKDIR /usr/local/bin + +# RUN apt-get update && apt-get install -y --no-install-recommends \ +# ca-certificates libssl3 libdbus-1-3 libudev1 libusb-1.0-0 \ +# && rm -rf /var/lib/apt/lists/* + +# RUN useradd -u 10001 -m -s /usr/sbin/nologin appuser + +# COPY --chown=appuser:appuser --from=builder /opt/target/release/stellar-api /usr/local/bin/stellar-api + +# COPY --from=builder /usr/local/cargo/bin/stellar /usr/local/bin/stellar +# COPY --from=builder /usr/local/cargo/bin/stellar-scaffold /usr/local/bin/stellar-scaffold +# RUN chmod 0755 /usr/local/bin/stellar-api /usr/local/bin/stellar /usr/local/bin/stellar-scaffold + +# ENV CARGO_HOME=/home/appuser/.cargo +# ENV RUSTUP_HOME=/home/appuser/.rustup +# ENV PATH=/home/appuser/.cargo/bin:$PATH + +# COPY --from=builder /usr/local/cargo/ $CARGO_HOME +# COPY --from=builder /usr/local/rustup/ $RUSTUP_HOME + +# RUN rm -rf /usr/local/cargo/registry /usr/local/cargo/git + +# RUN mkdir -p $CARGO_HOME $RUSTUP_HOME && chown -R appuser:appuser /home/appuser + +# USER appuser + +# EXPOSE 8888 + +# ENV RUST_LOG=info + +# ENTRYPOINT ["stellar-api"] diff --git a/packages/ui/api/stellar/README.md b/packages/ui/api/stellar/README.md new file mode 100644 index 000000000..695af8104 --- /dev/null +++ b/packages/ui/api/stellar/README.md @@ -0,0 +1,19 @@ + # Stellar Backend (Actix-web) + + This is a minimal "Hello, world!" HTTP service built with Rust and Actix-web. + + ## Local Run + + ```bash + cd packages/ui/api/stellar + cargo run --release + ``` + + The server listens on port 8888. + + ## Docker + + ```bash + docker build -t stellar packages/ui/api/stellar + docker run -p 8888:8888 stellar + ``` \ No newline at end of file diff --git a/packages/ui/api/stellar/rustfmt.toml b/packages/ui/api/stellar/rustfmt.toml new file mode 100644 index 000000000..4e5f2bf9c --- /dev/null +++ b/packages/ui/api/stellar/rustfmt.toml @@ -0,0 +1,19 @@ +# Basic formatting +max_width = 100 +tab_spaces = 4 +hard_tabs = false +edition = "2024" + +# Code organization +reorder_imports = true +reorder_modules = true + +# Formatting preferences +merge_derives = true + +# Function and control flow formatting +fn_params_layout = "Tall" + +# Code style preferences +use_try_shorthand = true +use_field_init_shorthand = true diff --git a/packages/ui/api/stellar/src/config/mod.rs b/packages/ui/api/stellar/src/config/mod.rs new file mode 100644 index 000000000..6c63b9b69 --- /dev/null +++ b/packages/ui/api/stellar/src/config/mod.rs @@ -0,0 +1,2 @@ +mod server; +pub use server::*; diff --git a/packages/ui/api/stellar/src/config/server.rs b/packages/ui/api/stellar/src/config/server.rs new file mode 100644 index 000000000..02b8efa02 --- /dev/null +++ b/packages/ui/api/stellar/src/config/server.rs @@ -0,0 +1,38 @@ +use std::env; + +#[derive(Debug, Clone)] +pub struct ServerConfig { + /// The host address the server will bind to. + pub host: String, + /// The port number the server will listen on. + pub port: u16, + /// The number of requests allowed per second. + pub rate_limit_requests_per_second: u64, + /// Origin of the Wizard web application. + pub wizard_origin: String, +} + +impl ServerConfig { + /// Creates a new `ServerConfig` instance from environment variables. + /// + /// # Defaults + /// + /// - `HOST` defaults to `"0.0.0.0"`. + /// - `APP_PORT` defaults to `8080`. + /// - `RATE_LIMIT_REQUESTS_PER_SECOND` defaults to `100`. + pub fn from_environment_variables() -> Self { + Self { + host: env::var("HOST").unwrap_or_else(|_| "0.0.0.0".to_string()), + port: env::var("APP_PORT") + .unwrap_or_else(|_| "8888".to_string()) + .parse() + .unwrap_or(8888), + rate_limit_requests_per_second: env::var("RATE_LIMIT_REQUESTS_PER_SECOND") + .unwrap_or_else(|_| "100".to_string()) + .parse() + .unwrap_or(100), + wizard_origin: env::var("WIZARD_ORIGIN") + .unwrap_or_else(|_| "http://localhost:8080".to_string()), + } + } +} diff --git a/packages/ui/api/stellar/src/controllers/mod.rs b/packages/ui/api/stellar/src/controllers/mod.rs new file mode 100644 index 000000000..70e1359a9 --- /dev/null +++ b/packages/ui/api/stellar/src/controllers/mod.rs @@ -0,0 +1,2 @@ +mod upgrade_scaffold; +pub use upgrade_scaffold::*; diff --git a/packages/ui/api/stellar/src/controllers/upgrade_scaffold.rs b/packages/ui/api/stellar/src/controllers/upgrade_scaffold.rs new file mode 100644 index 000000000..8e3fe1843 --- /dev/null +++ b/packages/ui/api/stellar/src/controllers/upgrade_scaffold.rs @@ -0,0 +1,36 @@ +use crate::environment::{run_scaffold_upgrade_command, unzip_in_temporary_folder, zip_directory}; +use crate::utils::to_http_hidden_error; +use actix_web::{web, Error as HttpError}; +use std::path::{Path, PathBuf}; +use walkdir::WalkDir; + +fn list_files(dir: &Path) -> Vec { + WalkDir::new(dir) + .into_iter() + .filter_map(|e| e.ok()) + .filter(|e| e.file_type().is_file()) + .map(|e| e.into_path()) + .collect() +} + +pub async fn upgrade_to_scaffold(rust_contract_zip: web::Bytes) -> Result, HttpError> { + let contract_zipped_files = [ + "contracts/*/src/contract.rs", + "contracts/*/src/test.rs", + "contracts/*/src/lib.rs", + "contracts/*/Cargo.toml", + "Cargo.toml", + "README.md", + ]; + + let contracts_dir = + unzip_in_temporary_folder(rust_contract_zip.to_vec(), &contract_zipped_files) + .map_err(to_http_hidden_error)?; + + run_scaffold_upgrade_command(contracts_dir.path()).map_err(to_http_hidden_error)?; + + let zipped_env = zip_directory(contracts_dir.path()).map_err(to_http_hidden_error)?; + + contracts_dir.close().map_err(to_http_hidden_error)?; + Ok(zipped_env) +} diff --git a/packages/ui/api/stellar/src/environment/mod.rs b/packages/ui/api/stellar/src/environment/mod.rs new file mode 100644 index 000000000..019b841d1 --- /dev/null +++ b/packages/ui/api/stellar/src/environment/mod.rs @@ -0,0 +1,4 @@ +mod zip_folder; +pub use zip_folder::*; +mod scaffold_upgrade; +pub use scaffold_upgrade::*; diff --git a/packages/ui/api/stellar/src/environment/scaffold_upgrade.rs b/packages/ui/api/stellar/src/environment/scaffold_upgrade.rs new file mode 100644 index 000000000..0d72d5b1e --- /dev/null +++ b/packages/ui/api/stellar/src/environment/scaffold_upgrade.rs @@ -0,0 +1,25 @@ +use std::path::Path; +use std::{ + io::Error, + process::{Command, Stdio}, +}; + +pub fn run_scaffold_upgrade_command(project_dir_path: &Path) -> Result<(), Error> { + let output = Command::new("stellar") + .args(["scaffold", "upgrade", "--skip-prompt"]) + .stdin(Stdio::null()) + .stdout(Stdio::null()) + .stderr(Stdio::piped()) + .current_dir(project_dir_path) + .output()?; + + if output.status.success() { + Ok(()) + } else { + Err(Error::other(format!( + "'stellar scaffold upgrade' failed with code {:?}: {}", + output.status.code(), + String::from_utf8_lossy(&output.stderr) + ))) + } +} diff --git a/packages/ui/api/stellar/src/environment/zip_folder.rs b/packages/ui/api/stellar/src/environment/zip_folder.rs new file mode 100644 index 000000000..d2a15d46b --- /dev/null +++ b/packages/ui/api/stellar/src/environment/zip_folder.rs @@ -0,0 +1,282 @@ +use crate::utils::{ + build_globset, create_dir_safe, expand_with_directories, is_glob_match, join_and_assert_inside, + to_zip_io_error, write_file_safe, +}; +use std::collections::HashSet; +use std::fs::{read, File}; +use std::io::{self, Cursor, Read, Seek, Write}; +use std::path::{Component, Path, PathBuf}; +use tempfile::{NamedTempFile, TempDir}; +use walkdir::WalkDir; +use zip::{ + read::ZipFile, + result::{ZipError, ZipResult}, + write::FileOptions, + CompressionMethod, ZipArchive, ZipWriter, +}; + +pub fn unzip_in_temporary_folder( + zip_data: Vec, + expected_files: &[&str], +) -> Result { + let mut temp_zip = NamedTempFile::new().map_err(to_zip_io_error)?; + + temp_zip.write_all(&zip_data).map_err(to_zip_io_error)?; + + let temp_dir = TempDir::new().map_err(to_zip_io_error)?; + + let file = File::open(temp_zip.path()).map_err(to_zip_io_error)?; + + let mut archive = ZipArchive::new(file).map_err(to_zip_io_error)?; + + secure_zip_extract(&mut archive, temp_dir.path(), expected_files)?; + + Ok(temp_dir) +} + +fn secure_zip_extract( + archive: &mut ZipArchive, + destination_path: &Path, + expected_files: &[&str], +) -> Result<(), ZipError> { + validate_archive_structure(archive, expected_files)?; + + let expected_globset = + build_globset(expand_with_directories(expected_files)).map_err(to_zip_io_error)?; + let mut seen_paths: HashSet = HashSet::with_capacity(archive.len()); + + let mut total_uncompressed: u64 = 0; + + for i in 0..archive.len() { + let entry = archive.by_index(i)?; + + let validated_entry = validate_entry_metadata(&entry)?; + + let entry_path = normalize_entry_path(&entry)?; + + validate_and_register_entry(&validated_entry, &expected_globset, &mut seen_paths)?; + + let target_full_path = join_and_assert_inside(destination_path, entry_path.as_path())?; + + if entry.is_dir() { + create_dir_safe(&target_full_path).map_err(to_zip_io_error)?; + continue; + } + + total_uncompressed = + validate_entry_size(&entry, total_uncompressed, &ZipEntryLimits::rust_env())?; + + if let Some(parent) = target_full_path.parent() { + create_dir_safe(parent)?; + } + + let size = entry.size(); + let mut limited_reader = entry.take(size); + write_file_safe( + &target_full_path, + destination_path, + size, + &mut limited_reader, + )?; + } + + Ok(()) +} + +fn validate_and_register_entry( + entry_path: &str, + expected_globset: &globset::GlobSet, + seen_paths: &mut HashSet, +) -> Result<(), ZipError> { + if seen_paths.contains(entry_path) { + return Err(ZipError::UnsupportedArchive("duplicate entry")); + } + + if is_glob_match(expected_globset, entry_path).is_err() { + return Err(ZipError::UnsupportedArchive("Unexpected zip content")); + } + + seen_paths.insert(entry_path.to_owned()); + + Ok(()) +} + +fn normalize_entry_path(entry: &ZipFile) -> Result { + let p = entry + .enclosed_name() + .ok_or_else(|| to_zip_io_error("invalid entry name"))?; + if p.is_absolute() + || p.components() + .any(|c| matches!(c, Component::Prefix { .. })) + { + return Err(ZipError::UnsupportedArchive("absolute or prefix path")); + } + Ok(p.to_path_buf()) +} + +pub struct ZipEntryLimits { + pub max_total_uncompressed: u64, + pub max_file_uncompressed: u64, + pub max_compression_ratio: u64, +} + +impl ZipEntryLimits { + pub const fn rust_env() -> Self { + Self { + max_total_uncompressed: 100 * 1024, // 100 KB + max_file_uncompressed: 50 * 1024, // 50 KB + max_compression_ratio: 200, + } + } +} + +fn validate_entry_size( + entry: &ZipFile, + total_uncompressed: u64, + zip_entry_limits: &ZipEntryLimits, +) -> Result { + let uncompressed = entry.size(); + let compressed = entry.compressed_size(); + + if uncompressed > zip_entry_limits.max_file_uncompressed { + return Err(ZipError::UnsupportedArchive("entry too large")); + } + + let new_total = total_uncompressed + .checked_add(uncompressed) + .ok_or_else(|| to_zip_io_error("Size overflow"))?; + if new_total > zip_entry_limits.max_total_uncompressed { + return Err(ZipError::UnsupportedArchive("archive too large")); + } + + if compressed.saturating_mul(zip_entry_limits.max_compression_ratio) < uncompressed { + return Err(ZipError::UnsupportedArchive("suspicious compression ratio")); + } + + Ok(new_total) +} + +fn validate_archive_structure( + archive: &ZipArchive, + expected_files: &[&str], +) -> Result<(), ZipError> { + if archive.len() != expected_entry_count(expected_files) { + return Err(ZipError::UnsupportedArchive("Unexpected zip file")); + } + + Ok(()) +} + +fn ancestors_rel(p: &Path) -> impl Iterator + '_ { + p.ancestors() + .take_while(|a| !a.as_os_str().is_empty()) + .map(Path::to_path_buf) +} + +pub fn expected_entry_count(file_globs: &[&str]) -> usize { + file_globs + .iter() + .flat_map(|pat| ancestors_rel(Path::new(pat))) + .collect::>() + .len() +} + +fn validate_entry_metadata(entry: &ZipFile) -> Result { + if entry.encrypted() { + return Err(ZipError::UnsupportedArchive( + "Encrypted entries are not allowed", + )); + } + + if entry.is_symlink() { + return Err(ZipError::UnsupportedArchive( + "Symlink entries are not allowed", + )); + } + + match entry.compression() { + CompressionMethod::Stored | CompressionMethod::Deflated => {} + _ => { + return Err(ZipError::UnsupportedArchive( + "Unsupported compression method", + )) + } + } + + let entry_path = entry + .enclosed_name() + .and_then(|p| p.to_str().map(|s| s.to_owned())) + .ok_or_else(|| to_zip_io_error("invalid entry name"))?; + + Ok(entry_path) +} + +//EvLUATE WHAT CAN BE EXTRACTED FROM SPECIFIC RUST ENV PROCESS +pub fn zip_directory(zip_path: &Path) -> ZipResult> { + let mut zip_result = Vec::new(); + + { + let mut zip_writer = ZipWriter::new(Cursor::new(&mut zip_result)); + let compression_options = default_options(); + + for entry in WalkDir::new(zip_path).into_iter().filter_map(Result::ok) { + let path = entry.path(); + let is_dir = path.is_dir(); + let root_path = path.strip_prefix(zip_path).unwrap(); + + if root_path.as_os_str().is_empty() { + continue; + } + + let normalized_root_path = normalize_path(root_path); + + if is_dir { + add_directory_to_zip(&mut zip_writer, &normalized_root_path, compression_options)?; + } else { + add_file_to_zip( + &mut zip_writer, + path, + &normalized_root_path, + compression_options, + )?; + } + } + + zip_writer.finish()?; + } + + Ok(zip_result) +} + +fn normalize_path(p: &Path) -> String { + p.to_string_lossy().replace('\\', "/") +} + +fn default_options() -> FileOptions<'static, ()> { + FileOptions::default() + .compression_method(CompressionMethod::Deflated) + .unix_permissions(0o755) +} + +fn add_directory_to_zip( + zip: &mut ZipWriter, + name: &str, + options: FileOptions<()>, +) -> ZipResult<()> { + let mut dir = name.to_string(); + if !dir.ends_with('/') { + dir.push('/'); + } + zip.add_directory(dir, options) +} + +fn add_file_to_zip( + zip: &mut ZipWriter, + src_path: &Path, + root_path: &str, + options: FileOptions<()>, +) -> Result<(), ZipError> { + zip.start_file(root_path, options)?; + let bytes = read(src_path).map_err(to_zip_io_error)?; + zip.write_all(&bytes).map_err(to_zip_io_error) +} diff --git a/packages/ui/api/stellar/src/lib.rs b/packages/ui/api/stellar/src/lib.rs new file mode 100644 index 000000000..7b4f1c35f --- /dev/null +++ b/packages/ui/api/stellar/src/lib.rs @@ -0,0 +1,17 @@ +//! # API Module +//! +//! Contains HTTP API implementation for the stellar service. +//! +//! ## Structure +//! +//! * `config` - Configuration management for the API server +//! * `controllers` - Request handling and business logic +//! * `environment` - The logic for create, upgrading and zipping the contract environment +//! * `routes` - API endpoint definitions and routing +//! * `utils` - Some utility functions and error handling + +pub mod config; +pub mod controllers; +pub mod environment; +pub mod routes; +pub mod utils; diff --git a/packages/ui/api/stellar/src/main.rs b/packages/ui/api/stellar/src/main.rs new file mode 100644 index 000000000..faef40bee --- /dev/null +++ b/packages/ui/api/stellar/src/main.rs @@ -0,0 +1,58 @@ +use actix_cors::Cors; +use actix_governor::{Governor, GovernorConfigBuilder}; +use actix_web::{ + middleware::{self, Logger}, + web, App, HttpServer, +}; +use dotenvy::dotenv; +use log::info; +use std::sync::Arc; +use stellar_api::config::ServerConfig; + +use stellar_api::routes::configure_routes; + +#[actix_web::main] +async fn main() -> std::io::Result<()> { + dotenv().ok(); + env_logger::init(); + + let config = Arc::new(ServerConfig::from_environment_variables()); + + let rate_limit_config = GovernorConfigBuilder::default() + .requests_per_second(config.rate_limit_requests_per_second) + .finish() + .expect("Invalid rate limiter config: ensure rate_limit_requests_per_second is a positive integer"); + + let host = config.host.clone(); + let port = config.port; + + info!("Starting server on {host}:{port}"); + + HttpServer::new(move || { + let cors = { + let wizard_origin = config.wizard_origin.clone(); + Cors::default() + .allowed_origin_fn(move |origin, _req| { + if let Ok(origin_str) = origin.to_str() { + origin_str.ends_with("wizard.netlify.app") + || origin_str == "https://wizard.openzeppelin.com" + || origin_str == wizard_origin + } else { + false + } + }) + .allowed_methods(["POST"]) + .allow_any_header() + }; + + App::new() + .wrap(cors) + .wrap(Governor::new(&rate_limit_config)) + .wrap(middleware::Compress::default()) + .wrap(Logger::default()) + .service(web::scope("/stellar").configure(configure_routes)) + }) + .bind((host.as_str(), port))? + .run() + .await +} diff --git a/packages/ui/api/stellar/src/routes/health.rs b/packages/ui/api/stellar/src/routes/health.rs new file mode 100644 index 000000000..ba2fa4483 --- /dev/null +++ b/packages/ui/api/stellar/src/routes/health.rs @@ -0,0 +1,14 @@ +//! This module provides a health check endpoint for the API. +//! The `/health` endpoint can be used to verify that the service is running and responsive. +use actix_web::{get, web, HttpResponse}; + +#[get("/health")] +async fn health() -> Result { + Ok(HttpResponse::Ok().body("OK")) +} + +/// Initializes the health check service. +/// Registers the `health` endpoint with the provided service configuration. +pub fn init(cfg: &mut web::ServiceConfig) { + cfg.service(health); +} diff --git a/packages/ui/api/stellar/src/routes/mod.rs b/packages/ui/api/stellar/src/routes/mod.rs new file mode 100644 index 000000000..28d9a1767 --- /dev/null +++ b/packages/ui/api/stellar/src/routes/mod.rs @@ -0,0 +1,9 @@ +pub mod health; +pub mod upgrade_scaffold; + +use actix_web::web; + +pub fn configure_routes(cfg: &mut web::ServiceConfig) { + cfg.configure(health::init) + .configure(upgrade_scaffold::init); +} diff --git a/packages/ui/api/stellar/src/routes/upgrade_scaffold.rs b/packages/ui/api/stellar/src/routes/upgrade_scaffold.rs new file mode 100644 index 000000000..d6c346444 --- /dev/null +++ b/packages/ui/api/stellar/src/routes/upgrade_scaffold.rs @@ -0,0 +1,30 @@ +//! This module upgrade a Rust contract environment to a Scaffold environment +use crate::controllers::upgrade_to_scaffold; +use actix_web::{http::header, post, web, HttpResponse}; +use std::io::Cursor; +use zip::ZipArchive; + +#[post("/upgrade-scaffold")] +async fn download_scaffold_route(req: web::Bytes) -> Result { + if ZipArchive::new(Cursor::new(&req)).is_err() { + return Ok(HttpResponse::UnsupportedMediaType().body("invalid ZIP archive")); + } + + match upgrade_to_scaffold(req).await { + Ok(body) => Ok(HttpResponse::Ok() + .insert_header((header::CONTENT_TYPE, "application/zip")) + .insert_header(( + header::CONTENT_DISPOSITION, + "attachment; filename=archive.zip", + )) + .body(body)), + Err(error) => { + log::error!("Error upgrading scaffold: {error}"); + Ok(HttpResponse::InternalServerError().body("Internal error")) + } + } +} + +pub fn init(cfg: &mut web::ServiceConfig) { + cfg.service(download_scaffold_route); +} diff --git a/packages/ui/api/stellar/src/utils/dir.rs b/packages/ui/api/stellar/src/utils/dir.rs new file mode 100644 index 000000000..6a58f7404 --- /dev/null +++ b/packages/ui/api/stellar/src/utils/dir.rs @@ -0,0 +1,49 @@ +use crate::utils::{ensure_no_symlinks, to_io_error}; +use std::fs::{DirBuilder, OpenOptions}; +use std::io::{copy, Error as IoError, Read, Take}; +use std::os::unix::fs::DirBuilderExt; +use std::path::Path; + +pub fn create_dir_safe(path: &Path) -> Result<(), IoError> { + // 0o700 on Unix. On non-Unix, this compiles but ignores mode. + #[cfg(unix)] + { + use DirBuilderExt; + let mut b = DirBuilder::new(); + b.recursive(true) + .mode(0o700) + .create(path) + .map_err(to_io_error) + } + #[cfg(not(unix))] + { + fs::create_dir_all(path).map_err(utils::to_io_error::to_io_error) + } +} + +pub fn write_file_safe( + target: &Path, + root: &Path, + file_size: u64, + file_take: &mut Take, +) -> Result<(), IoError> { + ensure_no_symlinks(root, target).map_err(to_io_error)?; + + let mut file = { + let mut open_option = OpenOptions::new(); + open_option.write(true).create_new(true); + #[cfg(unix)] + { + use std::os::unix::fs::OpenOptionsExt; + open_option.custom_flags(libc::O_NOFOLLOW); + open_option.mode(0o600); + } + open_option.open(target).map_err(to_io_error)? + }; + + let written = copy(file_take, &mut file).map_err(to_io_error)?; + if written != file_size { + return Err(IoError::other("size mismatch")); + } + Ok(()) +} diff --git a/packages/ui/api/stellar/src/utils/errors.rs b/packages/ui/api/stellar/src/utils/errors.rs new file mode 100644 index 000000000..20db5a2ce --- /dev/null +++ b/packages/ui/api/stellar/src/utils/errors.rs @@ -0,0 +1,20 @@ +use actix_web::{error::ErrorInternalServerError, Error as HttpError}; +use log::error; +use std::fmt::Debug; +use std::io::Error as IOError; +use zip::result::ZipError; + +pub fn to_http_hidden_error(error: E) -> HttpError { + error!("Internal error: {error:?}"); + ErrorInternalServerError("Internal Server Error") +} + +pub fn to_io_error(error: E) -> IOError { + error!("IO error: {error:?}"); + IOError::other(format!("{error:?}")) +} + +pub fn to_zip_io_error(error: E) -> ZipError { + error!("Zip error: {error:?}"); + ZipError::Io(IOError::other(format!("{error:?}"))) +} diff --git a/packages/ui/api/stellar/src/utils/glob.rs b/packages/ui/api/stellar/src/utils/glob.rs new file mode 100644 index 000000000..939ce972a --- /dev/null +++ b/packages/ui/api/stellar/src/utils/glob.rs @@ -0,0 +1,28 @@ +use globset::{Error as GlobError, Glob, GlobSet, GlobSetBuilder}; + +#[derive(Debug)] +pub enum MatchError { + Glob(GlobError), + NoMatch(String), +} + +pub fn build_globset(patterns: Vec) -> Result { + patterns + .iter() + .map(|p| Glob::new(p)) + .collect::, _>>()? + .into_iter() + .fold(GlobSetBuilder::new(), |mut builder, glob| { + builder.add(glob); + builder + }) + .build() +} + +pub fn is_glob_match(matchers: &GlobSet, glob: &str) -> Result { + matchers + .matches(glob) + .first() + .copied() + .ok_or_else(|| MatchError::NoMatch(glob.to_string())) +} diff --git a/packages/ui/api/stellar/src/utils/mod.rs b/packages/ui/api/stellar/src/utils/mod.rs new file mode 100644 index 000000000..12ce93397 --- /dev/null +++ b/packages/ui/api/stellar/src/utils/mod.rs @@ -0,0 +1,8 @@ +mod errors; +pub use errors::*; +mod glob; +pub use glob::*; +mod path; +pub use path::*; +mod dir; +pub use dir::*; diff --git a/packages/ui/api/stellar/src/utils/path.rs b/packages/ui/api/stellar/src/utils/path.rs new file mode 100644 index 000000000..f5538895c --- /dev/null +++ b/packages/ui/api/stellar/src/utils/path.rs @@ -0,0 +1,99 @@ +use std::collections::HashSet; +use std::fs::{canonicalize, symlink_metadata}; +use std::io::{Error as IoError, ErrorKind as IoErrorKind, Result as IoResult}; +use std::path::{Component, Path, PathBuf}; + +pub fn canonicalize_existing_dir(dir: &Path) -> Result { + let can_path = canonicalize(dir).map_err(|e| { + if e.kind() == IoErrorKind::NotFound { + IoError::other("Directory does not exist") + } else { + e + } + })?; + + if !can_path.is_dir() { + return Err(IoError::other("destination is not a directory")); + } + + Ok(can_path) +} + +fn norm(s: &str) -> String { + let mut v = s.replace('\\', "/"); + if let Some(x) = v.strip_prefix("./") { + v = x.to_string(); + } + v +} + +fn ancestors_rel(p: &str) -> impl Iterator + '_ { + Path::new(p) + .ancestors() + .skip(1) // parents only, not the full path + .take_while(|a| !a.as_os_str().is_empty()) + .map(|a| a.components() + .filter(|c| !matches!(c, Component::CurDir)) + .collect::() + .to_string_lossy() + .into_owned()) +} + +pub fn expand_with_directories(patterns: &[&str]) -> Vec { + let set: HashSet = patterns + .iter() + .map(|p| norm(p)) + .flat_map(|p| { + let mut v = Vec::new(); + v.push(p.clone()); + for d in ancestors_rel(&p) { + v.push(d.clone()); + v.push(format!("{d}/")); + } + v + }) + .collect(); + set.into_iter().collect() +} + +pub fn join_and_assert_inside(root: &Path, rel: &Path) -> Result { + let full = root.join(rel); + if !full.starts_with(root) { + return Err(IoError::other("Path escape root")); + } + Ok(full) +} + +pub fn ensure_no_symlinks(root: &Path, path: &Path) -> IoResult<()> { + let rel = path + .strip_prefix(root) + .map_err(|_| IoError::other("path escapes root"))?; + + let parents = rel.parent().unwrap_or(Path::new("")); + + parents + .components() + .scan(root.to_path_buf(), |acc: &mut PathBuf, c| { + acc.push(c); + Some(acc.clone()) + }) + .try_for_each(|p| { + let ft = symlink_metadata(&p)?.file_type(); + if ft.is_symlink() { + Err(IoError::other("symlink detected")) + } else { + Ok(()) + } + })?; + + match std::fs::symlink_metadata(path) { + Ok(meta) if meta.file_type().is_symlink() => { + return Err(IoError::other("symlink detected")) + } + Err(e) if e.kind() == IoErrorKind::NotFound => {} + Err(e) => return Err(e), + _ => {} + } + + Ok(()) +} diff --git a/packages/ui/api/stellar/tests/environment/mod.rs b/packages/ui/api/stellar/tests/environment/mod.rs new file mode 100644 index 000000000..024a9d5b3 --- /dev/null +++ b/packages/ui/api/stellar/tests/environment/mod.rs @@ -0,0 +1 @@ +pub mod zip_folder; diff --git a/packages/ui/api/stellar/tests/environment/zip_folder.rs b/packages/ui/api/stellar/tests/environment/zip_folder.rs new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/packages/ui/api/stellar/tests/environment/zip_folder.rs @@ -0,0 +1 @@ + diff --git a/packages/ui/api/stellar/tests/routes/health.rs b/packages/ui/api/stellar/tests/routes/health.rs new file mode 100644 index 000000000..9a08290a9 --- /dev/null +++ b/packages/ui/api/stellar/tests/routes/health.rs @@ -0,0 +1,15 @@ +use actix_web::{test, App}; +use stellar_api::routes::health::init; + +#[actix_web::test] +async fn test_health_endpoint() { + let app = test::init_service(App::new().configure(init)).await; + + let req = test::TestRequest::get().uri("/health").to_request(); + let resp = test::call_service(&app, req).await; + + assert!(resp.status().is_success()); + + let body = test::read_body(resp).await; + assert_eq!(body, "OK"); +} diff --git a/packages/ui/api/stellar/tests/routes/mod.rs b/packages/ui/api/stellar/tests/routes/mod.rs new file mode 100644 index 000000000..43a7c768a --- /dev/null +++ b/packages/ui/api/stellar/tests/routes/mod.rs @@ -0,0 +1 @@ +pub mod health; diff --git a/packages/ui/api/stellar/tests/tests_paths.rs b/packages/ui/api/stellar/tests/tests_paths.rs new file mode 100644 index 000000000..28dfbdf95 --- /dev/null +++ b/packages/ui/api/stellar/tests/tests_paths.rs @@ -0,0 +1,8 @@ +#[path = "environment/mod.rs"] +mod environment; + +#[path = "routes/mod.rs"] +mod routes; + +#[path = "utils/mod.rs"] +mod utils; diff --git a/packages/ui/api/stellar/tests/utils/glob.rs b/packages/ui/api/stellar/tests/utils/glob.rs new file mode 100644 index 000000000..d5eec27bf --- /dev/null +++ b/packages/ui/api/stellar/tests/utils/glob.rs @@ -0,0 +1,50 @@ +use stellar_api::utils::build_globset; + +#[test] +fn test_single_pattern_match() { + let globset = build_globset(vec!["*.rs".to_string()]).unwrap(); + let matcher = globset.matches("main.rs"); + assert!(!matcher.is_empty()); +} + +#[test] +fn test_single_pattern_no_match() { + let globset = build_globset(vec!["*.rs".to_string()]).unwrap(); + let matcher = globset.matches("main.txt"); + assert!(matcher.is_empty()); +} + +#[test] +fn test_multiple_patterns_match() { + let globset = build_globset(vec!["*.rs".to_string(), "*.txt".to_string()]).unwrap(); + assert!(globset.is_match("lib.rs")); + assert!(globset.is_match("readme.txt")); + assert!(!globset.is_match("image.png")); +} + +#[test] +fn test_empty_patterns() { + let globset = build_globset(Vec::::new()).unwrap(); + assert!(!globset.is_match("main.rs")); +} + +#[test] +fn test_invalid_pattern() { + let result = build_globset(vec!["[invalid".to_string()]); + assert!(result.is_err()); +} + +#[test] +fn test_directory_pattern() { + let globset = build_globset(vec!["src/*".to_string()]).unwrap(); + assert!(globset.is_match("src/main.rs")); + assert!(!globset.is_match("tests/main.rs")); +} + +#[test] +fn test_question_mark_pattern() { + let globset = build_globset(vec!["file?.rs".to_string()]).unwrap(); + assert!(globset.is_match("file1.rs")); + assert!(globset.is_match("fileA.rs")); + assert!(!globset.is_match("file10.rs")); +} diff --git a/packages/ui/api/stellar/tests/utils/mod.rs b/packages/ui/api/stellar/tests/utils/mod.rs new file mode 100644 index 000000000..9ee2e9707 --- /dev/null +++ b/packages/ui/api/stellar/tests/utils/mod.rs @@ -0,0 +1 @@ +pub mod glob; diff --git a/packages/ui/package.json b/packages/ui/package.json index 0b90b9efd..6e82281ee 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -5,9 +5,10 @@ "scripts": { "prepare": "echo \"Nothing to prepare\"", "build": "node scripts/copy-versions.mjs && rollup -c", - "type:check:api": "deno task --config deno.json type:check", + "type:check:api": "deno task --config ./api/ai/deno.json type:check", "dev": "node scripts/copy-versions.mjs && rollup -c -w", - "dev:api": "ENV=dev deno task dev", + "dev:api": "cd api && docker-compose up", + "dev:api:build": "cd api && docker-compose up --build", "start": "sirv public", "validate": "svelte-check" }, @@ -50,4 +51,4 @@ "tippy.js": "^6.3.1", "util": "^0.12.4" } -} +} \ No newline at end of file diff --git a/packages/ui/rollup.config.mjs b/packages/ui/rollup.config.mjs index 2f6eb05b4..9c38a8449 100644 --- a/packages/ui/rollup.config.mjs +++ b/packages/ui/rollup.config.mjs @@ -129,6 +129,9 @@ export default [ 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV), 'process.env.NODE_DEBUG': JSON.stringify(process.env.NODE_DEBUG), 'process.env.API_HOST': JSON.stringify(production ? '' : `http://localhost:${process.env.API_PORT || 3000}`), + 'process.env.FARGATE_HOST': JSON.stringify( + production ? 'TODO' : `http://localhost:${process.env.FARGATE_PORT || 8888}`, + ), }), json(), diff --git a/packages/ui/src/cairo/App.svelte b/packages/ui/src/cairo/App.svelte index 6ae12a0d5..2a406d6e4 100644 --- a/packages/ui/src/cairo/App.svelte +++ b/packages/ui/src/cairo/App.svelte @@ -27,7 +27,7 @@ import { injectHyperlinks } from './inject-hyperlinks'; import type { InitialOptions } from '../common/initial-options'; import { createWiz, mergeAiAssistanceOptions } from '../common/Wiz.svelte'; - import type { AiFunctionCall } from '../../api/ai-assistant/types/assistant'; + import type { AiFunctionCall } from '../../api/ai/ai-assistant/types/assistant'; const dispatch = createEventDispatcher(); diff --git a/packages/ui/src/cairo_alpha/App.svelte b/packages/ui/src/cairo_alpha/App.svelte index 2d52e64bb..17f1ab6e7 100644 --- a/packages/ui/src/cairo_alpha/App.svelte +++ b/packages/ui/src/cairo_alpha/App.svelte @@ -33,7 +33,7 @@ import { injectHyperlinks } from './inject-hyperlinks'; import type { InitialOptions } from '../common/initial-options'; import { createWiz, mergeAiAssistanceOptions } from '../common/Wiz.svelte'; - import type { AiFunctionCall } from '../../api/ai-assistant/types/assistant'; + import type { AiFunctionCall } from '../../api/ai/ai-assistant/types/assistant'; const dispatch = createEventDispatcher(); diff --git a/packages/ui/src/common/Wiz.svelte b/packages/ui/src/common/Wiz.svelte index 386f71614..1317d2da5 100644 --- a/packages/ui/src/common/Wiz.svelte +++ b/packages/ui/src/common/Wiz.svelte @@ -14,7 +14,6 @@ Object.keys(previousOptions).reduce( (acc, currentKey) => { if (aiFunctionCall.name === currentKey) - //@ts-expect-error currentKey can safely access acc has it was created from previousOptions with Object.key and acc initial value is also previousOptions return { ...acc, [currentKey]: { ...acc[currentKey], ...aiFunctionCall.arguments } }; else return acc; }, @@ -52,7 +51,7 @@ AiFunctionCall, AiFunctionCallResponse, Chat, - } from '../../api/ai-assistant/types/assistant'; + } from '../../api/ai/ai-assistant/types/assistant'; import { createEventDispatcher } from 'svelte'; const apiHost = process.env.API_HOST; diff --git a/packages/ui/src/solidity/App.svelte b/packages/ui/src/solidity/App.svelte index 7440a0aee..9851beb0d 100644 --- a/packages/ui/src/solidity/App.svelte +++ b/packages/ui/src/solidity/App.svelte @@ -32,7 +32,7 @@ import { saveAs } from 'file-saver'; import { injectHyperlinks } from './inject-hyperlinks'; import type { InitialOptions } from '../common/initial-options'; - import type { AiFunctionCall } from '../../api/ai-assistant/types/assistant'; + import type { AiFunctionCall } from '../../api/ai/ai-assistant/types/assistant'; import ErrorDisabledActionButtons from '../common/ErrorDisabledActionButtons.svelte'; import { createWiz, mergeAiAssistanceOptions } from '../common/Wiz.svelte'; import type { Language } from '../common/languages-types'; diff --git a/packages/ui/src/stellar/App.svelte b/packages/ui/src/stellar/App.svelte index 3e4e15b7c..aba62ddeb 100644 --- a/packages/ui/src/stellar/App.svelte +++ b/packages/ui/src/stellar/App.svelte @@ -30,11 +30,12 @@ import { injectHyperlinks } from './inject-hyperlinks'; import type { InitialOptions } from '../common/initial-options'; import { createWiz, mergeAiAssistanceOptions } from '../common/Wiz.svelte'; - import type { AiFunctionCall } from '../../api/ai-assistant/types/assistant'; + import type { AiFunctionCall } from '../../api/ai/ai-assistant/types/assistant'; import ZipIcon from '../common/icons/ZipIcon.svelte'; - import type { GenericOptions } from '@openzeppelin/wizard-stellar/src'; import type { Language } from '../common/languages-types'; + const fargateHost = process.env.FARGATE_HOST; + const WizStellar = createWiz<'stellar'>(); const dispatch = createEventDispatcher(); @@ -79,15 +80,45 @@ $: showButtons = getButtonVisibilities(opts); - const zipScaffoldModule = import('@openzeppelin/wizard-stellar/zip-env-scaffold'); + const zipRustModule = import('@openzeppelin/wizard-stellar/zip-env-rust'); + + let isDownloadingScaffold = false; + let downloadScaffoldError = false; const downloadScaffoldHandler = async () => { - const { zipScaffoldProject } = await zipScaffoldModule; + if (!opts) return; - await downloadZip(zipScaffoldProject, 'download-scaffold', 'stellar', contract, opts); - }; + const { zipRustProjectBlob } = await zipRustModule; - const zipRustModule = import('@openzeppelin/wizard-stellar/zip-env-rust'); + try { + downloadScaffoldError = false; + isDownloadingScaffold = true; + + const { + ok, + status, + body: scaffoldProject, + } = await fetch(`${fargateHost}/stellar/upgrade-scaffold`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: await zipRustProjectBlob(contract, opts), + }); + + if (!ok) throw new Error(`HTTP ${status}`); + + saveAs(await new Response(scaffoldProject).blob(), 'scaffold-project.zip'); + await postConfig(opts, 'download-file', language); + + isDownloadingScaffold = false; + } catch (error) { + console.log(error); + + downloadScaffoldError = true; + isDownloadingScaffold = false; + } + }; const downloadRustHandler = async () => { const { zipRustProject } = await zipRustModule; @@ -226,8 +257,20 @@ {/if} diff --git a/packages/ui/src/stylus/App.svelte b/packages/ui/src/stylus/App.svelte index 7726da8d3..91b48bf9e 100644 --- a/packages/ui/src/stylus/App.svelte +++ b/packages/ui/src/stylus/App.svelte @@ -28,7 +28,7 @@ import { injectHyperlinks } from './inject-hyperlinks'; import type { InitialOptions } from '../common/initial-options'; import { createWiz, mergeAiAssistanceOptions } from '../common/Wiz.svelte'; - import type { AiFunctionCall } from '../../api/ai-assistant/types/assistant'; + import type { AiFunctionCall } from '../../api/ai/ai-assistant/types/assistant'; const dispatch = createEventDispatcher();