diff --git a/.changeset/cute-squids-type.md b/.changeset/cute-squids-type.md new file mode 100644 index 000000000..dd1e7e2f3 --- /dev/null +++ b/.changeset/cute-squids-type.md @@ -0,0 +1,12 @@ +--- +"@turnkey/eip-1193-provider": minor +"@turnkey/react-wallet-kit": minor +"@turnkey/sdk-server": minor +"@turnkey/sdk-react": minor +"@turnkey/sdk-types": minor +"@turnkey/encoding": minor +"@turnkey/core": minor +"@turnkey/http": minor +--- + +@turnkey/react-wallet-kit and @turnkey/core beta-3 release diff --git a/.changeset/fair-bushes-retire.md b/.changeset/fair-bushes-retire.md new file mode 100644 index 000000000..dd1e7e2f3 --- /dev/null +++ b/.changeset/fair-bushes-retire.md @@ -0,0 +1,12 @@ +--- +"@turnkey/eip-1193-provider": minor +"@turnkey/react-wallet-kit": minor +"@turnkey/sdk-server": minor +"@turnkey/sdk-react": minor +"@turnkey/sdk-types": minor +"@turnkey/encoding": minor +"@turnkey/core": minor +"@turnkey/http": minor +--- + +@turnkey/react-wallet-kit and @turnkey/core beta-3 release diff --git a/.changeset/loose-ravens-walk.md b/.changeset/loose-ravens-walk.md new file mode 100644 index 000000000..19d25e6c2 --- /dev/null +++ b/.changeset/loose-ravens-walk.md @@ -0,0 +1,8 @@ +--- +"@turnkey/react-wallet-kit": minor +"@turnkey/sdk-types": minor +"@turnkey/encoding": minor +"@turnkey/core": minor +--- + +updating package versions diff --git a/.changeset/old-pillows-float.md b/.changeset/old-pillows-float.md new file mode 100644 index 000000000..1627f5a37 --- /dev/null +++ b/.changeset/old-pillows-float.md @@ -0,0 +1,8 @@ +--- +"@turnkey/react-wallet-kit": minor +"@turnkey/sdk-types": minor +"@turnkey/encoding": minor +"@turnkey/core": minor +--- + +test build diff --git a/.changeset/pre.json b/.changeset/pre.json new file mode 100644 index 000000000..8eea56b4b --- /dev/null +++ b/.changeset/pre.json @@ -0,0 +1,77 @@ +{ + "mode": "pre", + "tag": "beta", + "initialVersions": { + "@turnkey/delegated-access": "0.0.15-beta.2", + "@turnkey/example-deployer": "0.1.3", + "@turnkey/example-email-auth": "0.1.0", + "@turnkey/example-email-auth-local-storage": "0.1.0", + "@turnkey/example-export-in-node": "0.1.0", + "@turnkey/example-import-in-node": "0.1.0", + "@turnkey/kitchen-sink": "0.1.5", + "@turnkey/example-oauth": "0.1.0", + "@turnkey/example-otp-auth": "0.1.0", + "@turnkey/example-react-components": "0.1.0", + "@turnkey/example-demo-react-wallet-kit": "0.1.0", + "@turnkey/example-with-rebalancer": "0.0.2", + "@turnkey/example-sweeper": "0.1.3", + "@turnkey/example-trading-runner": "0.0.1", + "@turnkey/example-wallet-import-export": "0.2.0", + "@turnkey/example-with-aptos": "0.1.0", + "@turnkey/example-with-biconomy-aa": "0.2.0", + "@turnkey/example-with-bitcoin": "0.2.0", + "@turnkey/example-with-cosmjs": "0.1.3", + "@turnkey/example-with-eip-1193-provider": "0.1.0", + "@turnkey/with-eth-passkey-signers": "0.2.5", + "@turnkey/example-with-ethers": "0.1.3", + "@turnkey/example-with-federated-passkeys": "0.1.2", + "@turnkey/example-with-gnosis": "0.1.4", + "@turnkey/with-indexed-db": "0.1.0", + "@turnkey/with-morpho": "0.0.1", + "@turnkey/example-with-movement": "0.1.0", + "@turnkey/example-with-nonce-manager": "0.1.0", + "@turnkey/example-with-offline": "0.0.0", + "@turnkey/with-sdk-js": "0.1.0", + "@turnkey/example-with-sdk-server": "0.1.0", + "@turnkey/example-with-solana": "0.1.0", + "@turnkey/with-solana-passkeys": "0.1.7", + "@turnkey/with-stacks": "0.0.1", + "@turnkey/example-with-sui": "0.1.0", + "@turnkey/example-with-ton": "0.1.0", + "@turnkey/example-with-tron": "0.1.0", + "@turnkey/example-with-uniswap": "0.1.3", + "@turnkey/example-with-viem": "0.0.1", + "@turnkey/with-wallet-stamper": "0.1.7", + "@turnkey/example-with-zerodev-aa": "0.1.0", + "@turnkey/jest-config": "0.1.3", + "@turnkey/api-key-stamper": "0.4.8-beta.2", + "@turnkey/core": "1.0.0-beta.2", + "@turnkey/cosmjs": "0.7.25-beta.2", + "@turnkey/crypto": "2.5.1-beta.2", + "@turnkey/eip-1193-provider": "3.3.24-beta.2", + "@turnkey/encoding": "0.6.0-beta.2", + "@turnkey/ethers": "1.2.8-beta.2", + "@turnkey/http": "3.8.1-beta.2", + "@turnkey/iframe-stamper": "2.5.0", + "@turnkey/indexed-db-stamper": "1.1.2-beta.2", + "@turnkey/react-native-passkey-stamper": "1.1.2-beta.2", + "@turnkey/react-wallet-kit": "1.0.0-beta.2", + "@turnkey/sdk-browser": "5.6.1-beta.2", + "@turnkey/sdk-react": "5.3.2-beta.2", + "@turnkey/sdk-react-native": "1.4.2-beta.2", + "@turnkey/sdk-server": "4.5.1-beta.2", + "@turnkey/sdk-types": "0.4.0-beta.2", + "@turnkey/solana": "1.0.41-beta.2", + "@turnkey/telegram-cloud-storage-stamper": "2.0.4-beta.2", + "@turnkey/viem": "0.11.2-beta.2", + "@turnkey/wallet-stamper": "1.0.9-beta.2", + "@turnkey/webauthn-stamper": "0.5.1" + }, + "changesets": [ + "cute-squids-type", + "fair-bushes-retire", + "loose-ravens-walk", + "old-pillows-float", + "rotten-mugs-matter" + ] +} diff --git a/.changeset/rotten-mugs-matter.md b/.changeset/rotten-mugs-matter.md new file mode 100644 index 000000000..8db7dcadf --- /dev/null +++ b/.changeset/rotten-mugs-matter.md @@ -0,0 +1,8 @@ +--- +"@turnkey/react-wallet-kit": major +"@turnkey/core": major +"@turnkey/sdk-types": minor +"@turnkey/encoding": minor +--- + +beta for @turnkey/react-wallet-kit and @turnkey/core diff --git a/.codesandbox/ci.json b/.codesandbox/ci.json index bc92c473c..baf555991 100644 --- a/.codesandbox/ci.json +++ b/.codesandbox/ci.json @@ -19,7 +19,10 @@ "packages/iframe-stamper", "packages/crypto", "packages/react-native-passkey-stamper", - "packages/telegram-cloud-storage-stamper" + "packages/telegram-cloud-storage-stamper", + "packages/core", + "packages/react-wallet-kit", + "packages/sdk-types" ], "sandboxes": ["/examples/react-components"], "node": "20" diff --git a/.github/workflows/beta-version-and-publish.yml b/.github/workflows/beta-version-and-publish.yml new file mode 100644 index 000000000..641f2dbc5 --- /dev/null +++ b/.github/workflows/beta-version-and-publish.yml @@ -0,0 +1,301 @@ +name: Beta Release + +on: + workflow_dispatch: + push: + branches: + - amir/sdk-js + paths: + - ".changeset/**" # only trigger on changes to changesets + +permissions: + contents: write + packages: write + +concurrency: + group: beta-release + cancel-in-progress: false + +jobs: + beta-release: + runs-on: ubuntu-latest + outputs: + version_commit: ${{ steps.version-sha.outputs.sha }} + has_changesets: ${{ steps.has_changesets.outputs.has }} + steps: + - name: Checkout beta branch + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + fetch-depth: 0 + + - name: Setup JS + uses: ./.github/actions/js-setup + + - name: Ensure there are pending changesets + id: has_changesets + run: | + pnpm -w changeset status --output=JSON > /tmp/plan.json || echo '{}' > /tmp/plan.json + COUNT=$(jq '.changesets | length' /tmp/plan.json 2>/dev/null || echo 0) + echo "count=$COUNT" >> "$GITHUB_OUTPUT" + if [ "$COUNT" -gt 0 ]; then + echo "has=true" >> "$GITHUB_OUTPUT" + else + echo "has=false" >> "$GITHUB_OUTPUT" + echo "No pending changesets; this job will no-op." + fi + + - name: Configure Git user + if: steps.has_changesets.outputs.count != '0' + run: | + git config user.name "tkhq-deploy" + git config user.email "github@turnkey.engineering" + + - name: Version (Changesets) + your version script + if: steps.has_changesets.outputs.count != '0' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + pnpm -w changeset version + pnpm run version + pnpm install -r + + - name: Commit & push version bumps # [skip ci] so that this commit does not trigger another workflow run + if: steps.has_changesets.outputs.count != '0' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + if ! git diff --quiet; then + git add -A + git commit -m "chore: beta version bump [skip ci]" + git push --no-verify + else + echo "No changes to commit" + fi + + - name: Push branch + tags # push the updated branch and any tags created by changeset version + if: steps.has_changesets.outputs.count != '0' + run: | + git push --follow-tags origin HEAD:"${{ github.ref_name }}" + + - name: Capture versioned commit SHA + if: steps.has_changesets.outputs.count != '0' + id: version-sha + run: echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" + + - name: Build + if: steps.has_changesets.outputs.count != '0' + run: pnpm run build-all + + - name: Typecheck + if: steps.has_changesets.outputs.count != '0' + run: pnpm run typecheck-all + + - name: Prettier + if: steps.has_changesets.outputs.count != '0' + run: pnpm run prettier-all:check + + - name: Upload beta release artifacts + if: steps.has_changesets.outputs.count != '0' + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: beta-release-artifacts-${{ github.run_id }} + path: | + packages/** + !packages/*/node_modules + pnpm-lock.yaml + pnpm-workspace.yaml + .changeset/** + retention-days: 7 + + test-pre-prod: + if: needs.beta-release.outputs.has_changesets == 'true' + runs-on: ubuntu-latest + needs: beta-release + steps: + - name: Checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + fetch-depth: 0 # required for git tags and history + ref: ${{ needs.beta-release.outputs.version_commit }} + + - name: Setup JS + uses: ./.github/actions/js-setup + + - name: Download release artifacts + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + name: beta-release-artifacts-${{ github.run_id }} + path: _artifact + + - name: Overlay artifact snapshot + run: | + mkdir -p packages .changeset + rsync -a --delete ./_artifact/packages/ ./packages/ + cp -f ./_artifact/pnpm-lock.yaml ./pnpm-lock.yaml || true + cp -f ./_artifact/pnpm-workspace.yaml ./pnpm-workspace.yaml || true + rsync -a ./_artifact/.changeset/ ./.changeset/ || true + + - name: Install latest dependencies + run: pnpm install -r --frozen-lockfile + + - name: Test (preprod) + run: anvil & PN=$!; pnpm run test-all; RC=$?; lsof -t -i tcp:8545 | xargs -r kill; wait $PN || true; exit $RC + env: + API_PUBLIC_KEY: ${{ secrets.PREPROD_API_PUBLIC_KEY }} + API_PRIVATE_KEY: ${{ secrets.PREPROD_API_PRIVATE_KEY }} + BASE_URL: ${{ secrets.PREPROD_BASE_URL }} + ORGANIZATION_ID: ${{ secrets.PREPROD_ORGANIZATION_ID }} + PRIVATE_KEY_ID: ${{ secrets.PREPROD_PRIVATE_KEY_ID }} + EXPECTED_PRIVATE_KEY_ETH_ADDRESS: ${{ secrets.PREPROD_EXPECTED_PRIVATE_KEY_ETH_ADDRESS }} + EXPECTED_PRIVATE_KEY_ETH_ADDRESS_2: ${{ secrets.PREPROD_EXPECTED_PRIVATE_KEY_ETH_ADDRESS_2 }} + EXPECTED_WALLET_ACCOUNT_ETH_ADDRESS: ${{ secrets.PREPROD_EXPECTED_WALLET_ACCOUNT_ETH_ADDRESS }} + EXPECTED_WALLET_ACCOUNT_ETH_ADDRESS_2: ${{ secrets.PREPROD_EXPECTED_WALLET_ACCOUNT_ETH_ADDRESS_2 }} + BANNED_TO_ADDRESS: ${{ secrets.PREPROD_BANNED_TO_ADDRESS }} + SOLANA_TEST_ORG_API_PRIVATE_KEY: ${{ secrets.SOLANA_TEST_ORG_API_PRIVATE_KEY }} + WALLET_ID: ${{ secrets.PREPROD_WALLET_ID }} + + test-prod: + if: needs.beta-release.outputs.has_changesets == 'true' + runs-on: ubuntu-latest + needs: [beta-release, test-pre-prod] + steps: + - name: Checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + fetch-depth: 0 # required for git tags and history + ref: ${{ needs.beta-release.outputs.version_commit }} + + - name: Setup JS + uses: ./.github/actions/js-setup + + - name: Download beta-release artifacts + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + name: beta-release-artifacts-${{ github.run_id }} + path: _artifact + + - name: Overlay artifact snapshot + run: | + mkdir -p packages .changeset + rsync -a --delete ./_artifact/packages/ ./packages/ + cp -f ./_artifact/pnpm-lock.yaml ./pnpm-lock.yaml || true + cp -f ./_artifact/pnpm-workspace.yaml ./pnpm-workspace.yaml || true + rsync -a ./_artifact/.changeset/ ./.changeset/ || true + + - name: Install latest dependencies + run: pnpm install -r --frozen-lockfile + + - name: Test (prod) + run: anvil & PN=$!; pnpm run test-all; RC=$?; lsof -t -i tcp:8545 | xargs -r kill; wait $PN || true; exit $RC + env: + API_PUBLIC_KEY: ${{ secrets.API_PUBLIC_KEY }} + API_PRIVATE_KEY: ${{ secrets.API_PRIVATE_KEY }} + BASE_URL: "https://api.turnkey.com" + ORGANIZATION_ID: ${{ secrets.ORGANIZATION_ID }} + PRIVATE_KEY_ID: ${{ secrets.PRIVATE_KEY_ID }} + EXPECTED_PRIVATE_KEY_ETH_ADDRESS: ${{ secrets.EXPECTED_PRIVATE_KEY_ETH_ADDRESS }} + EXPECTED_PRIVATE_KEY_ETH_ADDRESS_2: ${{ secrets.EXPECTED_PRIVATE_KEY_ETH_ADDRESS_2 }} + EXPECTED_WALLET_ACCOUNT_ETH_ADDRESS: ${{ secrets.EXPECTED_WALLET_ACCOUNT_ETH_ADDRESS }} + EXPECTED_WALLET_ACCOUNT_ETH_ADDRESS_2: ${{ secrets.EXPECTED_WALLET_ACCOUNT_ETH_ADDRESS_2 }} + BANNED_TO_ADDRESS: "0x6F72eDB2429820c2A0606a9FC3cA364f5E9b2375" + SOLANA_TEST_ORG_API_PRIVATE_KEY: ${{ secrets.SOLANA_TEST_ORG_API_PRIVATE_KEY }} + WALLET_ID: ${{ secrets.WALLET_ID }} + + publish-beta-dry-run: + if: needs.beta-release.outputs.has_changesets == 'true' + runs-on: ubuntu-latest + needs: [beta-release, test-prod] + environment: production # require manual approval for beta deployments + steps: + - name: Checkout versioned commit + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + ref: ${{ needs.beta-release.outputs.version_commit }} + fetch-depth: 0 + + - name: Setup JS + uses: ./.github/actions/js-setup + + - name: Download beta-release artifacts + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + name: beta-release-artifacts-${{ github.run_id }} + path: _artifact + + - name: Overlay artifact snapshot + run: | + mkdir -p packages .changeset + rsync -a --delete ./_artifact/packages/ ./packages/ + cp -f ./_artifact/pnpm-lock.yaml ./pnpm-lock.yaml || true + cp -f ./_artifact/pnpm-workspace.yaml ./pnpm-workspace.yaml || true + rsync -a ./_artifact/.changeset/ ./.changeset/ || true + + - name: Verify pre mode is 'beta' + run: | + test -f .changeset/pre.json || { echo "::error::.changeset/pre.json missing. Refusing to publish (beta-only)."; exit 1; } + TAG=$(jq -r '.tag // empty' .changeset/pre.json) + MODE=$(jq -r '.mode // empty' .changeset/pre.json) + echo "mode=$MODE tag=$TAG" + [ "$MODE" = "pre" ] && [ "$TAG" = "beta" ] || { echo "::error::pre mode/tag check failed (mode=$MODE tag=$TAG). Refusing to publish."; exit 1; } + + - name: Configure npm auth (npmjs) + run: | + echo "::add-mask::$NPM_TOKEN" + echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > .npmrc + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: Publish to NPM (dry run beta dist-tag) + run: pnpm -w changeset publish --dry-run --tag beta -- --no-git-checks --report-summary + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + NPM_CONFIG_DRY_RUN: "true" + + publish-beta: + if: needs.beta-release.outputs.has_changesets == 'true' + runs-on: ubuntu-latest + needs: [beta-release, test-prod, publish-beta-dry-run] + environment: production # require manual approval for beta deployments + steps: + - name: Checkout versioned commit + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + ref: ${{ needs.beta-release.outputs.version_commit }} + fetch-depth: 0 + + - name: Setup JS + uses: ./.github/actions/js-setup + + - name: Download beta-release artifacts + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + name: beta-release-artifacts-${{ github.run_id }} + path: _artifact + + - name: Overlay artifact snapshot + run: | + mkdir -p packages .changeset + rsync -a --delete ./_artifact/packages/ ./packages/ + cp -f ./_artifact/pnpm-lock.yaml ./pnpm-lock.yaml || true + cp -f ./_artifact/pnpm-workspace.yaml ./pnpm-workspace.yaml || true + rsync -a ./_artifact/.changeset/ ./.changeset/ || true + + - name: Verify pre mode is 'beta' + run: | + test -f .changeset/pre.json || { echo "::error::.changeset/pre.json missing. Refusing to publish (beta-only)."; exit 1; } + TAG=$(jq -r '.tag // empty' .changeset/pre.json) + MODE=$(jq -r '.mode // empty' .changeset/pre.json) + echo "mode=$MODE tag=$TAG" + [ "$MODE" = "pre" ] && [ "$TAG" = "beta" ] || { echo "::error::pre mode/tag check failed (mode=$MODE tag=$TAG). Refusing to publish."; exit 1; } + + - name: Configure npm auth (npmjs) + run: | + echo "::add-mask::$NPM_TOKEN" + echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > .npmrc + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: Publish to npm (beta dist-tag) + run: pnpm -w changeset publish -- --no-git-checks --tag beta + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/examples/delegated-access/CHANGELOG.md b/examples/delegated-access/CHANGELOG.md index 31b6377fc..e9794a211 100644 --- a/examples/delegated-access/CHANGELOG.md +++ b/examples/delegated-access/CHANGELOG.md @@ -1,5 +1,40 @@ # @turnkey/delegated-access +## 0.0.15-beta.4 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/sdk-server@4.7.0-beta.1 + +## 0.0.15-beta.3 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/sdk-server@4.7.0-beta.0 + +## 0.0.15-beta.2 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/sdk-server@4.5.1-beta.2 + +## 0.0.15-beta.1 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/sdk-server@4.5.1-beta.1 + +## 0.0.15-beta.0 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/sdk-server@4.5.1-beta.0 + ## 0.0.15 ### Patch Changes diff --git a/examples/delegated-access/package.json b/examples/delegated-access/package.json index 18954ba61..16dc72f18 100644 --- a/examples/delegated-access/package.json +++ b/examples/delegated-access/package.json @@ -1,6 +1,6 @@ { "name": "@turnkey/delegated-access", - "version": "0.0.15", + "version": "0.0.15-beta.4", "private": true, "scripts": { "build": "pnpm -w run build-all", diff --git a/examples/react-wallet-kit/.env.local.example b/examples/react-wallet-kit/.env.local.example new file mode 100644 index 000000000..3835e7785 --- /dev/null +++ b/examples/react-wallet-kit/.env.local.example @@ -0,0 +1,6 @@ +NEXT_PUBLIC_ORGANIZATION_ID="" +NEXT_PUBLIC_AUTH_PROXY_ID="" + +# Only needed if you're using WalletConnect (walletconnect.network) +NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID="" +NEXT_PUBLIC_WALLETCONNECT_PROJECT_URL="http://localhost:3000/" \ No newline at end of file diff --git a/examples/react-wallet-kit/.eslintrc.json b/examples/react-wallet-kit/.eslintrc.json new file mode 100644 index 000000000..bffb357a7 --- /dev/null +++ b/examples/react-wallet-kit/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "extends": "next/core-web-vitals" +} diff --git a/examples/react-wallet-kit/.gitignore b/examples/react-wallet-kit/.gitignore new file mode 100644 index 000000000..8f322f0d8 --- /dev/null +++ b/examples/react-wallet-kit/.gitignore @@ -0,0 +1,35 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env*.local + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/examples/react-wallet-kit/README.md b/examples/react-wallet-kit/README.md new file mode 100644 index 000000000..5fdac57f3 --- /dev/null +++ b/examples/react-wallet-kit/README.md @@ -0,0 +1,3 @@ +# Turnkey Demo EWK + +A demo of @turnkey/react-wallet-kit diff --git a/examples/react-wallet-kit/next-env.d.ts b/examples/react-wallet-kit/next-env.d.ts new file mode 100644 index 000000000..40c3d6809 --- /dev/null +++ b/examples/react-wallet-kit/next-env.d.ts @@ -0,0 +1,5 @@ +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information. diff --git a/examples/react-wallet-kit/next.config.js b/examples/react-wallet-kit/next.config.js new file mode 100644 index 000000000..0d46a14d8 --- /dev/null +++ b/examples/react-wallet-kit/next.config.js @@ -0,0 +1,10 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = { + transpilePackages: ["three"], + images: { + domains: [], + unoptimized: true, // Allow base64-encoded images + }, +}; + +module.exports = nextConfig; diff --git a/examples/react-wallet-kit/package.json b/examples/react-wallet-kit/package.json new file mode 100644 index 000000000..25f209874 --- /dev/null +++ b/examples/react-wallet-kit/package.json @@ -0,0 +1,57 @@ +{ + "name": "@turnkey/example-demo-react-wallet-kit", + "version": "0.1.0", + "main": "./dist/index.js", + "module": "./dist/index.mjs", + "types": "./dist/index.d.ts", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint", + "typecheck": "tsc --noEmit" + }, + "dependencies": { + "@fortawesome/fontawesome-svg-core": "^6.7.2", + "@fortawesome/free-brands-svg-icons": "^6.7.2", + "@fortawesome/free-solid-svg-icons": "^6.7.2", + "@fortawesome/react-fontawesome": "^0.2.2", + "@headlessui/react": "^2.2.4", + "@hello-pangea/dnd": "^17.0.0", + "@noble/hashes": "1.4.0", + "@react-three/drei": "^10.6.1", + "@react-three/fiber": "^8.18.0", + "@solana/web3.js": "^1.95.8", + "@tailwindcss/postcss": "^4.1.10", + "@turnkey/react-wallet-kit": "workspace:*", + "@turnkey/sdk-types": "workspace:*", + "@types/node": "20.3.1", + "@types/react": "18.2.14", + "@types/react-dom": "18.2.6", + "axios": "^1.8.2", + "clsx": "^2.1.1", + "encoding": "^0.1.13", + "eslint": "8.56.0", + "eslint-config-next": "14.2.25", + "esm": "^3.2.25", + "ethers": "^6.10.0", + "install": "^0.13.0", + "maath": "^0.10.8", + "next": "^14.2.25", + "npm": "^9.7.2", + "postcss": "^8.5.6", + "react": "18.2.0", + "react-dom": "18.2.0", + "react-hook-form": "^7.45.1", + "react-toastify": "^11.0.5", + "tailwindcss": "^4.1.11", + "three": "^0.160.0", + "tweetnacl": "^1.0.3", + "typescript": "5.1.3", + "viem": "^2.33.2" + }, + "devDependencies": { + "@types/three": "^0.178.1" + } +} diff --git a/examples/react-wallet-kit/postcss.config.mjs b/examples/react-wallet-kit/postcss.config.mjs new file mode 100644 index 000000000..7059fe95a --- /dev/null +++ b/examples/react-wallet-kit/postcss.config.mjs @@ -0,0 +1,6 @@ +const config = { + plugins: { + "@tailwindcss/postcss": {}, + }, +}; +export default config; diff --git a/examples/react-wallet-kit/public/3D/turnkey.glb b/examples/react-wallet-kit/public/3D/turnkey.glb new file mode 100644 index 000000000..2431a2299 Binary files /dev/null and b/examples/react-wallet-kit/public/3D/turnkey.glb differ diff --git a/examples/react-wallet-kit/public/favicon.svg b/examples/react-wallet-kit/public/favicon.svg new file mode 100644 index 000000000..73948fa1a --- /dev/null +++ b/examples/react-wallet-kit/public/favicon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/examples/react-wallet-kit/public/fonts/inter/Inter-Bold.woff2 b/examples/react-wallet-kit/public/fonts/inter/Inter-Bold.woff2 new file mode 100644 index 000000000..2846f29cc Binary files /dev/null and b/examples/react-wallet-kit/public/fonts/inter/Inter-Bold.woff2 differ diff --git a/examples/react-wallet-kit/public/fonts/inter/Inter-Regular.woff2 b/examples/react-wallet-kit/public/fonts/inter/Inter-Regular.woff2 new file mode 100644 index 000000000..6c2b6893d Binary files /dev/null and b/examples/react-wallet-kit/public/fonts/inter/Inter-Regular.woff2 differ diff --git a/examples/react-wallet-kit/public/fonts/inter/Inter-SemiBold.woff2 b/examples/react-wallet-kit/public/fonts/inter/Inter-SemiBold.woff2 new file mode 100644 index 000000000..611e90c95 Binary files /dev/null and b/examples/react-wallet-kit/public/fonts/inter/Inter-SemiBold.woff2 differ diff --git a/examples/react-wallet-kit/public/logo.svg b/examples/react-wallet-kit/public/logo.svg new file mode 100644 index 000000000..f983fd29b --- /dev/null +++ b/examples/react-wallet-kit/public/logo.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + diff --git a/examples/react-wallet-kit/src/app/global.css b/examples/react-wallet-kit/src/app/global.css new file mode 100644 index 000000000..56e6c8c9f --- /dev/null +++ b/examples/react-wallet-kit/src/app/global.css @@ -0,0 +1,126 @@ +@import "tailwindcss"; + +@custom-variant dark (&:where(.dark, .dark *)); +@custom-variant light (&:where(.light, .light *)); + +@theme { + --color-primary-light: oklch(0.547 0.2389 266.82); + --color-primary-dark: oklch(0.547 0.2389 266.82); + /* This is the color of the text that goes on top of primary color buttons */ + --color-primary-text-light: rgb(255, 255, 255); + --color-primary-text-dark: rgb(255, 255, 255); + + --color-danger-light: oklch(0.65 0.1406 12.71); + --color-danger-dark: oklch(0.6088 0.1801 30.71); + /* This is the color of the text that goes on top of danger color buttons */ + --color-danger-text-light: rgb(255, 255, 255); + --color-danger-text-dark: rgb(255, 255, 255); + + --color-success-light: oklch(0.7231 0.1834 142.46); + --color-success-dark: oklch(0.7679 0.1603 152.74); + /* This is the color of the text that goes on top of success color buttons */ + --color-success-text-light: rgb(255, 255, 255); + --color-success-text-dark: rgb(255, 255, 255); + + --color-button-light: rgb(255, 255, 255); + --color-button-dark: oklch(0.2532 0.0056 285.99); + + --color-background-light: oklch(0.9774 0 76.65); + --color-background-dark: oklch(0.25 0 0); + --color-text-light: oklch(0 0.1 41); + --color-text-dark: rgb(255, 255, 255); + + --color-panel-background-light: #ffffff; + --color-panel-background-dark: oklch(0.2 0 0); + + --color-icon-background-light: oklch(0.928 0.006 264.531); + --color-icon-background-dark: oklch(0.3222 0.0053 286.1); + --color-icon-text-light: oklch(0.6066 0 0); + --color-icon-text-dark: oklch(0.7174 0.0029 286.32); + + /* This is the color of the background of draggable items */ + --color-draggable-background-light: oklch(0.9758 0.0057 264.53); + --color-draggable-background-dark: oklch(0.2622 0 0); + + --animate-shake: shake 250ms ease-in-out; + @keyframes shake { + 0%, + 100% { + transform: translateX(0); + } + 25% { + transform: translateX(-5px); + } + 75% { + transform: translateX(5px); + } + } +} + +@font-face { + font-family: "Inter"; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url("/fonts/inter/Inter-Regular.woff2?v=3.19") format("woff2"); +} + +@font-face { + font-family: "Inter"; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url("/fonts/inter/Inter-SemiBold.woff2?v=3.19") format("woff2"); +} + +* { + font-family: + "Inter", + -apple-system, + BlinkMacSystemFont, + sans-serif; +} + +:root { + font-family: + "Inter", + -apple-system, + BlinkMacSystemFont, + sans-serif; +} + +@layer components { + /* A nice scrollbar that conforms to light/dark mode */ + .tk-scrollbar { + /* For Firefox */ + scrollbar-width: thin; + scrollbar-color: var(--color-background-light) + var(--color-panel-background-light); /* thumb and track (light mode) */ + } + /* For WebKit browsers */ + .tk-scrollbar::-webkit-scrollbar { + width: 8px; + height: 8px; + } + .tk-scrollbar::-webkit-scrollbar-track { + background: var(--color-draggable-background-light); + } + .tk-scrollbar::-webkit-scrollbar-thumb { + background-color: var(--color-draggable-background-light); + border-radius: 10px; + border: 2px solid var(--color-draggable-background-light); + } + + /* Dark mode styles */ + .dark .tk-scrollbar { + scrollbar-color: var(--color-background-dark) + var(--color-panel-background-dark); /* thumb and track (dark mode) */ + } + .dark .tk-scrollbar::-webkit-scrollbar-track { + background: var(--color-background-dark); + } + .dark .tk-scrollbar::-webkit-scrollbar-thumb { + background-color: var(--color-background-dark); + border: 2px solid var(--color-background-dark); + } +} diff --git a/examples/react-wallet-kit/src/app/layout.tsx b/examples/react-wallet-kit/src/app/layout.tsx new file mode 100644 index 000000000..6bc2068f2 --- /dev/null +++ b/examples/react-wallet-kit/src/app/layout.tsx @@ -0,0 +1,60 @@ +"use client"; + +import "@turnkey/react-wallet-kit/styles.css"; +import "./global.css"; +import { TurnkeyConfigProvider } from "@/providers/config/ConfigProvider"; +import "@fortawesome/fontawesome-svg-core/styles.css"; +import { Slide, toast } from "react-toastify"; +import { initialConfig } from "@/constants"; +import { TurnkeyErrorCodes } from "@turnkey/sdk-types"; + +interface RootLayoutProps { + children: React.ReactNode; +} + +function RootLayout({ children }: RootLayoutProps) { + const notify = (message: String) => + toast.error("Error: " + message, { + position: "bottom-right", + autoClose: 5000, + hideProgressBar: false, + pauseOnFocusLoss: false, + closeOnClick: false, + pauseOnHover: true, + draggable: true, + progress: undefined, + transition: Slide, + }); + + return ( + + + Turnkey Demo EWK + + + + { + console.error("Turnkey Error:", error.code); + switch (error.code) { + case TurnkeyErrorCodes.ACCOUNT_ALREADY_EXISTS: + notify( + "This social login is already associated with another account.", + ); + break; + default: + notify(error.message); + } + }, + }} + > + {children} + + + + ); +} + +export default RootLayout; diff --git a/examples/react-wallet-kit/src/app/page.tsx b/examples/react-wallet-kit/src/app/page.tsx new file mode 100644 index 000000000..98cf65bec --- /dev/null +++ b/examples/react-wallet-kit/src/app/page.tsx @@ -0,0 +1,106 @@ +"use client"; + +import DemoPanel from "@/components/demo/DemoPanel"; +import UserSettings from "@/components/demo/UserSettings"; +import { Spinner } from "@/components/Spinners"; +import { useScreenSize } from "@/utils"; +import { faUserGear, faWallet } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { + Button, + Tab, + TabGroup, + TabList, + TabPanel, + TabPanels, + Transition, +} from "@headlessui/react"; +import { AuthState, ClientState, useTurnkey } from "@turnkey/react-wallet-kit"; +import { useEffect, useState } from "react"; + +export default function AuthPage() { + const { handleLogin, clientState, authState } = useTurnkey(); + + const [selectedTabIndex, setSelectedTabIndex] = useState(1); + + useEffect(() => { + if ( + clientState === ClientState.Ready && + authState === AuthState.Unauthenticated + ) { + handleLogin(); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [clientState]); + + const { isMobile } = useScreenSize(); + + return ( +
+ {authState === AuthState.Unauthenticated && + (clientState === undefined || clientState === ClientState.Loading ? ( + + ) : clientState === ClientState.Error ? ( + + ) : ( + + ))} + + {!isMobile ? ( +
+ + +
+ ) : ( + setSelectedTabIndex(index)} + selectedIndex={selectedTabIndex} + > + + + + + + + + + + + +

Account

+
+ + +

Wallet

+
+
+
+ )} +
+
+ ); +} diff --git a/examples/react-wallet-kit/src/components/3D/Background.tsx b/examples/react-wallet-kit/src/components/3D/Background.tsx new file mode 100644 index 000000000..b2c1be286 --- /dev/null +++ b/examples/react-wallet-kit/src/components/3D/Background.tsx @@ -0,0 +1,68 @@ +import { Canvas } from "@react-three/fiber"; +import { TurnkeyLogo } from "./TurnkeyLogo"; +import { Stars } from "./Stars"; +import { PerspectiveCamera, useProgress } from "@react-three/drei"; +import { Suspense, useEffect, useState } from "react"; +import clsx from "clsx"; +import { useTurnkeyConfig } from "@/providers/config/ConfigProvider"; +import { useScreenSize } from "@/utils"; + +function FadeInWrapper(props: { + startVisible: boolean; + children: React.ReactNode; +}) { + const { startVisible, children } = props; + const { progress } = useProgress(); // This tracks loading progress of async assets like the Turnkey glb model + const [visible, setVisible] = useState(false); + + useEffect(() => { + if (startVisible) { + setVisible(true); + return; + } + if (progress === 100) { + const timeout = setTimeout(() => setVisible(true), 50); // Fade in after a short delay + return () => clearTimeout(timeout); + } + }, [progress, startVisible]); + + return ( +
+ {children} +
+ ); +} + +export function ThreeDimensionalBackground() { + const { isMobile } = useScreenSize(); + const { demoConfig, hardwareAccelerationEnabled } = useTurnkeyConfig(); + + const canShow3DBackground = + demoConfig.backgroundEnabled && hardwareAccelerationEnabled; + + return ( + + {canShow3DBackground && ( + + + + + + + + + )} + + ); +} diff --git a/examples/react-wallet-kit/src/components/3D/Stars.tsx b/examples/react-wallet-kit/src/components/3D/Stars.tsx new file mode 100644 index 000000000..9df4b46db --- /dev/null +++ b/examples/react-wallet-kit/src/components/3D/Stars.tsx @@ -0,0 +1,57 @@ +import { useFrame } from "@react-three/fiber"; +import { useRef, useMemo, useState, useEffect } from "react"; +import * as THREE from "three"; +import { useTurnkeyConfig } from "@/providers/config/ConfigProvider"; +import { logoColour } from "@/utils"; + +interface StarsProps { + position?: [number, number, number]; +} + +export function Stars({ position = [0, 0, 0] }: StarsProps) { + const ref = useRef(null); + const { demoConfig, config } = useTurnkeyConfig(); + + const [color, setColor] = useState("gray"); + + useEffect(() => { + setColor( + demoConfig.ui + ? config.ui?.darkMode + ? demoConfig.ui?.dark?.background + ? logoColour(demoConfig.ui.dark.background) + : "gray" + : demoConfig.ui?.light?.background + ? logoColour(demoConfig.ui.light.background) + : "gray" + : "gray", + ); + }, [demoConfig, config]); + + const radius = 1; + const widthSegments = 32; + const heightSegments = 16; + + const geometry = useMemo(() => { + const sphere = new THREE.SphereGeometry( + radius, + widthSegments, + heightSegments, + ); + return new THREE.WireframeGeometry(sphere); + }, [radius, widthSegments, heightSegments]); + + useFrame((state) => { + if (ref.current) { + ref.current.rotation.y = state.clock.getElapsedTime() * 0.1; + } + }); + + return ( + + + + + + ); +} diff --git a/examples/react-wallet-kit/src/components/3D/TurnkeyLogo.tsx b/examples/react-wallet-kit/src/components/3D/TurnkeyLogo.tsx new file mode 100644 index 000000000..aa2dd918d --- /dev/null +++ b/examples/react-wallet-kit/src/components/3D/TurnkeyLogo.tsx @@ -0,0 +1,99 @@ +import { useGLTF } from "@react-three/drei"; +import { useMemo, useRef, useEffect, useState } from "react"; +import { MeshBasicMaterial, Group } from "three"; +import { useFrame } from "@react-three/fiber"; +import { useModal } from "@turnkey/react-wallet-kit"; +import { lerp } from "three/src/math/MathUtils"; +import { logoColour } from "@/utils"; +import { useTurnkeyConfig } from "@/providers/config/ConfigProvider"; + +interface TurnkeyLogoProps { + position?: [number, number, number]; +} + +export function TurnkeyLogo(props: TurnkeyLogoProps) { + const { position = [0, 0, 0] } = props; + const { modalStack } = useModal(); + const { demoConfig, config } = useTurnkeyConfig(); + + const url = "/3D/turnkey.glb"; + const { scene } = useGLTF(url); + const groupRef = useRef(null); + const [logoColor, setLogoColor] = useState("gray"); + + useEffect(() => { + setLogoColor( + demoConfig.ui + ? config.ui?.darkMode + ? demoConfig.ui?.dark?.background + ? logoColour(demoConfig.ui.dark.background) + : "gray" + : demoConfig.ui?.light?.background + ? logoColour(demoConfig.ui.light.background) + : "gray" + : "gray", + ); + }, [demoConfig, config]); + + const defaultSpeed = 0.1; // Default rotation speed + const burstSpeed = 10; // Speed during burst + const lerpSpeed = 5; // How quickly to interpolate speed + const burstDuration = 300; // Duration to burst speed + + const speedRef = useRef(defaultSpeed); // current speed + const targetSpeedRef = useRef(defaultSpeed); // what we're lerping toward + const previousModalLength = useRef(modalStack.length); + + useFrame((_, delta) => { + // Lerp current speed toward the target + speedRef.current = lerp( + speedRef.current, + targetSpeedRef.current, + lerpSpeed * delta, + ); + + // Rotate the model using interpolated speed + if (groupRef.current) { + groupRef.current.rotation.y += delta * speedRef.current; + } + }); + + // When modalStack changes, trigger burst + useEffect(() => { + if (modalStack.length !== previousModalLength.current) { + // Accelerate + targetSpeedRef.current = burstSpeed; + + // Then decelerate over time + const timeout = setTimeout(() => { + targetSpeedRef.current = defaultSpeed; + }, burstDuration); + + previousModalLength.current = modalStack.length; + + return () => clearTimeout(timeout); + } + }, [modalStack.length]); + + // Make Turnkey logo wireframe. + const wireframeMaterial = useMemo( + () => new MeshBasicMaterial({ color: logoColor, wireframe: true }), + [logoColor], + ); + + const model = useMemo(() => { + const clone = scene.clone(true); + clone.traverse((child) => { + if ((child as any).isMesh) { + (child as any).material = wireframeMaterial; + } + }); + return clone; + }, [scene, wireframeMaterial]); + + return ( + + + + ); +} diff --git a/examples/react-wallet-kit/src/components/Color.tsx b/examples/react-wallet-kit/src/components/Color.tsx new file mode 100644 index 000000000..afdbada42 --- /dev/null +++ b/examples/react-wallet-kit/src/components/Color.tsx @@ -0,0 +1,31 @@ +interface ColourPickerProps { + value: string; + onChange: (val: string) => void; + label?: string; +} + +export function ColourPicker /*πŸ‡¨πŸ‡¦*/(props: ColourPickerProps) { + const { value, onChange, label } = props; + return ( +
+ {label && {label}} +
+
+ ); +} diff --git a/examples/react-wallet-kit/src/components/Disclosure.tsx b/examples/react-wallet-kit/src/components/Disclosure.tsx new file mode 100644 index 000000000..5ad6c46e6 --- /dev/null +++ b/examples/react-wallet-kit/src/components/Disclosure.tsx @@ -0,0 +1,113 @@ +import { + Disclosure, + DisclosureButton, + DisclosurePanel, + Transition, +} from "@headlessui/react"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faChevronDown } from "@fortawesome/free-solid-svg-icons"; +import { type ReactNode } from "react"; + +interface PanelDisclosureProps { + title: string; + icon?: ReactNode; + children: ReactNode; + defaultOpen?: boolean; +} + +export function PanelDisclosure(props: PanelDisclosureProps) { + const { title, icon, children, defaultOpen = true } = props; + return ( + + {({ open }) => ( +
+ +
+ {icon} + {title} +
+ + +
+ + + + {children} + + +
+ )} +
+ ); +} + +interface InputPanelDisclosureProps { + value: string; + setValue: (value: string) => void; + placeholder?: string; + children?: ReactNode; + defaultOpen?: boolean; +} + +export function InputPanelDisclosure({ + value, + setValue, + children, + defaultOpen = true, + placeholder, +}: InputPanelDisclosureProps) { + return ( + + {({ open }) => ( +
+
+ setValue(e.target.value)} + className="w-full shadow px-2 py-1 rounded-lg bg-background-light dark:bg-background-dark focus:outline-none" + placeholder={placeholder} + /> + + + +
+ + + + {children} + + +
+ )} +
+ ); +} diff --git a/examples/react-wallet-kit/src/components/Input.tsx b/examples/react-wallet-kit/src/components/Input.tsx new file mode 100644 index 000000000..a8c12a2a5 --- /dev/null +++ b/examples/react-wallet-kit/src/components/Input.tsx @@ -0,0 +1,30 @@ +import { Input } from "@headlessui/react"; +import React from "react"; + +interface TextInputFieldProps { + value: string; + onChange: (val: string) => void; + width?: number; + label?: string; + placeholder?: string; +} + +export function TextInputField(props: TextInputFieldProps) { + const { value, onChange, width = 40, label, placeholder } = props; + + return ( +
+ {label && {label}} + ) => + onChange(e.target.value) + } + placeholder={placeholder} + style={{ width }} + className={`rounded border border-gray-300 focus:outline-none focus:ring-2 focus:ring-primary-light dark:ring-primary-dark text-sm text-center h-7`} + /> +
+ ); +} diff --git a/examples/react-wallet-kit/src/components/Slider.tsx b/examples/react-wallet-kit/src/components/Slider.tsx new file mode 100644 index 000000000..738ad6700 --- /dev/null +++ b/examples/react-wallet-kit/src/components/Slider.tsx @@ -0,0 +1,42 @@ +import { Input } from "@headlessui/react"; + +interface SliderFieldProps { + value: number; + onChange: (val: number) => void; + min?: number; + max?: number; + step?: number; + label?: string; + suffix?: string; // This comes after the number, e.g., "px" for pixel values +} + +export function SliderField(props: SliderFieldProps) { + const { + value, + onChange, + min = 0, + max = 100, + step = 1, + label, + suffix, + } = props; + return ( +
+ {label && {label}} + ) => + onChange(Number(e.target.value)) + } + min={min} + max={max} + step={step} + /> + + {value} {suffix} + +
+ ); +} diff --git a/examples/react-wallet-kit/src/components/Spinners.tsx b/examples/react-wallet-kit/src/components/Spinners.tsx new file mode 100644 index 000000000..dada61296 --- /dev/null +++ b/examples/react-wallet-kit/src/components/Spinners.tsx @@ -0,0 +1,33 @@ +import clsx from "clsx"; + +interface SpinnerProps { + className?: string; + style?: React.CSSProperties; + strokeWidth?: number; +} + +export function Spinner(props: SpinnerProps) { + const { className, style, strokeWidth = 3, ...rest } = props; + return ( + + + + + + + ); +} diff --git a/examples/react-wallet-kit/src/components/Svg.tsx b/examples/react-wallet-kit/src/components/Svg.tsx new file mode 100644 index 000000000..f5c08abca --- /dev/null +++ b/examples/react-wallet-kit/src/components/Svg.tsx @@ -0,0 +1,316 @@ +interface SVGProps { + className?: string; + style?: React.CSSProperties; +} + +export function TurnkeyLogoSVG(props: SVGProps) { + return ( + + + + + + + ); +} + +export function TurnkeySVG(props: SVGProps) { + return ( + + + + + + + + + + + + + ); +} + +export function GoogleSVG(props: SVGProps) { + return ( + + + + ); +} + +export function AppleSVG(props: SVGProps) { + return ( + + + + ); +} + +export function FacebookSVG(props: SVGProps) { + return ( + + + + ); +} + +export function AddSVG(props: SVGProps) { + return ( + + + + ); +} + +export function UnlinkSVG(props: SVGProps) { + return ( + + + + ); +} + +export function MinusSVG(props: SVGProps) { + return ( + + + + ); +} + +export function KeySVG(props: SVGProps) { + return ( + + + + ); +} + +export function CheckboxCircleFillSVG(props: SVGProps) { + return ( + + + + ); +} + +export function EmailSVG(props: SVGProps) { + return ( + + + + ); +} + +export function PhoneSVG(props: SVGProps) { + return ( + + + + ); +} + +export function EditSVG(props: SVGProps) { + return ( + + + + ); +} + +export function DeleteSVG(props: SVGProps) { + return ( + + + + ); +} + +export function SolanaSVG(props: SVGProps) { + return ( + + + + + + + + + + + + + + ); +} + +export function EthereumSVG(props: SVGProps) { + return ( + + + + + + + + + + + ); +} + +export function ExportSVG(props: SVGProps) { + return ( + + + + ); +} + +export function ImportSVG(props: SVGProps) { + return ( + + + + ); +} diff --git a/examples/react-wallet-kit/src/components/Switch.tsx b/examples/react-wallet-kit/src/components/Switch.tsx new file mode 100644 index 000000000..4e05e489b --- /dev/null +++ b/examples/react-wallet-kit/src/components/Switch.tsx @@ -0,0 +1,57 @@ +import { Switch } from "@headlessui/react"; +import clsx from "clsx"; + +interface ToggleSwitchProps { + checked: boolean; + onChange: (val: boolean) => void; + disabled?: boolean; + size?: "sm" | "md"; + label?: string; + tooltip?: string; +} + +export function ToggleSwitch(props: ToggleSwitchProps) { + const { checked, onChange, size = "md", disabled, label, tooltip } = props; + const height = size === "sm" ? "h-4" : "h-5"; + const width = size === "sm" ? "w-8" : "w-10"; + const knobSize = size === "sm" ? "h-3 w-3" : "h-4 w-4"; + const translate = checked + ? size === "sm" + ? "translate-x-[1.05rem]" + : "translate-x-5" + : "translate-x-1"; + + return ( +
+ {label && {label}} + + + +
+ ); +} diff --git a/examples/react-wallet-kit/src/components/demo/AuthButtons/AuthenticatorButton.tsx b/examples/react-wallet-kit/src/components/demo/AuthButtons/AuthenticatorButton.tsx new file mode 100644 index 000000000..81872d427 --- /dev/null +++ b/examples/react-wallet-kit/src/components/demo/AuthButtons/AuthenticatorButton.tsx @@ -0,0 +1,31 @@ +import { KeySVG } from "@/components/Svg"; +import { AuthToggleButton } from "./index"; +import { useTurnkey } from "@turnkey/react-wallet-kit"; +import { toast } from "react-toastify"; + +export default function AuthenticatorButton({ + canRemoveAuthMethod, +}: { + canRemoveAuthMethod: boolean; +}) { + const { user, handleAddPasskey, handleRemovePasskey } = useTurnkey(); + const authenticator = user?.authenticators?.[0]; + + const notify = () => + toast.error("Error: Cannot remove your last authenticator."); + + return ( + } + isLinked={!!authenticator} + onAdd={handleAddPasskey} + canRemoveAuthMethod={canRemoveAuthMethod} + onRemove={() => { + handleRemovePasskey({ + authenticatorId: authenticator?.authenticatorId!, + }); + }} + /> + ); +} diff --git a/examples/react-wallet-kit/src/components/demo/AuthButtons/EmailAuthButton.tsx b/examples/react-wallet-kit/src/components/demo/AuthButtons/EmailAuthButton.tsx new file mode 100644 index 000000000..6ce4dc684 --- /dev/null +++ b/examples/react-wallet-kit/src/components/demo/AuthButtons/EmailAuthButton.tsx @@ -0,0 +1,24 @@ +import { EmailSVG } from "@/components/Svg"; +import { AuthToggleButton } from "./index"; +import { useTurnkey } from "@turnkey/react-wallet-kit"; + +export default function EmailAuthButton({ + canRemoveAuthMethod, +}: { + canRemoveAuthMethod: boolean; +}) { + const { user, handleAddEmail, handleRemoveUserEmail } = useTurnkey(); + + return ( + } + isLinked={!!user?.userEmail} + onAdd={handleAddEmail} + canRemoveAuthMethod={canRemoveAuthMethod} + onRemove={() => { + handleRemoveUserEmail(); + }} + /> + ); +} diff --git a/examples/react-wallet-kit/src/components/demo/AuthButtons/PhoneAuthButton.tsx b/examples/react-wallet-kit/src/components/demo/AuthButtons/PhoneAuthButton.tsx new file mode 100644 index 000000000..50bd96c1c --- /dev/null +++ b/examples/react-wallet-kit/src/components/demo/AuthButtons/PhoneAuthButton.tsx @@ -0,0 +1,25 @@ +import { PhoneSVG } from "@/components/Svg"; +import { AuthToggleButton } from "./index"; +import { useTurnkey } from "@turnkey/react-wallet-kit"; + +export default function PhoneAuthButton({ + canRemoveAuthMethod, +}: { + canRemoveAuthMethod: boolean; +}) { + const { user, handleAddPhoneNumber, handleRemoveUserPhoneNumber } = + useTurnkey(); + + return ( + } + isLinked={!!user?.userPhoneNumber} + onAdd={handleAddPhoneNumber} + canRemoveAuthMethod={canRemoveAuthMethod} + onRemove={() => { + handleRemoveUserPhoneNumber({}); + }} + /> + ); +} diff --git a/examples/react-wallet-kit/src/components/demo/AuthButtons/SocialButton.tsx b/examples/react-wallet-kit/src/components/demo/AuthButtons/SocialButton.tsx new file mode 100644 index 000000000..3b4572f68 --- /dev/null +++ b/examples/react-wallet-kit/src/components/demo/AuthButtons/SocialButton.tsx @@ -0,0 +1,38 @@ +import { AuthToggleButton } from "./index"; +import { useTurnkey } from "@turnkey/react-wallet-kit"; +import { OAuthProviders } from "@turnkey/sdk-types"; + +interface SocialButtonProps { + canRemoveAuthMethod: boolean; + provider: OAuthProviders; + logo: React.ReactNode; +} + +export default function SocialButton({ + provider, + logo, + canRemoveAuthMethod, +}: SocialButtonProps) { + const { user, handleAddOauthProvider, handleRemoveOauthProvider } = + useTurnkey(); + + const existingProvider = user?.oauthProviders.find( + (p) => p.providerName.toLowerCase() === provider.toLowerCase(), + ); + + return ( + handleAddOauthProvider({ providerName: provider })} + canRemoveAuthMethod={canRemoveAuthMethod} + onRemove={() => { + existingProvider && + handleRemoveOauthProvider({ + providerId: existingProvider.providerId, + }); + }} + /> + ); +} diff --git a/examples/react-wallet-kit/src/components/demo/AuthButtons/index.tsx b/examples/react-wallet-kit/src/components/demo/AuthButtons/index.tsx new file mode 100644 index 000000000..2d111bed0 --- /dev/null +++ b/examples/react-wallet-kit/src/components/demo/AuthButtons/index.tsx @@ -0,0 +1,58 @@ +import { AddSVG, UnlinkSVG } from "@/components/Svg"; +import clsx from "clsx"; +import { useState } from "react"; +import { toast } from "react-toastify"; + +interface AuthToggleButtonProps { + label: string; + icon: React.ReactNode; + isLinked: boolean; + canRemoveAuthMethod: boolean; + onAdd: () => void; + onRemove: () => void; +} + +export function AuthToggleButton(props: AuthToggleButtonProps) { + const { label, icon, isLinked, onAdd, onRemove, canRemoveAuthMethod } = props; + const handleClick = () => { + if (isLinked) { + if (!canRemoveAuthMethod) { + setShaking(true); + setTimeout(() => setShaking(false), 500); + toast.error("Error: Cannot remove your last authenticator."); + return; + } + onRemove(); + } else { + onAdd(); + } + }; + + const [shaking, setShaking] = useState(false); + + return ( + + ); +} diff --git a/examples/react-wallet-kit/src/components/demo/ConfigViewer.tsx b/examples/react-wallet-kit/src/components/demo/ConfigViewer.tsx new file mode 100644 index 000000000..03cb50663 --- /dev/null +++ b/examples/react-wallet-kit/src/components/demo/ConfigViewer.tsx @@ -0,0 +1,119 @@ +import { useTurnkeyConfig } from "@/providers/config/ConfigProvider"; +import { faCheck, faCopy } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { Button, Transition } from "@headlessui/react"; +import clsx from "clsx"; +import { useState } from "react"; + +const envVars: Record = { + authProxyConfigId: '""', + organizationId: '""', +}; + +const omitKeys = [ + "apiBaseUrl", + "authProxyUrl", + "importIframeUrl", + "exportIframeUrl", + "googleClientId", + "appleClientId", + "facebookClientId", + "oauthRedirectUri", + "walletConfig", + "renderModalInProvider", +]; + +function renderValue(value: any, indentLevel = 2, key?: string): string { + const indent = " ".repeat(indentLevel); + + if (key && envVars[key]) { + return envVars[key]; + } + + if (Array.isArray(value)) { + const items = value + .map((item) => `${indent}${renderValue(item, indentLevel + 2)}`) + .join(",\n"); + return `[\n${items}\n${" ".repeat(indentLevel - 2)}]`; + } + + if (typeof value === "object" && value !== null) { + const entries = Object.entries(value) + .filter(([nestedKey]) => !omitKeys.includes(nestedKey)) // Omit specified keys + .map( + ([nestedKey, nestedValue]) => + `${indent}${nestedKey}: ${renderValue(nestedValue, indentLevel + 2, nestedKey)}`, + ) + .join(",\n"); + return `{\n${entries}\n${" ".repeat(indentLevel - 2)}}`; + } + + return typeof value === "string" ? `"${value}"` : String(value); +} + +export default function ConfigViewer() { + const { config } = useTurnkeyConfig(); + const [showCopied, setShowCopied] = useState(false); + + const handleCopy = () => { + setShowCopied(true); + navigator.clipboard.writeText( + `{\n${Object.entries(config) + .filter(([key]) => !omitKeys.includes(key)) // Omit specified keys + .map(([key, value]) => ` ${key}: ${renderValue(value, 4, key)}`) + .join(",\n")}\n}`, + ); + setTimeout(() => { + setShowCopied(false); + }, 1500); + }; + + return ( +
+
+        {`{\n${Object.entries(config)
+          .filter(([key]) => !omitKeys.includes(key)) // Omit specified keys
+          .map(([key, value]) => `  ${key}: ${renderValue(value, 4, key)}`)
+          .join(",\n")}\n}`}
+      
+ +
+ + Config copied to clipboard! + +
+
+ + +
+ ); +} diff --git a/examples/react-wallet-kit/src/components/demo/DeleteSubOrgWarning.tsx b/examples/react-wallet-kit/src/components/demo/DeleteSubOrgWarning.tsx new file mode 100644 index 000000000..144ed3400 --- /dev/null +++ b/examples/react-wallet-kit/src/components/demo/DeleteSubOrgWarning.tsx @@ -0,0 +1,96 @@ +import { + faCheck, + faTriangleExclamation, +} from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { Button, Checkbox } from "@headlessui/react"; +import { useModal, useTurnkey, WalletSource } from "@turnkey/react-wallet-kit"; +import { useState } from "react"; +import { Spinner } from "../Spinners"; + +export default function DeleteSubOrgWarning() { + const { session, user, wallets, deleteSubOrganization, logout } = + useTurnkey(); + const { isMobile, closeModal } = useModal(); + + const [deleteWithoutExport, setDeleteWithoutExport] = useState(false); + const [isLoading, setIsLoading] = useState(false); + + const handleContinue = async () => { + try { + setIsLoading(true); + await deleteSubOrganization({ + deleteWithoutExport: true, + }); + closeModal(); + logout(); + } catch (error) { + console.error("Error deleting sub-organization:", error); + } finally { + setIsLoading(false); + } + }; + + const unExportedWallets = wallets.filter( + (wallet) => !wallet.exported && wallet.source !== WalletSource.Connected, + ); + + return ( +
+
+ +
Delete Account
+
+ This action is irreversible. +
+
+
+ Sub-org ID: {session!.organizationId} +
+ + {unExportedWallets.length > 0 && + unExportedWallets.map((wallet) => ( +
+ Wallet: {wallet.walletName} (Unexported) +
+ ))} +
+
+ {unExportedWallets.length > 0 && ( +
+ setDeleteWithoutExport(checked)} + className="group flex items-center justify-center size-4 rounded border text-icon-background-light dark:text-icon-background-dark bg-icon-background-light dark:bg-icon-background-dark data-checked:text-danger-text-light dark:data-checked:text-danger-text-dark data-checked:bg-danger-light dark:data-checked:bg-danger-dark border-icon-text-light dark:border-icon-text-dark focus:outline-none focus:ring-2 focus:ring-danger-light dark:focus:ring-danger-dark transition-all" + > + {/* Checkmark icon */} + + + + Delete without exporting my wallets + +
+ )} + +
+ +
+
+ ); +} diff --git a/examples/react-wallet-kit/src/components/demo/DemoPanel.tsx b/examples/react-wallet-kit/src/components/demo/DemoPanel.tsx new file mode 100644 index 000000000..64734b15c --- /dev/null +++ b/examples/react-wallet-kit/src/components/demo/DemoPanel.tsx @@ -0,0 +1,460 @@ +"use client"; + +import { + Menu, + MenuButton, + MenuItem, + MenuItems, + Field, + Label, + Radio, + RadioGroup, + Button, + Transition, +} from "@headlessui/react"; +import { + ConnectedWallet, + ExportType, + useModal, + useTurnkey, + Wallet, + WalletAccount, + WalletSource, +} from "@turnkey/react-wallet-kit"; +import { useEffect, useState } from "react"; +import { EthereumSVG, SolanaSVG } from "../Svg"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { + faAdd, + faArrowDown, + faArrowUp, + faArrowUpRightFromSquare, + faChevronDown, + faPlus, + faRss, + faWallet, +} from "@fortawesome/free-solid-svg-icons"; +import { + verifyEthSignatureWithAddress, + verifySolSignatureWithAddress, +} from "@/utils"; +import SignatureVerification from "./SignatureVerification"; +import Image from "next/image"; + +export default function DemoPanel() { + const { + wallets, + createWalletAccounts, + createWallet, + fetchWallets, + handleSignMessage, + handleExportWallet, + handleImportWallet, + handleLinkExternalWallet, + getWalletProviders, + } = useTurnkey(); + + const { pushPage } = useModal(); + + const [selectedWallet, setSelectedWallet] = useState( + wallets[0] || null, // Initialize with null if wallets[0] is undefined + ); + const [selectedWalletAccount, setSelectedWalletAccount] = useState< + WalletAccount | undefined + >(wallets[0]?.accounts[0] || null); // Initialize with null if no accounts exist + + const [connectedWallets, setConnectedWallets] = useState< + ConnectedWallet[] | undefined + >([]); // Initialize with an empty array + const [connectedWalletIcons, setConnectedWalletIcons] = useState( + [], + ); // Initialize with an empty array + + useEffect(() => { + const getConnectedWalletIcons = async (): Promise => { + const res = await getWalletProviders(); + const providersVisited = new Set(); + let icons: string[] = []; + for (const provider of res) { + if ( + provider.connectedAddresses.length > 0 && + !providersVisited.has(provider.info.name) + ) { + providersVisited.add(provider.info.name); + icons.push(provider.info.icon ? provider.info.icon : ""); + } + } + return icons; + }; + + if (!selectedWallet) { + setSelectedWallet(wallets[0]); + } + if (!selectedWalletAccount && wallets[0]?.accounts.length > 0) { + setSelectedWalletAccount(wallets[0].accounts[0]); + } + + const cw = wallets.filter( + (w) => w.source === WalletSource.Connected, + ) as ConnectedWallet[]; + if (cw) { + getConnectedWalletIcons().then((icons) => { + if (icons && icons.length > 0) setConnectedWalletIcons(icons); + }); + setConnectedWallets(cw); + } else { + setConnectedWallets(undefined); + } + }, [wallets]); + + function truncateAddress(address: string) { + return `${address.slice(0, 4)}...${address.slice(-4)}`; + } + + return ( + +
+
+
+ + +
+
+

+ {selectedWallet?.walletName} +

+
+ {selectedWallet?.source === WalletSource.Connected ? ( + + ) : ( + + )} +
+ +
+
+
+ + {wallets.length > 0 && + wallets.map((wallet) => { + if (wallet.walletId !== selectedWallet?.walletId) + return ( + +
+ +
+
+ ); + })} + {wallets.length !== 1 && ( +
+ )} + + + +
+
+ +
+ {selectedWallet?.accounts && selectedWallet?.accounts.length > 0 ? ( + + {selectedWallet?.accounts.map((account) => ( + + + + + + + ))} + + ) : ( + + )} + + + {selectedWallet?.source === WalletSource.Embedded && ( + <> +
+ +
+ + +
+ + )} +
+
+
+ ); +} + +const StackedImg = ({ + connectedWalletIcons, +}: { + connectedWalletIcons: (string | undefined)[]; +}) => { + return ( +
+ {connectedWalletIcons.map((icon, index) => + icon && index < 2 ? ( + {`Wallet 0 ? "-ml-3" : ""}`} + /> + ) : null, + )} + {connectedWalletIcons.length > 2 && ( + + +{connectedWalletIcons.length - 2} + + )} +
+ ); +}; + +const ConnectedWalletIcon = () => { + return ( +
+ + +
+ ); +}; + +const EmbeddedWalletIcon = () => { + return ( +
+ +
+ ); +}; diff --git a/examples/react-wallet-kit/src/components/demo/SignatureVerification.tsx b/examples/react-wallet-kit/src/components/demo/SignatureVerification.tsx new file mode 100644 index 000000000..14718c226 --- /dev/null +++ b/examples/react-wallet-kit/src/components/demo/SignatureVerification.tsx @@ -0,0 +1,73 @@ +import { faCheck, faXmark } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { useEffect, useState } from "react"; + +export default function SignatureVerification({ + verificationPassed, + signature, +}: { + verificationPassed: boolean; + signature: string | null; +}) { + const [scale, setScale] = useState(0); + const [pulsing, setPulsing] = useState(false); + + useEffect(() => { + setScale(1); + const pulseTimer = setTimeout(() => { + setPulsing(true); + }, 300); + return () => { + clearTimeout(pulseTimer); + }; + }, []); + + return ( +
+
+
+ + {pulsing && verificationPassed && ( + + )} +
+
+
+

+ {verificationPassed + ? "Signature Verified" + : "Signature Verification Failed"} +

+ {verificationPassed && ( +

+ The address used to sign the message matches your wallet address. +

+ )} + + {signature && ( +

+ {signature} +

+ )} +
+
+ ); +} diff --git a/examples/react-wallet-kit/src/components/demo/UserSettings.tsx b/examples/react-wallet-kit/src/components/demo/UserSettings.tsx new file mode 100644 index 000000000..a7b4b630e --- /dev/null +++ b/examples/react-wallet-kit/src/components/demo/UserSettings.tsx @@ -0,0 +1,192 @@ +import { useModal, useTurnkey } from "@turnkey/react-wallet-kit"; +import { OAuthProviders } from "@turnkey/sdk-types"; +import { + AppleSVG, + CheckboxCircleFillSVG, + DeleteSVG, + EditSVG, + FacebookSVG, + GoogleSVG, +} from "../Svg"; +import EmailAuthButton from "./AuthButtons/EmailAuthButton"; +import PhoneAuthButton from "./AuthButtons/PhoneAuthButton"; +import SocialButton from "./AuthButtons/SocialButton"; +import AuthenticatorButton from "./AuthButtons/AuthenticatorButton"; +import DeleteSubOrgWarning from "./DeleteSubOrgWarning"; +import { Button, Transition } from "@headlessui/react"; +import { useEffect, useRef, useState } from "react"; + +export default function UserSettings() { + const { + user, + handleAddEmail, + handleAddPhoneNumber, + handleUpdateUserName, + config: clientConfig, + logout, + } = useTurnkey(); + + const { pushPage } = useModal(); + + const [canRemoveAuthMethod, setCanRemoveAuthMethod] = useState(false); + + useEffect(() => { + if (!user) return setCanRemoveAuthMethod(false); + const userAuthMethods = + (user?.authenticators?.length || 0) + + (user?.oauthProviders?.length || 0) + + (user?.apiKeys?.filter((apiKey) => + apiKey.apiKeyName.startsWith("wallet-auth"), + ).length || 0) + + (user?.userEmail ? 1 : 0) + + (user?.userPhoneNumber ? 1 : 0); + setCanRemoveAuthMethod(userAuthMethods > 1); + }, [user]); + + function handleDeleteSubOrganization() { + pushPage({ + key: "Delete Sub-Organization", + content: , + preventBack: true, + showTitle: false, + }); + } + + return ( + +
+
+

Manage Account

+
+ { + return await handleUpdateUserName(); + }} + /> + {user?.userEmail && ( + { + return await handleAddEmail(); + }} + verified={true} + /> + )} + {user?.userPhoneNumber && ( + { + return await handleAddPhoneNumber(); + }} + verified={true} + /> + )} +
+
+

Auth Methods

+
+
+ {clientConfig?.auth?.methods?.emailOtpAuthEnabled && ( + + )} + {clientConfig?.auth?.methods?.smsOtpAuthEnabled && ( + + )} + {clientConfig?.auth?.methods?.googleOauthEnabled && ( + } + /> + )} + {clientConfig?.auth?.methods?.appleOauthEnabled && ( + } + /> + )} + {clientConfig?.auth?.methods?.facebookOauthEnabled && ( + } + /> + )} + {clientConfig?.auth?.methods?.passkeyAuthEnabled && ( + + )} +
+
+
+
+ + +
+
+
+
+ ); +} + +const AccountParam = ({ + label, + value, + onClick, + verified, +}: { + label: string; + value: string | undefined; + onClick: () => Promise; + verified?: boolean | undefined; +}) => { + return ( +
+ + +
+ ); +}; diff --git a/examples/react-wallet-kit/src/constants.ts b/examples/react-wallet-kit/src/constants.ts new file mode 100644 index 000000000..aab886516 --- /dev/null +++ b/examples/react-wallet-kit/src/constants.ts @@ -0,0 +1,105 @@ +import { + CreateSubOrgParams, + TurnkeyProviderConfig, +} from "@turnkey/react-wallet-kit"; + +export const createSuborgParams: CreateSubOrgParams = { + customWallet: { + walletName: "Wallet 1", + walletAccounts: [ + { + addressFormat: "ADDRESS_FORMAT_ETHEREUM", + curve: "CURVE_SECP256K1", + pathFormat: "PATH_FORMAT_BIP32", + path: "m/44'/60'/0'/0/0", + }, + { + addressFormat: "ADDRESS_FORMAT_SOLANA", + curve: "CURVE_ED25519", + pathFormat: "PATH_FORMAT_BIP32", + path: "m/44'/501'/0'/0/0", + }, + ], + }, +}; + +export const initialConfig: TurnkeyProviderConfig = { + apiBaseUrl: process.env.NEXT_PUBLIC_BASE_URL || "https://api.turnkey.com", + authProxyUrl: + process.env.NEXT_PUBLIC_AUTH_PROXY_URL || "https://authproxy.turnkey.com", + authProxyConfigId: process.env.NEXT_PUBLIC_AUTH_PROXY_ID!, + organizationId: process.env.NEXT_PUBLIC_ORGANIZATION_ID!, + importIframeUrl: + process.env.NEXT_PUBLIC_IMPORT_IFRAME_URL || "https://import.turnkey.com", + exportIframeUrl: + process.env.NEXT_PUBLIC_EXPORT_IFRAME_URL || "https://export.turnkey.com", + auth: { + oauthConfig: { + googleClientId: process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID, + facebookClientId: process.env.NEXT_PUBLIC_FACEBOOK_CLIENT_ID, + appleClientId: process.env.NEXT_PUBLIC_APPLE_CLIENT_ID, + oauthRedirectUri: process.env.NEXT_PUBLIC_OAUTH_REDIRECT_URI, + openOauthInPage: true, + }, + methods: { + emailOtpAuthEnabled: true, + smsOtpAuthEnabled: false, + passkeyAuthEnabled: true, + walletAuthEnabled: true, + googleOauthEnabled: true, + appleOauthEnabled: false, + facebookOauthEnabled: false, + }, + methodOrder: ["socials", "email", "sms", "passkey", "wallet"], + oauthOrder: ["google", "apple", "facebook"], + autoRefreshSession: true, + createSuborgParams: { + emailOtpAuth: createSuborgParams, + smsOtpAuth: createSuborgParams, + passkeyAuth: createSuborgParams, + walletAuth: createSuborgParams, + oauth: createSuborgParams, + }, + }, + ui: { + darkMode: true, + borderRadius: 16, + backgroundBlur: 8, + renderModalInProvider: true, // This is needed for the config panel to push the modal over + colors: { + light: { + primary: "#335bf9", + modalBackground: "#f5f7fb", + }, + dark: { + primary: "#335bf9", + modalBackground: "#0b0b0b", + }, + }, + }, + walletConfig: { + features: { + auth: true, + connecting: true, + }, + chains: { + ethereum: { + native: true, + walletConnectNamespaces: ["eip155:1"], + }, + solana: { + native: true, + walletConnectNamespaces: ["solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"], + }, + }, + walletConnect: { + projectId: process.env.NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID!, + appMetadata: { + name: "Turnkey Wallet", + description: "A wallet for Turnkey", + url: process.env.NEXT_PUBLIC_WALLETCONNECT_PROJECT_URL!, + icons: ["/favicon.svg"], + }, + }, + }, +}; diff --git a/examples/react-wallet-kit/src/providers/config/ConfigProvider.tsx b/examples/react-wallet-kit/src/providers/config/ConfigProvider.tsx new file mode 100644 index 000000000..c1a804161 --- /dev/null +++ b/examples/react-wallet-kit/src/providers/config/ConfigProvider.tsx @@ -0,0 +1,233 @@ +"use client"; + +import { + createContext, + useContext, + useState, + ReactNode, + useEffect, +} from "react"; +import { Button, Transition } from "@headlessui/react"; +import { TurnkeyConfigPanel } from "./Panel"; +import clsx from "clsx"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { + faBars, + faCaretDown, + faClose, +} from "@fortawesome/free-solid-svg-icons"; +import { ThreeDimensionalBackground } from "@/components/3D/Background"; +import { TurnkeySVG } from "@/components/Svg"; +import { isHardwareAccelerationEnabled, kebab, useScreenSize } from "@/utils"; +import { Slide, ToastContainer } from "react-toastify"; +import { DemoConfig } from "@/types"; +import { + TurnkeyProviderConfig, + TurnkeyCallbacks, + TurnkeyProvider, +} from "@turnkey/react-wallet-kit"; + +type ConfigContextValue = { + config: TurnkeyProviderConfig; + initialConfig: TurnkeyProviderConfig; + demoConfig: DemoConfig; + hardwareAccelerationEnabled: boolean; + setConfig: ( + newConfig: Partial, + demoConfig?: Partial, + ) => void; +}; + +const ConfigContext = createContext(undefined); + +export function useTurnkeyConfig() { + const ctx = useContext(ConfigContext); + if (!ctx) throw new Error("Must be used inside TurnkeyConfigProvider"); + return ctx; +} + +interface TurnkeyConfigProviderProps { + initialConfig: TurnkeyProviderConfig; + callbacks?: TurnkeyCallbacks; + children: ReactNode; +} + +export function TurnkeyConfigProvider({ + initialConfig, + callbacks, + children, +}: TurnkeyConfigProviderProps) { + const [config, setConfigState] = useState(initialConfig); + const [demoConfig, setDemoConfig] = useState({ + backgroundEnabled: true, + }); + const [panelOpen, setPanelOpen] = useState(false); + const { isMobile } = useScreenSize(); + + const [hardwareAccelerationEnabled, setHardwareAccelerationEnabled] = + useState(false); + + const panelWidth = 384; + const setConfig = ( + newConfig: Partial, + demoConfig?: Partial, + ) => { + setConfigState((prev) => ({ ...prev, ...newConfig })); + setDemoConfig((prev) => ({ ...prev, ...demoConfig })); + }; + + useEffect(() => { + setHardwareAccelerationEnabled(isHardwareAccelerationEnabled()); + }, []); + + const generateCSSVars = (theme?: Partial) => { + if (!theme?.ui?.light) return ""; + return Object.entries(theme.ui.light) + .map(([key, value]) => `--color-${kebab(key)}-light: ${value};`) + .join("\n"); + }; + + const generateDarkCSSVars = (theme?: Partial) => { + if (!theme?.ui?.dark) return ""; + return Object.entries(theme.ui.dark) + .map(([key, value]) => `--color-${kebab(key)}-dark: ${value};`) + .join("\n"); + }; + + useEffect(() => { + if (isMobile) { + setPanelOpen(false); + } else { + setPanelOpen(true); + } + }, [isMobile]); + + return ( + + +
+ {/* Sliding Config Panel */} + +
+
+

Wallet Kit Config

+ +
+ + +
+
+ + + + + + {/* Content (shifted when panel is open) */} +
+ + +
{children}
+
+
+
+ + + + + + +
+ @turnkey/react-wallet-kit +
+
+ +
+
+
+
+ This is purely a demo app for the Turnkey React Wallet Kit. You will + not receive any real tokens or rewards. +
+
+
+ + ); +} diff --git a/examples/react-wallet-kit/src/providers/config/Panel.tsx b/examples/react-wallet-kit/src/providers/config/Panel.tsx new file mode 100644 index 000000000..00e2cd14f --- /dev/null +++ b/examples/react-wallet-kit/src/providers/config/Panel.tsx @@ -0,0 +1,460 @@ +import { + faGamepad, + faGears, + faGripLines, + faPalette, + faUserLock, +} from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; + +import { Draggable, DragDropContext, Droppable } from "@hello-pangea/dnd"; +import { useTurnkeyConfig } from "./ConfigProvider"; +import { ToggleSwitch } from "@/components/Switch"; +import { SliderField } from "@/components/Slider"; +import { ColourPicker } from "@/components/Color"; +import { PanelDisclosure } from "@/components/Disclosure"; +import { useEffect } from "react"; +import { TurnkeyProviderConfig } from "@turnkey/react-wallet-kit"; +import ConfigViewer from "@/components/demo/ConfigViewer"; +import { completeTheme, textColour } from "@/utils"; +import { Button } from "@headlessui/react"; +import { DemoConfig } from "@/types"; + +interface AuthMethod { + name: string; + toggles: { toggle: string; overrideDisplayName?: string }[]; + order: "socials" | "email" | "sms" | "passkey" | "wallet"; +} + +const authMethods: AuthMethod[] = [ + { + name: "Socials", + toggles: [ + { overrideDisplayName: "Google", toggle: "googleOauthEnabled" }, + { overrideDisplayName: "Apple", toggle: "appleOauthEnabled" }, + { overrideDisplayName: "Facebook", toggle: "facebookOauthEnabled" }, + ], + order: "socials", + }, + { + name: "Email OTP", + toggles: [{ toggle: "emailOtpAuthEnabled" }], + order: "email", + }, + { name: "SMS OTP", toggles: [{ toggle: "smsOtpAuthEnabled" }], order: "sms" }, + { + name: "Passkey", + toggles: [{ toggle: "passkeyAuthEnabled" }], + order: "passkey", + }, + { + name: "Wallet", + toggles: [{ toggle: "walletAuthEnabled" }], + order: "wallet", + }, +]; + +export function TurnkeyConfigPanel() { + const { + config, + demoConfig, + initialConfig, + hardwareAccelerationEnabled, + setConfig, + } = useTurnkeyConfig(); + + const handleDragEnd = (result: any) => { + if (!result.destination) return; + + const currentOrder = config.auth?.methodOrder ?? []; + const reordered = Array.from(currentOrder); + const [moved] = reordered.splice(result.source.index, 1); + reordered.splice(result.destination.index, 0, moved); + + handleSetConfig({ + auth: { + ...config.auth, + methodOrder: reordered, + }, + }); + }; + + const handleSetConfig = async ( + newConfig: Partial, + newDemoConfig?: Partial, + ) => { + setConfig({ ...config, ...newConfig }, { ...demoConfig, ...newDemoConfig }); + storeConfig( + { ...config, ...newConfig }, + { ...demoConfig, ...newDemoConfig }, + ); + }; + + // Store config in local storage + const storeConfig = ( + config: Partial, + demoConfig?: Partial, + ) => { + localStorage.setItem("turnkeyConfig", JSON.stringify(config)); + localStorage.setItem("turnkeyDemoConfig", JSON.stringify(demoConfig)); + }; + + useEffect(() => { + // Load config from local storage + const loadConfig = () => { + const storedConfig = localStorage.getItem("turnkeyConfig"); + const storedDemoConfig = localStorage.getItem("turnkeyDemoConfig"); + if (storedConfig) { + setConfig(JSON.parse(storedConfig)); + } + if (storedDemoConfig) { + setConfig({}, JSON.parse(storedDemoConfig)); + } + }; + loadConfig(); + }, []); + + return ( +
+ {/* Auth Methods with Reordering & Toggle */} + } + title="Auth" + > + + + {(provided) => ( +
+ {(config.auth?.methodOrder ?? []).map((methodKey, index) => { + const method = authMethods.find( + (m) => m.order === methodKey, + )!; + const someEnabled = method.toggles.some( + (key) => + config.auth?.methods?.[ + key.toggle as keyof typeof config.auth.methods + ] ?? false, + ); + return ( + + {(provided) => ( +
+
+ + {/* Top Row: Name + Master Toggle */} +
+ { + const newToggles = method.toggles.reduce( + (acc, { toggle }) => { + acc[toggle] = val; + return acc; + }, + {} as Record, + ); + + handleSetConfig({ + auth: { + ...config.auth, + methods: { + ...config.auth?.methods, + ...newToggles, + }, + }, + }); + }} + /> +
+
+ + {/* Individual Toggles */} + {method.toggles.length > 1 && ( +
+ {method.toggles.map((toggleKey) => ( + + handleSetConfig({ + auth: { + ...config.auth, + methods: { + ...config.auth?.methods, + [toggleKey.toggle]: val, + }, + }, + }) + } + /> + ))} + + {method.name === "Socials" && ( + <> +
+ + handleSetConfig({ + auth: { + ...config.auth, + oauthConfig: { + ...config.auth?.oauthConfig, + openOauthInPage: val, + }, + }, + }) + } + /> + + )} +
+ )} +
+ )} + + ); + })} + + {provided.placeholder} +
+ )} + + + + + {/* UI Toggles */} + }> + <> + + handleSetConfig({ + ui: { + ...config.ui, + darkMode: val, + }, + }) + } + /> + { + const primaryText = textColour(val); + handleSetConfig({ + ui: { + ...config.ui, + colors: !config.ui?.darkMode + ? { + ...config.ui?.colors, + light: { + ...config.ui?.colors?.light, + primary: val, + primaryText, + }, + } + : { + ...config.ui?.colors, + dark: { + ...config.ui?.colors?.dark, + primary: val, + primaryText, + }, + }, + }, + }); + }} + /> + { + const newColors = completeTheme(val); + + handleSetConfig( + { + ui: { + ...config.ui, + colors: !config.ui?.darkMode + ? { + ...config.ui?.colors, + light: { + ...config.ui?.colors?.light, + modalBackground: val, + modalText: textColour(val, true), + iconBackground: newColors.iconBackground, + iconText: newColors.iconText, + button: newColors.buttonBackground, + }, + } + : { + ...config.ui?.colors, + dark: { + ...config.ui?.colors?.dark, + modalBackground: val, + modalText: textColour(val, true), + iconBackground: newColors.iconBackground, + iconText: newColors.iconText, + button: newColors.buttonBackground, + }, + }, + }, + }, + { + ui: !config.ui?.darkMode + ? { + ...demoConfig.ui, + light: { + background: newColors.background, + text: textColour(newColors.background, true), + panelBackground: newColors.panelBackground, + draggableBackground: newColors.draggableBackground, + }, + } + : { + ...demoConfig.ui, + dark: { + background: newColors.background, + text: textColour(newColors.background, true), + panelBackground: newColors.panelBackground, + draggableBackground: newColors.draggableBackground, + }, + }, + }, + ); + }} + /> + + + handleSetConfig({ + ui: { + ...config.ui, + borderRadius: val || 0, + }, + }) + } + /> + + + handleSetConfig({ + ui: { + ...config.ui, + backgroundBlur: val || 0, + }, + }) + } + /> + + + handleSetConfig({ + ui: { + ...config.ui, + preferLargeActionButtons: val, + }, + }) + } + /> + + + } + > +

+ These settings are just for the demo, they do not affect the + TurnkeyProvider config. +

+ + handleSetConfig({}, { backgroundEnabled: val, ui: demoConfig.ui }) + } + /> +
+ }> +

+ Paste this config into your TurnkeyProvider config to use in your own + app. +

+ +
+ +
+ ); +} diff --git a/examples/react-wallet-kit/src/types.ts b/examples/react-wallet-kit/src/types.ts new file mode 100644 index 000000000..0a9a20344 --- /dev/null +++ b/examples/react-wallet-kit/src/types.ts @@ -0,0 +1,17 @@ +export interface DemoConfig { + backgroundEnabled: boolean; + ui?: { + light?: { + background: string; + text: string; + panelBackground: string; + draggableBackground: string; + }; + dark?: { + background: string; + text: string; + panelBackground: string; + draggableBackground: string; + }; + }; +} diff --git a/examples/react-wallet-kit/src/utils.ts b/examples/react-wallet-kit/src/utils.ts new file mode 100644 index 000000000..28dab3c95 --- /dev/null +++ b/examples/react-wallet-kit/src/utils.ts @@ -0,0 +1,309 @@ +import { useState, useEffect } from "react"; +import { PublicKey } from "@solana/web3.js"; +import nacl from "tweetnacl"; +import { Buffer } from "buffer"; + +import { hashMessage, recoverAddress } from "ethers"; + +// Custom hook to get the current screen size +export function useScreenSize() { + const [width, setWidth] = useState( + typeof window !== "undefined" ? window.innerWidth : 1024, + ); + + useEffect(() => { + const handleResize = () => setWidth(window.innerWidth); + window.addEventListener("resize", handleResize); + return () => window.removeEventListener("resize", handleResize); + }, []); + + return { + width, + isMobile: width < 640, + }; +} + +// Utility to get theme based on modal background +export function completeTheme(modalBackgroundColour: string) { + const { L, C, h } = hexToOklch(modalBackgroundColour); + + const isLight = L > 0.7; + + const iconBackgroundLMultiplier = isLight ? 0.8 : 1.5; + const iconTextLMultiplier = isLight ? 0.3 : 6; + const buttonBackgroundLMultiplier = isLight ? 1.1 : 1.3; + const backgroundLMultiplier = isLight ? 0.85 : 0.9; + const draggableBackgroundLMultiplier = isLight ? 0.9 : 0.7; + const panelBackgroundLMultiplier = isLight ? 0.95 : 0.7; + + const iconBackgroundL = isLight + ? Math.max(L * iconBackgroundLMultiplier, 0.95) + : Math.max(L * iconBackgroundLMultiplier, 0.2); + const iconTextL = isLight + ? Math.min(L * iconTextLMultiplier, 0.9) + : Math.max(L * iconTextLMultiplier, 0.7); + + const buttonBackgroundL = isLight + ? Math.min(L * buttonBackgroundLMultiplier, 0.95) + : Math.max(L * buttonBackgroundLMultiplier, 0.2); + + const backgroundL = isLight + ? L > 0.9 + ? 0.9 + : Math.min(L * backgroundLMultiplier, 0.9) + : Math.max(L * backgroundLMultiplier, 0.25); + const draggableBackgroundL = isLight + ? Math.min(L * draggableBackgroundLMultiplier, 0.9) + : Math.max(L * draggableBackgroundLMultiplier, 0.3); + const panelBackgroundL = isLight + ? Math.min(L * panelBackgroundLMultiplier, 1) + : Math.max(L * panelBackgroundLMultiplier, 0.2); + + const iconBackground = oklchToHex({ L: iconBackgroundL, C, h }); + const iconText = oklchToHex({ L: iconTextL, C, h }); + const buttonBackground = oklchToHex({ L: buttonBackgroundL, C, h }); + const background = oklchToHex({ L: backgroundL, C, h }); + const draggableBackground = oklchToHex({ L: draggableBackgroundL, C, h }); + const panelBackground = oklchToHex({ L: panelBackgroundL, C, h }); + + return { + iconBackground, + iconText, + buttonBackground, + background, + draggableBackground, + panelBackground, + }; +} + +// Utility to get primary-text color based on primary-colour +export function textColour(colour: string, highContrast = false) { + // Use OKLCh for perceptual lightness + const { L, C, h } = hexToOklch(colour); + const isLight = L > 0.5; + + // Use pure black or white for maximum contrast + return isLight + ? oklchToHex({ L: !highContrast ? 0.2 : 0.05, C, h }) + : oklchToHex({ L: !highContrast ? 0.9 : 1.5, C, h }); +} + +export function logoColour(colour: string) { + // Use OKLCh for perceptual lightness + const { L, C, h } = hexToOklch(colour); + const isLight = L > 0.6; + + // Use a slightly darker or lighter shade for logo + return isLight ? oklchToHex({ L: 0.5, C, h }) : oklchToHex({ L: 0.7, C, h }); +} + +// parse a hex string into [r,g,b] in 0–1 +function hexToRgb01(hex: string) { + hex = hex.replace(/^#/, ""); + if (hex.length === 3) hex = hex.replace(/(.)/g, "$1$1"); + const int = parseInt(hex, 16); + return [ + ((int >> 16) & 0xff) / 255, + ((int >> 8) & 0xff) / 255, + (int & 0xff) / 255, + ]; +} + +// linearize an sRGB channel +function srgbToLinear(u: number) { + return u <= 0.04045 ? u / 12.92 : Math.pow((u + 0.055) / 1.055, 2.4); +} + +// gamma-correct a linear channel +function linearToSrgb(u: number) { + return u <= 0.0031308 ? 12.92 * u : 1.055 * Math.pow(u, 1 / 2.4) - 0.055; +} + +// multiply a 3Γ—3 matrix by a 3-vector +function mat3Mul(mat: number[], [x, y, z]: [number, number, number]) { + return [ + mat[0] * x + mat[1] * y + mat[2] * z, + mat[3] * x + mat[4] * y + mat[5] * z, + mat[6] * x + mat[7] * y + mat[8] * z, + ]; +} + +// clamp to [0,1] +function clamp01(x: number) { + return x < 0 ? 0 : x > 1 ? 1 : x; +} + +// ---- Core Conversions ---- + +// linear sRGB β†’ OKLab +function linearSrgbToOklab([lr, lg, lb]: [number, number, number]) { + // first to LMS + let [l_, m_, s_] = mat3Mul( + [ + 0.4122214708, 0.5363325363, 0.0514459929, 0.2119034982, 0.6806995451, + 0.1073969566, 0.0883024619, 0.2817188376, 0.6299787005, + ], + [lr, lg, lb], + ); + + // cube-root + let l = Math.cbrt(l_), + m = Math.cbrt(m_), + s = Math.cbrt(s_); + + // to OKLab + return mat3Mul( + [ + 0.2104542553, 0.793617785, -0.0040720468, 1.9779984951, -2.428592205, + 0.4505937099, 0.0259040371, 0.7827717662, -0.808675766, + ], + [l, m, s], + ); +} + +// OKLab β†’ linear sRGB +function oklabToLinearSrgb([L, a, b]: [number, number, number]) { + // first to LMS-cube + let l = L + 0.3963377774 * a + 0.2158037573 * b; + let m = L - 0.1055613458 * a - 0.0638541728 * b; + let s = L - 0.0894841775 * a - 1.291485548 * b; + + // cube + l = l * l * l; + m = m * m * m; + s = s * s * s; + + // back to linear RGB + return mat3Mul( + [ + 4.0767416621, -3.3077115913, 0.2309699292, -1.2684380046, 2.6097574011, + -0.3413193965, -0.0041960863, -0.7034186147, 1.707614701, + ], + [l, m, s], + ); +} + +// ---- Public API ---- + +/** + * Convert a hex color to OKLCh. + * @param {string} hex – e.g. "#ff00aa" or "abc" + * @returns {{L:number,C:number,h:number}} + */ +function hexToOklch(hex: string) { + // parse, linearize + const rgb01 = hexToRgb01(hex).map(srgbToLinear) as [number, number, number]; + // to OKLab + let [L, a, b] = linearSrgbToOklab(rgb01); + // to cylindrical LCh + let C = Math.hypot(a, b); + let h = (Math.atan2(b, a) * 180) / Math.PI; + if (h < 0) h += 360; + return { L, C, h }; +} + +/** + * Convert OKLCh back to hex. + * @param {{L:number,C:number,h:number}} oklch + * @returns {string} – a 7-char "#rrggbb" + */ +function oklchToHex({ L, C, h }: { L: number; C: number; h: number }) { + // cylindrical β†’ OKLab + let a = C * Math.cos((h * Math.PI) / 180); + let b = C * Math.sin((h * Math.PI) / 180); + // to linear RGB + let [lr, lg, lb] = oklabToLinearSrgb([L, a, b]); + // gamma-correct & clamp & scale + const to255 = (x: number) => Math.round(clamp01(linearToSrgb(x)) * 255); + let r = to255(lr), + g = to255(lg), + b8 = to255(lb); + // hex + return "#" + [r, g, b8].map((v) => v.toString(16).padStart(2, "0")).join(""); +} + +/** + * Verifies an Ethereum signature and returns the address it was signed with. + * @param {string} message - The original message that was signed. + * @param {string} r - The r value of the signature. + * @param {string} s - The s value of the signature. + * @param {string} v - The v value of the signature. + * @param {string} address - The Ethereum address of the signer. + * @returns {boolean} - The recovered Ethereum address. + */ +export function verifyEthSignatureWithAddress( + message: string, + r: string, + s: string, + v: string, + address: string, +): boolean { + try { + // Construct the full signature + const signature = `0x${r}${s}${v}`; + + const hashedMessage = hashMessage(message); + + // Recover the address from the signature + return ( + address.toLowerCase() === + recoverAddress(hashedMessage, signature).toLowerCase() + ); + } catch (error) { + console.error("Ethereum signature verification failed:", error); + return false; + } +} + +/** + * Verifies a Solana signature using the address (treated as the public key). + * @param {string} message - The original message that was signed. + * @param {string} r - The r value of the signature. + * @param {string} s - The s value of the signature. + * @param {string} address - The Solana address of the signer. + * @returns {boolean} - True if the signature is valid, false otherwise. + */ +export function verifySolSignatureWithAddress( + message: string, + r: string, + s: string, + address: string, +) { + try { + // Combine r and s as the full signature (64 bytes for Solana) + const signatureBuffer = Buffer.from(r + s, "hex"); + const signature = new Uint8Array(signatureBuffer); + + // Convert the message to a Uint8Array + const messageBuffer = new Uint8Array(Buffer.from(message)); + + // Treat the address as the public key (if valid) + const pubKey = new PublicKey(address); + + // Verify the signature + return nacl.sign.detached.verify( + messageBuffer, + signature, + pubKey.toBytes(), + ); + } catch (error) { + console.error("Solana signature verification failed:", error); + return false; + } +} + +// Utility to check if hardware acceleration is enabled. Used for 3D background. +export function isHardwareAccelerationEnabled(): boolean { + try { + const canvas = document.createElement("canvas"); + const gl = + canvas.getContext("webgl") || canvas.getContext("experimental-webgl"); + return !!gl; + } catch (e) { + return false; + } +} + +export function kebab(str: string): string { + return str.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`); +} diff --git a/examples/react-wallet-kit/tsconfig.json b/examples/react-wallet-kit/tsconfig.json new file mode 100644 index 000000000..06f3d9aad --- /dev/null +++ b/examples/react-wallet-kit/tsconfig.json @@ -0,0 +1,29 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": ["./src/*"], + "react": ["./node_modules/@types/react"] + } + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "exclude": ["node_modules"] +} diff --git a/examples/with-sdk-js/.env.local.example b/examples/with-sdk-js/.env.local.example new file mode 100644 index 000000000..d257a410e --- /dev/null +++ b/examples/with-sdk-js/.env.local.example @@ -0,0 +1,7 @@ +TURNKEY_API_PUBLIC_KEY="" +TURNKEY_API_PRIVATE_KEY="" +NEXT_PUBLIC_BASE_URL="https://api.turnkey.com" +NEXT_PUBLIC_ORGANIZATION_ID="" + +NEXT_PUBLIC_AUTH_PROXY_URL="http://localhost:8090" +NEXT_PUBLIC_AUTH_PROXY_ID="" \ No newline at end of file diff --git a/examples/with-sdk-js/.eslintrc.json b/examples/with-sdk-js/.eslintrc.json new file mode 100644 index 000000000..bffb357a7 --- /dev/null +++ b/examples/with-sdk-js/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "extends": "next/core-web-vitals" +} diff --git a/examples/with-sdk-js/.gitignore b/examples/with-sdk-js/.gitignore new file mode 100644 index 000000000..8f322f0d8 --- /dev/null +++ b/examples/with-sdk-js/.gitignore @@ -0,0 +1,35 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env*.local + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/examples/with-sdk-js/README.md b/examples/with-sdk-js/README.md new file mode 100644 index 000000000..a776b2996 --- /dev/null +++ b/examples/with-sdk-js/README.md @@ -0,0 +1,3 @@ +# with-sdk-js + +A list of buttons to test `@turnkey/core` and `@turnkey/react-wallet-kit` diff --git a/examples/with-sdk-js/next.config.js b/examples/with-sdk-js/next.config.js new file mode 100644 index 000000000..658404ac6 --- /dev/null +++ b/examples/with-sdk-js/next.config.js @@ -0,0 +1,4 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = {}; + +module.exports = nextConfig; diff --git a/examples/with-sdk-js/package.json b/examples/with-sdk-js/package.json new file mode 100644 index 000000000..08c6bcbde --- /dev/null +++ b/examples/with-sdk-js/package.json @@ -0,0 +1,49 @@ +{ + "name": "@turnkey/with-sdk-js", + "version": "0.1.0", + "main": "./dist/index.js", + "module": "./dist/index.mjs", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.mjs", + "require": "./dist/index.js", + "default": "./dist/index.mjs" + } + }, + "types": "./dist/index.d.ts", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint", + "typecheck": "tsc --noEmit" + }, + "dependencies": { + "@noble/hashes": "1.4.0", + "@react-oauth/google": "^0.12.1", + "@solana/web3.js": "^1.95.8", + "@turnkey/react-wallet-kit": "workspace:*", + "@turnkey/core": "workspace:*", + "@turnkey/sdk-react": "workspace:*", + "@turnkey/sdk-server": "workspace:*", + "@turnkey/sdk-types": "workspace:*", + "@types/node": "20.3.1", + "@types/react": "18.2.14", + "@types/react-dom": "18.2.6", + "axios": "^1.8.2", + "encoding": "^0.1.13", + "eslint": "8.56.0", + "eslint-config-next": "14.2.25", + "esm": "^3.2.25", + "ethers": "^6.10.0", + "install": "^0.13.0", + "next": "^14.2.25", + "npm": "^9.7.2", + "react": "18.2.0", + "react-dom": "18.2.0", + "react-hook-form": "^7.45.1", + "typescript": "5.1.3" + } +} diff --git a/examples/with-sdk-js/public/favicon.svg b/examples/with-sdk-js/public/favicon.svg new file mode 100644 index 000000000..73948fa1a --- /dev/null +++ b/examples/with-sdk-js/public/favicon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/examples/with-sdk-js/public/fonts/inter/Inter-Bold.woff2 b/examples/with-sdk-js/public/fonts/inter/Inter-Bold.woff2 new file mode 100644 index 000000000..2846f29cc Binary files /dev/null and b/examples/with-sdk-js/public/fonts/inter/Inter-Bold.woff2 differ diff --git a/examples/with-sdk-js/public/fonts/inter/Inter-Regular.woff2 b/examples/with-sdk-js/public/fonts/inter/Inter-Regular.woff2 new file mode 100644 index 000000000..6c2b6893d Binary files /dev/null and b/examples/with-sdk-js/public/fonts/inter/Inter-Regular.woff2 differ diff --git a/examples/with-sdk-js/public/fonts/inter/Inter-SemiBold.woff2 b/examples/with-sdk-js/public/fonts/inter/Inter-SemiBold.woff2 new file mode 100644 index 000000000..611e90c95 Binary files /dev/null and b/examples/with-sdk-js/public/fonts/inter/Inter-SemiBold.woff2 differ diff --git a/examples/with-sdk-js/public/logo.svg b/examples/with-sdk-js/public/logo.svg new file mode 100644 index 000000000..f983fd29b --- /dev/null +++ b/examples/with-sdk-js/public/logo.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + diff --git a/examples/with-sdk-js/src/app/global.css b/examples/with-sdk-js/src/app/global.css new file mode 100644 index 000000000..7fa1056aa --- /dev/null +++ b/examples/with-sdk-js/src/app/global.css @@ -0,0 +1,31 @@ +@font-face { + font-family: "Inter"; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url("/fonts/inter/Inter-Regular.woff2?v=3.19") format("woff2"); +} + +@font-face { + font-family: "Inter"; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url("/fonts/inter/Inter-SemiBold.woff2?v=3.19") format("woff2"); +} + +* { + font-family: + "Inter", + -apple-system, + BlinkMacSystemFont, + sans-serif; +} + +:root { + font-family: + "Inter", + -apple-system, + BlinkMacSystemFont, + sans-serif; +} diff --git a/examples/with-sdk-js/src/app/index.module.css b/examples/with-sdk-js/src/app/index.module.css new file mode 100644 index 000000000..16144f1b2 --- /dev/null +++ b/examples/with-sdk-js/src/app/index.module.css @@ -0,0 +1,61 @@ +.main { + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: center; + padding: 6rem; + gap: 60px; +} + +.input { + display: block; + width: 240px; + margin: 0; + padding: 10px 16px; + border-radius: 8px; + border-width: 1px; + border-style: solid; + border-color: rgba(216, 219, 227, 1); + margin: 0 auto; +} + +.input_checkbox { + display: block; + margin: 0 auto; +} + +.label { + display: block; + text-align: center; +} + +.base { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} + +.button { + display: inline-flex; + align-items: center; + justify-content: center; + margin: 0; + padding: 10px 16px; + border-radius: 8px; + border-width: 1px; + border-style: solid; + cursor: pointer; + color: white; + background-color: rgba(43, 47, 51, 1); + border-color: rgba(63, 70, 75, 1); +} + +.form { + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: center; + gap: 20px; + min-width: 400px; +} diff --git a/examples/with-sdk-js/src/app/layout.tsx b/examples/with-sdk-js/src/app/layout.tsx new file mode 100644 index 000000000..d6e50951c --- /dev/null +++ b/examples/with-sdk-js/src/app/layout.tsx @@ -0,0 +1,78 @@ +"use client"; + +import "@turnkey/react-wallet-kit/styles.css"; +import "./global.css"; +import { TurnkeyProvider } from "@turnkey/react-wallet-kit"; + +interface RootLayoutProps { + children: React.ReactNode; +} + +function RootLayout({ children }: RootLayoutProps) { + return ( + + + A monumental leap + + + + + {children} + + + + ); +} + +export default RootLayout; diff --git a/examples/with-sdk-js/src/app/page.tsx b/examples/with-sdk-js/src/app/page.tsx new file mode 100644 index 000000000..6dc75757a --- /dev/null +++ b/examples/with-sdk-js/src/app/page.tsx @@ -0,0 +1,1084 @@ +"use client"; + +import Image from "next/image"; + +import { useContext, useEffect, useState } from "react"; +import { + OAuthProviders, + Session, + v1AddressFormat, + v1Attestation, +} from "@turnkey/sdk-types"; +import { + Chain, + OtpType, + StamperType, + useModal, + useTurnkey, +} from "@turnkey/react-wallet-kit"; +import { SessionKey } from "@turnkey/react-wallet-kit"; +import { ExportType } from "@turnkey/react-wallet-kit/dist/types/base"; +import { parseEther, Transaction as EthTransaction } from "ethers"; +import { PublicKey, SystemProgram, Transaction } from "@solana/web3.js"; + +export default function AuthPage() { + const [email, setEmail] = useState(""); + const [otpCode, setOtpCode] = useState(""); + const [otpId, setOtpId] = useState(""); + const [newEmail, setNewEmail] = useState(""); + const [newPhoneNumber, setNewPhoneNumber] = useState(""); + const [newUserName, setNewUserName] = useState(""); + + const { + httpClient, + session, + allSessions, + clientState, + authState, + wallets, + user, + handleLogin, + handleGoogleOauth, + createPasskey, + loginWithPasskey, + signUpWithPasskey, + getWalletProviders, + connectWalletAccount, + loginWithWallet, + signUpWithWallet, + loginOrSignupWithWallet, + fetchUser, + fetchWallets, + initOtp, + completeOtp, + handleSignMessage, + signMessage, + refreshSession, + createWallet, + logout, + setActiveSession, + addPasskey, + removeUserEmail, + createWalletAccounts, + signTransaction, + signAndSendTransaction, + switchWalletProviderChain, + handleExportWallet, + handleImportWallet, + handleUpdateUserEmail, + handleUpdateUserPhoneNumber, + handleAddOauthProvider, + handleUpdateUserName, + handleAddEmail, + handleAddPhoneNumber, + handleRemoveOauthProvider, + handleAddPasskey, + handleRemovePasskey, + handleLinkExternalWallet, + } = useTurnkey(); + + useEffect(() => { + console.log("wallets:", wallets); + }, [wallets]); + + useEffect(() => { + console.log("User:", user); + }, [user]); + + useEffect(() => { + console.log("All Sessions:", allSessions); + }, [allSessions]); + + useEffect(() => { + console.log("Auth state", authState); + }, [authState]); + + useEffect(() => { + console.log("Client state", clientState); + }, [clientState]); + + const logInWithPasskey1 = async () => { + await loginWithPasskey({ sessionKey: "session-1" }); + }; + + const logInWithPasskey2 = async () => { + await loginWithPasskey({ sessionKey: "session-2" }); + }; + + const indexedDB = async () => { + const resp = await httpClient?.getWhoami({}); + console.log("Response from getWhoami:", resp); + }; + + const handleCreatePasskey = async () => { + const res = await createPasskey(); + console.log("Created passkey:", res); + }; + + const getWallets = async () => { + const res = await fetchWallets(); + if (res) { + console.log("Wallets:", res); + } + }; + + const handleVerifyOtp = async () => { + const res = await completeOtp({ + otpId, + otpCode, + contact: email, + otpType: OtpType.Email, + }); + + console.log("OTP verification response:", res); + }; + + const getUser = async () => { + const res = await fetchUser(); + if (res) { + console.log("Users:", res); + } else { + console.error("Failed to fetch users"); + } + }; + + const doSignMessage = async () => { + if ( + (wallets.length === 0 && !wallets[0]) || + !wallets[0].accounts || + wallets[0].accounts.length < 1 + ) { + console.error("No wallets available to sign message"); + return; + } + + for (const walletAccount of wallets[0].accounts) { + const res = await signMessage({ + message: "Hello, Turnkey!", + walletAccount, + }); + + console.log("Signed message response:", res); + } + }; + + const handleRefreshSession = async () => { + return await refreshSession({}); + }; + + const doCreateWallet = async (walletName: string) => { + // List of all v1AddressFormat values + const allAddressFormats: v1AddressFormat[] = [ + "ADDRESS_FORMAT_BITCOIN_MAINNET_P2PKH", + "ADDRESS_FORMAT_BITCOIN_MAINNET_P2WPKH", + "ADDRESS_FORMAT_APTOS", + "ADDRESS_FORMAT_ETHEREUM", + "ADDRESS_FORMAT_SOLANA", + ]; + + const res = await createWallet({ + walletName, + accounts: allAddressFormats, + }); + + console.log("Created wallet response:", res); + }; + + const switchSession = async (sessionKey: string) => { + await setActiveSession({ sessionKey }); + }; + + const showLoginModal = () => { + handleLogin(); + }; + + const showSigningModal = async () => { + if ( + (wallets.length === 0 && !wallets[0]) || + !wallets[0].accounts || + wallets[0].accounts.length < 1 + ) { + console.error("No wallets available to sign message"); + return; + } + + const result = await handleSignMessage({ + message: + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. . Sed id maximus elit. Mauris lacus ligula, dictum nec purus sit amet, mollis tempor nisl. Morbi neque lectus, tempor sed tristique sit amet, ornare eget dui", + walletAccount: wallets[0].accounts[0], + }); + console.log("Signing result:", result); + }; + + const showUpdateUserNameModal = async () => { + const res = await handleUpdateUserName({ + subTitle: "Edit your user name", + }); + console.log("User name updated successfully: ", res); + }; + + return ( +
+ + Turnkey Logo + + + + + + + + + + + + + + + + + { + setEmail(e.target.value); + }} + /> + + + { + setOtpCode(e.target.value); + }} + /> + + + + + + + + {session ? ( + + ) : null} + + + + + + + + + + + + + + + + + + + + + + + + {session ? ( + + ) : null} + + {session ? ( + + ) : null} + + + + + + + + {session ? ( + + ) : null} + + {wallets.length > 0 && ( + + )} + {session && ( + <> + { + setNewEmail(e.target.value); + }} + /> + + { + setNewPhoneNumber(e.target.value); + }} + /> + + { + setNewUserName(e.target.value); + }} + /> + + + )} + {session && ( + + )} + {session && ( + + )} + {session && ( + + )} + {session && ( + + )} + + {session && ( + + )} + + {session && ( + + )} + + {session && ( + + )} + {session && ( + + )} + {session && ( + + )} + {session && ( + + )} +
+ ); +} diff --git a/examples/with-sdk-js/src/assets/google.svg b/examples/with-sdk-js/src/assets/google.svg new file mode 100644 index 000000000..fb226ca2d --- /dev/null +++ b/examples/with-sdk-js/src/assets/google.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/with-sdk-js/src/components/Socials.module.css b/examples/with-sdk-js/src/components/Socials.module.css new file mode 100644 index 000000000..fdfb5a96b --- /dev/null +++ b/examples/with-sdk-js/src/components/Socials.module.css @@ -0,0 +1,53 @@ +.socialButton { + letter-spacing: -0.01em; + padding: 10px 16px; + gap: 8px; + color: var(--button-text); + width: 100%; + font-size: 1rem; + background: var(--button-bg); + border: 1px solid var(--button-border); + border-radius: 8px; + cursor: pointer; + text-align: center; + display: flex; + align-items: center; + justify-content: center; + transition: background-color 0.2s ease; +} + +.iconButton { + padding: 10px 16px; + gap: 8px; + color: var(--button-text); + width: 100%; + font-size: 1rem; + background: var(--button-bg); + border: 1px solid var(--button-border); + border-radius: 8px; + cursor: pointer; + text-align: center; + display: flex; + align-items: center; + justify-content: center; + transition: background-color 0.2s ease; +} + +.socialButton:hover { + background-color: var(--button-hover-bg); +} + +.iconButton:hover { + background-color: var(--button-hover-bg); +} + +.iconSmall { + width: 20px; + height: 20px; + margin-right: 4px; +} + +.iconLarge { + width: 24px; + height: 24px; +} diff --git a/examples/with-sdk-js/src/components/constants.ts b/examples/with-sdk-js/src/components/constants.ts new file mode 100644 index 000000000..1b1702057 --- /dev/null +++ b/examples/with-sdk-js/src/components/constants.ts @@ -0,0 +1,55 @@ +export const GOOGLE_AUTH_URL = "https://accounts.google.com/o/oauth2/v2/auth"; +export const APPLE_AUTH_URL = "https://appleid.apple.com/auth/authorize"; +export const APPLE_AUTH_SCRIPT_URL = + "https://appleid.cdn-apple.com/appleauth/static/jsapi/appleid/1/en_US/appleid.auth.js"; +export const FACEBOOK_AUTH_URL = "https://www.facebook.com/v11.0/dialog/oauth"; +export const FACEBOOK_GRAPH_URL = + "https://graph.facebook.com/v11.0/oauth/access_token"; +export const popupWidth = 500; +export const popupHeight = 600; + +export const authErrors = { + // Passkey-related errors + passkey: { + createFailed: "Passkey not created. Please try again.", + loginFailed: "Failed to login with passkey. Please try again.", + timeoutOrNotAllowed: + "The operation either timed out or was not allowed. Please try again.", + }, + + // OTP-related errors + otp: { + sendFailed: "Failed to send OTP", + invalidEmail: "Invalid email address.", + invalidPhone: "Invalid phone number.", + }, + + // OAuth-related errors + oauth: { + loginFailed: "Failed to login with OAuth provider", + }, + + // Wallet-related errors + wallet: { + loginFailed: "Failed to login with wallet", + noPublicKey: "No public key found", + }, + + // Sub-organization-related errors + suborg: { + fetchFailed: "Failed to fetch account", + createFailed: "Failed to create account.", + }, +}; + +export enum OtpType { + Email = "OTP_TYPE_EMAIL", + Sms = "OTP_TYPE_SMS", +} + +export enum FilterType { + Email = "EMAIL", + PhoneNumber = "PHONE_NUMBER", + OidcToken = "OIDC_TOKEN", + PublicKey = "PUBLIC_KEY", +} diff --git a/examples/with-sdk-js/tsconfig.json b/examples/with-sdk-js/tsconfig.json new file mode 100644 index 000000000..06f3d9aad --- /dev/null +++ b/examples/with-sdk-js/tsconfig.json @@ -0,0 +1,29 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": ["./src/*"], + "react": ["./node_modules/@types/react"] + } + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "exclude": ["node_modules"] +} diff --git a/generated-docs/sdks/core/index/ApiKeyStamper/readme.mdx b/generated-docs/sdks/core/index/ApiKeyStamper/readme.mdx new file mode 100644 index 000000000..825aa7fba --- /dev/null +++ b/generated-docs/sdks/core/index/ApiKeyStamper/readme.mdx @@ -0,0 +1,70 @@ +--- +title: "ApiKeyStamper" +mode: wide +--- + +# Class: ApiKeyStamper + +Defined in: api-key-stamper/dist/index.d.ts:19 + +Stamper to use with `@turnkey/http`'s `TurnkeyClient` + +## Constructors + +### Constructor + +> **new ApiKeyStamper**(`config`): `ApiKeyStamper` + +Defined in: api-key-stamper/dist/index.d.ts:23 + +#### Parameters + +##### config + +`TApiKeyStamperConfig` + +#### Returns + +`ApiKeyStamper` + +## Properties + +### apiPrivateKey + +> **apiPrivateKey**: `string` + +Defined in: api-key-stamper/dist/index.d.ts:21 + +*** + +### apiPublicKey + +> **apiPublicKey**: `string` + +Defined in: api-key-stamper/dist/index.d.ts:20 + +*** + +### runtimeOverride? + +> `optional` **runtimeOverride**: [`Runtime`](../../../api-key-stamper/index/Runtime/readme) + +Defined in: api-key-stamper/dist/index.d.ts:22 + +## Methods + +### stamp() + +> **stamp**(`payload`): `Promise`\<\{ `stampHeaderName`: `string`; `stampHeaderValue`: `string`; \}\> + +Defined in: api-key-stamper/dist/index.d.ts:24 + +#### Parameters + +##### payload + +`string` + +#### Returns + +`Promise`\<\{ `stampHeaderName`: `string`; `stampHeaderValue`: `string`; \}\> diff --git a/generated-docs/sdks/core/index/TurnkeyClient/readme.mdx b/generated-docs/sdks/core/index/TurnkeyClient/readme.mdx new file mode 100644 index 000000000..a4788eb8b --- /dev/null +++ b/generated-docs/sdks/core/index/TurnkeyClient/readme.mdx @@ -0,0 +1,2434 @@ +--- +title: "TurnkeyClient" +mode: wide +--- + +# Class: TurnkeyClient + +Defined in: [core/src/\_\_clients\_\_/core.ts:90](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L90) + +## Constructors + +### Constructor + +> **new TurnkeyClient**(`config`, `apiKeyStamper?`, `passkeyStamper?`, `walletManager?`): `TurnkeyClient` + +Defined in: [core/src/\_\_clients\_\_/core.ts:99](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L99) + +#### Parameters + +##### config + +[`TurnkeySDKClientConfig`](../../../react-wallet-kit/index/TurnkeySDKClientConfig/readme) + +##### apiKeyStamper? + +`CrossPlatformApiKeyStamper` + +##### passkeyStamper? + +`CrossPlatformPasskeyStamper` + +##### walletManager? + +[`WalletManagerBase`](../../../react-wallet-kit/index/WalletManagerBase/readme) + +#### Returns + +`TurnkeyClient` + +## Properties + +### config + +> **config**: [`TurnkeySDKClientConfig`](../../../react-wallet-kit/index/TurnkeySDKClientConfig/readme) + +Defined in: [core/src/\_\_clients\_\_/core.ts:91](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L91) + +*** + +### httpClient + +> **httpClient**: `TurnkeySDKClientBase` + +Defined in: [core/src/\_\_clients\_\_/core.ts:92](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L92) + +## Methods + +### addOauthProvider() + +> **addOauthProvider**(`params`): `Promise`\<`string`[]\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:2458](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L2458) + +Adds an OAuth provider to the user. + +- This function adds an OAuth provider (e.g., Google, Apple) to the user account. +- If a userId is provided, it adds the provider for that specific user; otherwise, it uses the current session's userId. +- Automatically checks if an account already exists for the provided OIDC token and prevents duplicate associations. +- If the user's email is not set or not verified, attempts to update and verify the email using the email from the OIDC token. +- Handles session management and error reporting for the add provider flow. +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Parameters + +##### params + +###### oidcToken + +`string` + +OIDC token for the OAuth provider. + +###### providerName + +`string` + +name of the OAuth provider to add (e.g., "Google", "Apple"). + +###### stampWith? + +[`StamperType`](../../../react-wallet-kit/index/StamperType/readme) + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### userId? + +`string` + +user ID to add the provider for a specific user (defaults to current session's userId). + +#### Returns + +`Promise`\<`string`[]\> + +A promise that resolves to an array of provider IDs associated with the user. + +#### Throws + +If there is no active session, if the account already exists, or if there is an error adding the OAuth provider. + +*** + +### addPasskey() + +> **addPasskey**(`params?`): `Promise`\<`string`[]\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:2610](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L2610) + +Adds a new passkey authenticator for the user. + +- This function prompts the user to create a new passkey (WebAuthn/FIDO2) and adds it as an authenticator for the user. +- Handles both web and React Native environments, automatically selecting the appropriate passkey creation flow. +- If a userId is provided, the passkey is added for that specific user; otherwise, it uses the current session's userId. +- The passkey's name and display name can be customized; if not provided, defaults are generated. +- The resulting passkey attestation and challenge are registered with Turnkey as a new authenticator. + +#### Parameters + +##### params? + +###### displayName? + +`string` + +display name of the passkey (defaults to the value of `name`). + +###### name? + +`string` + +name of the passkey (defaults to "Turnkey Passkey-`timestamp`"). + +###### stampWith? + +[`StamperType`](../../../react-wallet-kit/index/StamperType/readme) + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### userId? + +`string` + +user ID to add the passkey for a specific user (defaults to the current session's userId). + +#### Returns + +`Promise`\<`string`[]\> + +A promise that resolves to an array of authenticator IDs for the newly added passkey(s). + +#### Throws + +If there is no active session, if passkey creation fails, or if there is an error adding the passkey. + +*** + +### clearAllSessions() + +> **clearAllSessions**(): `Promise`\<`void`\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:3122](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L3122) + +Clears all sessions and resets the active session state. + +- This function removes all session data from the client and persistent storage, including all associated key pairs. +- Iterates through all stored session keys, clearing each session and deleting its corresponding API key pair. +- After clearing, there will be no active session, and all session-related data will be removed from local storage. +- Throws an error if no sessions exist or if there is an error during the clearing process. + +#### Returns + +`Promise`\<`void`\> + +A promise that resolves when all sessions are successfully cleared. + +#### Throws + +If no sessions exist or if there is an error clearing all sessions. + +*** + +### clearSession() + +> **clearSession**(`params?`): `Promise`\<`void`\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:3088](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L3088) + +Clears the session associated with the specified session key, or the active session by default. + +- This function deletes the session and its associated key pair from storage. +- If a sessionKey is provided, it will clear the session under that key; otherwise, it will clear the default (active) session. +- Removes the session data from local storage and deletes the corresponding API key pair from the key store. +- Throws an error if the session does not exist or if there is an error during the clearing process. + +#### Parameters + +##### params? + +###### sessionKey? + +`string` + +session key to clear the session under (defaults to the default session key). + +#### Returns + +`Promise`\<`void`\> + +A promise that resolves when the session is successfully cleared. + +#### Throws + +If the session does not exist or if there is an error clearing the session. + +*** + +### clearUnusedKeyPairs() + +> **clearUnusedKeyPairs**(): `Promise`\<`void`\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:3362](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L3362) + +Clears any unused API key pairs from persistent storage. + +- This function scans all API key pairs stored in indexedDB and removes any key pairs that are not associated with a session in persistent storage. +- Ensures that only key pairs referenced by existing sessions are retained, preventing orphaned or stale key pairs from accumulating. +- Iterates through all stored session keys and builds a map of in-use public keys, then deletes any key pairs not present in this map. +- Intended to be called after session changes (e.g., login, logout, session replacement) to keep key storage clean and secure. + +#### Returns + +`Promise`\<`void`\> + +A promise that resolves when all unused key pairs are successfully cleared. + +#### Throws + +If there is an error listing, checking, or deleting unused key pairs. + +*** + +### completeOauth() + +> **completeOauth**(`params`): `Promise`\<`string`\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:1380](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L1380) + +Completes the OAuth authentication flow by either signing up or logging in the user, depending on whether a sub-organization already exists for the provided OIDC token. + +- This function first checks if there is an existing sub-organization associated with the OIDC token. +- If a sub-organization exists, it proceeds with the OAuth login flow. +- If no sub-organization exists, it creates a new sub-organization and completes the sign-up flow. +- Optionally accepts a custom OAuth provider name, session key, and additional sub-organization creation parameters. +- Handles session storage and management, and supports invalidating existing sessions if specified. + +#### Parameters + +##### params + +###### createSubOrgParams? + +[`CreateSubOrgParams`](../../../react-wallet-kit/index/CreateSubOrgParams/readme) + +parameters for sub-organization creation (e.g., authenticators, user metadata). + +###### invalidateExisting? + +`boolean` + +flag to invalidate existing sessions for the user. + +###### oidcToken + +`string` + +OIDC token received after successful authentication with the OAuth provider. + +###### providerName? + +`string` + +name of the OAuth provider (defaults to a generated name with a timestamp). + +###### publicKey + +`string` + +public key to use for authentication. Must be generated prior to calling this function. + +###### sessionKey? + +`string` + +session key to use for session creation (defaults to the default session key). + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to a signed JWT session token for the user. + +#### Throws + +If there is an error during the OAuth completion process, such as account lookup, sign-up, or login. + +*** + +### completeOtp() + +> **completeOtp**(`params`): `Promise`\<`string`\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:1297](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L1297) + +Completes the OTP authentication flow by verifying the OTP code and then either signing up or logging in the user. + +- This function first verifies the OTP code for the provided contact and OTP type. +- If the contact is not associated with an existing sub-organization, it will automatically create a new sub-organization and complete the sign-up flow. +- If the contact is already associated with a sub-organization, it will complete the login flow. +- Supports passing a custom public key for authentication, invalidating existing session, specifying a session key, and providing additional sub-organization creation parameters. +- Handles both email and SMS OTP types. + +#### Parameters + +##### params + +###### contact + +`string` + +contact information for the user (e.g., email address or phone number). + +###### createSubOrgParams? + +[`CreateSubOrgParams`](../../../react-wallet-kit/index/CreateSubOrgParams/readme) + +parameters for sub-organization creation (e.g., authenticators, user metadata). + +###### invalidateExisting? + +`boolean` + +flag to invalidate existing sessions for the user. + +###### otpCode + +`string` + +OTP code entered by the user. + +###### otpId + +`string` + +ID of the OTP to complete (returned from `initOtp`). + +###### otpType + +[`OtpType`](../../../react-wallet-kit/index/OtpType/readme) + +type of OTP being completed (OtpType.Email or OtpType.Sms). + +###### publicKey? + +`string` + +public key to use for authentication. If not provided, a new key pair may be generated. + +###### sessionKey? + +`string` + +session key to use for session creation (defaults to the default session key). + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to a signed JWT session token for the user. + +#### Throws + +If there is an error during OTP verification, sign-up, or login. + +*** + +### connectWalletAccount() + +> **connectWalletAccount**(`walletProvider`): `Promise`\<`void`\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:522](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L522) + +Connects the specified wallet account. + +- Requires the wallet manager and its connector to be initialized. + +#### Parameters + +##### walletProvider + +[`WalletProvider`](../../../react-wallet-kit/index/WalletProvider/readme) + +wallet provider to connect. + +#### Returns + +`Promise`\<`void`\> + +A promise that resolves once the wallet account is connected. + +#### Throws + +If the wallet manager is uninitialized or the connection fails. + +*** + +### createApiKeyPair() + +> **createApiKeyPair**(`params?`): `Promise`\<`string`\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:3415](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L3415) + +Creates a new API key pair and returns the public key. + +- This function generates a new API key pair and stores it in the underlying key store (IndexedDB). +- If an external key pair is provided, it will use that key pair for creation instead of generating a new one. +- If `storeOverride` is set to true, the generated or provided public key will be set as the override key in the API key stamper, making it the active key for subsequent signing operations. +- Ensures the API key stamper is initialized before proceeding. +- Handles both native CryptoKeyPair objects and raw key material. + +#### Parameters + +##### params? + +###### externalKeyPair? + +`CryptoKeyPair` \| \{ `privateKey`: `string`; `publicKey`: `string`; \} + +An externally generated key pair (either a CryptoKeyPair or an object with publicKey/privateKey strings) to use instead of generating a new one. + +###### storeOverride? + +`boolean` + +If true, sets the generated or provided public key as the override key in the API key stamper (defaults to false). +@returnparams.s A promise that resolves to the public key of the created or provided API key pair as a string. + +#### Returns + +`Promise`\<`string`\> + +#### Throws + +If the API key stamper is not initialized or if there is an error during key pair creation or storage. + +*** + +### createPasskey() + +> **createPasskey**(`params?`): `Promise`\<\{ `attestation`: [`v1Attestation`](../../../_turnkey/sdk-types/v1Attestation/readme); `encodedChallenge`: `string`; \}\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:172](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L172) + +Creates a new passkey authenticator for the user. + +- This function generates a new passkey attestation and challenge, suitable for registration with the user's device. +- Handles both web and React Native environments, automatically selecting the appropriate passkey creation flow. +- The resulting attestation and challenge can be used to register the passkey with Turnkey. + +#### Parameters + +##### params? + +###### displayName? + +`string` + +display name for the passkey. If not provided, defaults to "A Passkey". + +###### name? + +`string` + +name of the passkey. If not provided, defaults to "A Passkey". + +###### stampWith? + +[`StamperType`](../../../react-wallet-kit/index/StamperType/readme) + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Returns + +`Promise`\<\{ `attestation`: [`v1Attestation`](../../../_turnkey/sdk-types/v1Attestation/readme); `encodedChallenge`: `string`; \}\> + +A promise that resolves to an object containing: + - attestation: attestation object returned from the passkey creation process. + - encodedChallenge: encoded challenge string used for passkey registration. + +#### Throws + +If there is an error during passkey creation, or if the platform is unsupported. + +*** + +### createWallet() + +> **createWallet**(`params`): `Promise`\<`string`\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:2734](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L2734) + +Creates a new wallet for sub-organization. + +- This function creates a new wallet for the current sub-organization. +- If an organizationId is provided, the wallet will be created under that specific sub-organization; otherwise, it uses the current session's organizationId. +- If a list of address formats is provided, accounts will be created in the wallet based on those formats (starting from path index 0). +- If a list of account parameters is provided, those accounts will be created in the wallet. +- If no accounts or address formats are provided, default Ethereum and Solana accounts will be created. +- Optionally allows specifying the mnemonic length for the wallet seed phrase (defaults to 12). +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Parameters + +##### params + +###### accounts? + +[`v1WalletAccountParams`](../../../_turnkey/sdk-types/v1WalletAccountParams/readme)[] \| [`v1AddressFormat`](../../../_turnkey/sdk-types/v1AddressFormat/readme)[] + +array of account parameters or address formats to create in the wallet. + +###### mnemonicLength? + +`number` + +mnemonic length for the wallet seed phrase (defaults to 12). + +###### organizationId? + +`string` + +organization ID to create the wallet under a specific sub-organization (defaults to the current session's organizationId). + +###### stampWith? + +[`StamperType`](../../../react-wallet-kit/index/StamperType/readme) + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### walletName + +`string` + +name of the wallet to create. + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to the ID of the newly created wallet. + +#### Throws + +If there is no active session or if there is an error creating the wallet. + +*** + +### createWalletAccounts() + +> **createWalletAccounts**(`params`): `Promise`\<`string`[]\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:2808](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L2808) + +Creates new accounts in the specified wallet. + +- This function creates new wallet accounts based on the provided account parameters or address formats. +- If a walletId is provided, it creates the accounts in that specific wallet; otherwise, it uses the current session's wallet. +- If a list of address formats is provided, it will create accounts in the wallet based on those formats, automatically determining the next available path indexes to avoid duplicates with existing accounts. +- If account parameters are provided, they are used directly for account creation. +- Automatically queries existing wallet accounts to prevent duplicate account creation for the same address format and path. +- Supports stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Parameters + +##### params + +###### accounts + +[`v1WalletAccountParams`](../../../_turnkey/sdk-types/v1WalletAccountParams/readme)[] \| [`v1AddressFormat`](../../../_turnkey/sdk-types/v1AddressFormat/readme)[] + +An array of account parameters or address formats to create in the wallet. + +###### organizationId? + +`string` + +organization ID to create the accounts under a specific organization (walletId must be associated with the sub-organization). + +###### stampWith? + +[`StamperType`](../../../react-wallet-kit/index/StamperType/readme) + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### walletId + +`string` + +ID of the wallet to create accounts in. + +#### Returns + +`Promise`\<`string`[]\> + +A promise that resolves to an array of addresses for the newly created accounts. + +#### Throws + +If there is no active session, if the wallet does not exist, or if there is an error creating the wallet accounts. + +*** + +### deleteSubOrganization() + +> **deleteSubOrganization**(`params?`): `Promise`\<[`TDeleteSubOrganizationResponse`](../../../_turnkey/sdk-types/TDeleteSubOrganizationResponse/readme)\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:3007](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L3007) + +Deletes the current sub-organization (sub-org) for the active session. + +- This function deletes the sub-organization associated with the current active session. +- By default, the deletion will fail if any wallets associated with the sub-organization have not been exported. +- If `deleteWithoutExport` is set to true, the sub-organization will be deleted even if its wallets have not been exported (potentially resulting in loss of access to those wallets). +- Requires an active session; otherwise, an error is thrown. +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Parameters + +##### params? + +###### deleteWithoutExport? + +`boolean` + +flag to delete the sub-organization without requiring all wallets to be exported first (defaults to false). + +###### stampWith? + +[`StamperType`](../../../react-wallet-kit/index/StamperType/readme) + +parameter to stamp the request with a specific stamper. + +#### Returns + +`Promise`\<[`TDeleteSubOrganizationResponse`](../../../_turnkey/sdk-types/TDeleteSubOrganizationResponse/readme)\> + +A promise that resolves to a `TDeleteSubOrganizationResponse` object containing the result of the deletion. + +#### Throws + +If there is no active session or if there is an error deleting the sub-organization. + +*** + +### disconnectWalletAccount() + +> **disconnectWalletAccount**(`walletProvider`): `Promise`\<`void`\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:550](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L550) + +Disconnects the specified wallet account. + +- Requires the wallet manager and its connector to be initialized. + +#### Parameters + +##### walletProvider + +[`WalletProvider`](../../../react-wallet-kit/index/WalletProvider/readme) + +wallet provider to disconnect. + +#### Returns + +`Promise`\<`void`\> + +A promise that resolves once the wallet account is disconnected. + +#### Throws + +If the wallet manager is uninitialized or the disconnection fails. + +*** + +### exportWallet() + +> **exportWallet**(`params`): `Promise`\<`string`\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:2885](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L2885) + +Exports a wallet as an encrypted bundle. + +- This function exports the specified wallet and its accounts as an encrypted bundle, suitable for backup or transfer. +- The exported bundle contains the wallet's seed phrase, encrypted to the provided target public key. +- If a targetPublicKey is provided, the bundle will be encrypted to that public key; otherwise, an error will be thrown. +- If an organizationId is provided, the wallet will be exported under that sub-organization; otherwise, the current session's organizationId is used. +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). +- The exported bundle can later be imported using the `importWallet` method. + +#### Parameters + +##### params + +###### organizationId? + +`string` + +organization ID to export the wallet under a specific sub-organization (walletId must be associated with the sub-organization). + +###### stampWith? + +[`StamperType`](../../../react-wallet-kit/index/StamperType/readme) + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### targetPublicKey + +`string` + +public key to encrypt the bundle to (required). + +###### walletId + +`string` + +ID of the wallet to export. + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to an `ExportBundle` object containing the encrypted wallet seed phrase and metadata. + +#### Throws + +If there is no active session, if the targetPublicKey is missing, or if there is an error exporting the wallet. + +*** + +### fetchUser() + +> **fetchUser**(`params?`): `Promise`\<[`v1User`](../../../_turnkey/sdk-types/v1User/readme)\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:2119](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L2119) + +Fetches the user details for the current session or a specified user. + +- Retrieves user details from the Turnkey API using the provided userId and organizationId, or defaults to those from the active session. +- If no userId is provided, the userId from the current session is used. +- If no organizationId is provided, the organizationId from the current session is used. +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). +- Ensures that an active session exists before making the request. + +#### Parameters + +##### params? + +###### organizationId? + +`string` + +organization ID to specify the sub-organization (defaults to the current session's organizationId). + +###### stampWith? + +[`StamperType`](../../../react-wallet-kit/index/StamperType/readme) + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### userId? + +`string` + +user ID to fetch specific user details (defaults to the current session's userId). + +#### Returns + +`Promise`\<[`v1User`](../../../_turnkey/sdk-types/v1User/readme)\> + +A promise that resolves to a `v1User` object containing the user details. + +#### Throws + +If there is no active session, if there is no userId, or if there is an error fetching user details. + +*** + +### fetchWalletAccounts() + +> **fetchWalletAccounts**(`params`): `Promise`\<[`WalletAccount`](../../../react-wallet-kit/index/WalletAccount/readme)[]\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:1712](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L1712) + +Fetches all accounts for a specific wallet, including both embedded and connected wallet accounts. + +- For embedded wallets, retrieves accounts from the Turnkey API, supporting pagination (defaults to the first page with a limit of 100 accounts). +- For connected wallets (e.g., browser extensions or external providers), constructs account objects for each connected address from the provided or discovered wallet providers. +- Automatically determines the account type and populates relevant fields such as address, curve, and signing capability. +- Optionally allows filtering by a specific set of wallet providers and supports custom pagination options. +- Supports stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Parameters + +##### params + +###### paginationOptions? + +[`v1Pagination`](../../../_turnkey/sdk-types/v1Pagination/readme) + +pagination options for embedded wallets. + +###### stampWith? + +[`StamperType`](../../../react-wallet-kit/index/StamperType/readme) + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### wallet + +[`Wallet`](../../../react-wallet-kit/index/Wallet/readme) + +wallet for which to fetch accounts. + +###### walletProviders? + +[`WalletProvider`](../../../react-wallet-kit/index/WalletProvider/readme)[] + +list of wallet providers to filter by (used for connected wallets). + +#### Returns + +`Promise`\<[`WalletAccount`](../../../react-wallet-kit/index/WalletAccount/readme)[]\> + +A promise that resolves to an array of `v1WalletAccount` objects. + +#### Throws + +If no active session is found or if there is an error fetching wallet accounts. + +*** + +### fetchWallets() + +> **fetchWallets**(`params?`): `Promise`\<[`Wallet`](../../../react-wallet-kit/index/Wallet/readme)[]\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:1596](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L1596) + +Fetches all wallets for the current user, including both embedded and connected wallets. + +- Retrieves all wallets associated with the organizationId from the current active session. +- For each embedded wallet, automatically fetches and attaches all associated wallet accounts. +- For connected wallets (e.g., browser extensions or external providers), groups providers by wallet name and attaches all connected accounts. +- Returns both embedded and connected wallets in a single array, each with their respective accounts populated. +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Parameters + +##### params? + +###### stampWith? + +[`StamperType`](../../../react-wallet-kit/index/StamperType/readme) + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Returns + +`Promise`\<[`Wallet`](../../../react-wallet-kit/index/Wallet/readme)[]\> + +A promise that resolves to an array of `Wallet` objects. + +#### Throws + +If no active session is found or if there is an error fetching wallets. + +*** + +### getActiveSessionKey() + +> **getActiveSessionKey**(): `Promise`\<`undefined` \| `string`\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:3338](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L3338) + +Retrieves the active session key currently set in persistent storage. + +- This function fetches the session key that is currently marked as active in the client's persistent storage. +- The active session key determines which session is used for all session-dependent operations. +- If no active session key is set, returns `undefined`. +- Useful for determining which session is currently in use, especially when managing multiple sessions. + +#### Returns + +`Promise`\<`undefined` \| `string`\> + +A promise that resolves to the active session key as a string, or `undefined` if no active session is set. + +#### Throws + +If there is an error retrieving the active session key from storage. + +*** + +### getAllSessions() + +> **getAllSessions**(): `Promise`\<`undefined` \| `Record`\<`string`, [`Session`](../../../sdk-browser/index/Session/readme)\>\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:3277](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L3277) + +Retrieves all sessions stored in persistent storage. + +- This function fetches all session objects currently stored by the client, including those that are not active. +- Returns a record mapping each session key to its corresponding `Session` object. +- Useful for session management, auditing, or displaying all available sessions to the user. +- Automatically skips any session keys that do not have a valid session object. + +#### Returns + +`Promise`\<`undefined` \| `Record`\<`string`, [`Session`](../../../sdk-browser/index/Session/readme)\>\> + +A promise that resolves to a record of session keys and their corresponding `Session` objects, or `undefined` if no sessions exist. + +#### Throws + +If there is an error retrieving sessions from storage. + +*** + +### getProxyAuthConfig() + +> **getProxyAuthConfig**(): `Promise`\<[`ProxyTGetWalletKitConfigResponse`](../../../_turnkey/sdk-types/ProxyTGetWalletKitConfigResponse/readme)\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:3459](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L3459) + +Fetches the WalletKit proxy authentication configuration from the auth proxy. + +- This function makes a request to the Turnkey auth proxy to retrieve the current WalletKit configuration, + including supported authentication methods, OAuth providers, and any custom proxy settings. +- Useful for dynamically configuring the client UI or authentication flows based on the proxy's capabilities. +- Ensures that the client is aware of the latest proxy-side configuration, which may affect available login/signup options. + +#### Returns + +`Promise`\<[`ProxyTGetWalletKitConfigResponse`](../../../_turnkey/sdk-types/ProxyTGetWalletKitConfigResponse/readme)\> + +A promise that resolves to a `ProxyTGetWalletKitConfigResponse` object containing the proxy authentication configuration. + +#### Throws + +If there is an error retrieving the proxy authentication configuration from the auth proxy. + +*** + +### getSession() + +> **getSession**(`params?`): `Promise`\<`undefined` \| [`Session`](../../../sdk-browser/index/Session/readme)\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:3249](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L3249) + +Retrieves the session associated with the specified session key, or the active session by default. + +- This function retrieves the session object from storage, using the provided session key or, if not specified, the current active session key. +- If no session key is provided and there is no active session, it returns undefined. +- Returns the session details, including public key, organization ID, user ID, and expiration. + +#### Parameters + +##### params? + +###### sessionKey? + +`string` + +session key to retrieve a specific session (defaults to the current active session key). + +#### Returns + +`Promise`\<`undefined` \| [`Session`](../../../sdk-browser/index/Session/readme)\> + +A promise that resolves to a `Session` object containing the session details, or undefined if not found. + +#### Throws + +If there is an error retrieving the session from storage. + +*** + +### getWalletProviders() + +> **getWalletProviders**(`chain?`): `Promise`\<[`WalletProvider`](../../../react-wallet-kit/index/WalletProvider/readme)[]\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:494](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L494) + +Retrieves wallet providers from the initialized wallet manager. + +- Optionally filters providers by the specified blockchain chain. +- Throws an error if the wallet manager is not initialized. + +#### Parameters + +##### chain? + +[`Chain`](../../../react-wallet-kit/index/Chain/readme) + +optional blockchain chain to filter the returned providers. + +#### Returns + +`Promise`\<[`WalletProvider`](../../../react-wallet-kit/index/WalletProvider/readme)[]\> + +A promise that resolves to an array of wallet providers. + +#### Throws + +If the wallet manager is uninitialized or provider retrieval fails. + +*** + +### importWallet() + +> **importWallet**(`params`): `Promise`\<`string`\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:2944](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L2944) + +Imports a wallet from an encrypted bundle. + +- This function imports a wallet using the provided encrypted bundle and creates accounts based on the provided parameters. +- If a userId is provided, the wallet will be imported for that specific user; otherwise, it uses the current session's userId. +- If an accounts array is provided, those accounts will be created in the imported wallet; otherwise, default Ethereum and Solana accounts will be created. +- The encrypted bunlde MUST be encrypted to +- Automatically ensures an active session exists before making the request. +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Parameters + +##### params + +###### accounts? + +[`v1WalletAccountParams`](../../../_turnkey/sdk-types/v1WalletAccountParams/readme)[] + +array of account parameters to create in the imported wallet (defaults to standard Ethereum and Solana accounts). + +###### encryptedBundle + +`string` + +encrypted bundle containing the wallet seed phrase and metadata. + +###### stampWith? + +[`StamperType`](../../../react-wallet-kit/index/StamperType/readme) + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### userId? + +`string` + +user ID to import the wallet for a specific user (defaults to the current session's userId). + +###### walletName + +`string` + +name of the wallet to create upon import. + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to the ID of the imported wallet. + +#### Throws + +If there is no active session, if the encrypted bundle is invalid, or if there is an error importing the wallet. + +*** + +### init() + +> **init**(): `Promise`\<`void`\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:117](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L117) + +#### Returns + +`Promise`\<`void`\> + +*** + +### initOtp() + +> **initOtp**(`params`): `Promise`\<`string`\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:1020](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L1020) + +Initializes the OTP process by sending an OTP code to the provided contact. + +- This function initiates the OTP flow by sending a one-time password (OTP) code to the user's contact information (email address or phone number) via the auth proxy. +- Supports both email and SMS OTP types. +- Returns an OTP ID that is required for subsequent OTP verification. + +#### Parameters + +##### params + +###### contact + +`string` + +contact information for the user (e.g., email address or phone number). + +###### otpType + +[`OtpType`](../../../react-wallet-kit/index/OtpType/readme) + +type of OTP to initialize (OtpType.Email or OtpType.Sms). + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to the OTP ID required for verification. + +#### Throws + +If there is an error during the OTP initialization process or if the maximum number of OTPs has been reached. + +*** + +### loginOrSignupWithWallet() + +> **loginOrSignupWithWallet**(`params`): `Promise`\<`string`\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:838](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L838) + +Logs in an existing user or signs up a new user using a wallet, creating a new sub-organization if needed. + +- This function attempts to log in the user by stamping a login request with the provided wallet. +- If the wallet’s public key is not associated with an existing sub-organization, a new one is created. +- Handles both wallet authentication and sub-organization creation in a single flow. +- For Ethereum wallets, derives the public key from the signed request header; for Solana wallets, retrieves it directly from the wallet. +- Optionally accepts additional sub-organization parameters, a custom session key, and a custom session expiration. +- Stores the resulting session token under the specified session key, or the default session key if not provided. + +#### Parameters + +##### params + +###### createSubOrgParams? + +[`CreateSubOrgParams`](../../../react-wallet-kit/index/CreateSubOrgParams/readme) + +optional parameters for creating a sub-organization (e.g., authenticators, user metadata). + +###### expirationSeconds? + +`string` + +session expiration time in seconds (defaults to the configured default). + +###### sessionKey? + +`string` + +session key to use for storing the session (defaults to the default session key). + +###### walletProvider + +[`WalletProvider`](../../../react-wallet-kit/index/WalletProvider/readme) + +wallet provider to use for authentication. + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to a signed JWT session token for the sub-organization (new or existing). + +#### Throws + +If there is an error during wallet authentication, sub-organization creation, or session storage. + +*** + +### loginWithOauth() + +> **loginWithOauth**(`params`): `Promise`\<`string`\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:1453](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L1453) + +Logs in a user using OAuth authentication. + +- This function logs in a user using the provided OIDC token and public key. +- Optionally invalidates any existing sessions for the user if `invalidateExisting` is set to true. +- Stores the resulting session token under the specified session key, or the default session key if not provided. +- Handles cleanup of unused key pairs if login fails. + +#### Parameters + +##### params + +###### invalidateExisting? + +`boolean` + +flag to invalidate existing sessions for the user. + +###### oidcToken + +`string` + +OIDC token received after successful authentication with the OAuth provider. + +###### publicKey + +`string` + +public key to use for authentication. Must be generated prior to calling this function. + +###### sessionKey? + +`string` + +session key to use for session creation (defaults to the default session key). + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to a signed JWT session token. + +#### Throws + +If there is an error during the OAuth login process or if key pair cleanup fails. + +*** + +### loginWithOtp() + +> **loginWithOtp**(`params`): `Promise`\<`string`\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:1142](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L1142) + +Logs in a user using an OTP verification token. + +- This function logs in a user using the verification token received after OTP verification (from email or SMS). +- If a public key is not provided, a new API key pair will be generated for authentication. +- Optionally invalidates any existing sessions for the user if `invalidateExisting` is set to true. +- Stores the resulting session token under the specified session key, or the default session key if not provided. +- Handles cleanup of unused key pairs if login fails. + +#### Parameters + +##### params + +###### invalidateExisting? + +`boolean` + +flag to invalidate existing session for the user. + +###### publicKey? + +`string` + +public key to use for authentication. If not provided, a new key pair will be generated. + +###### sessionKey? + +`string` + +session key to use for session creation (defaults to the default session key). + +###### verificationToken + +`string` + +verification token received after OTP verification. + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to a signed JWT session token. + +#### Throws + +If there is an error during the OTP login process or if key pair cleanup fails. + +*** + +### loginWithPasskey() + +> **loginWithPasskey**(`params?`): `Promise`\<`string`\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:296](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L296) + +Logs in a user using a passkey, optionally specifying the public key, session key, and session expiration. + +- This function initiates the login process with a passkey and handles session creation and storage. +- If a public key is not provided, a new key pair will be generated for authentication. +- If a session key is not provided, the default session key will be used. +- The session expiration can be customized via the expirationSeconds parameter. +- Handles cleanup of unused key pairs if login fails. + +#### Parameters + +##### params? + +###### expirationSeconds? + +`string` + +session expiration time in seconds (defaults to the configured default). + +###### publicKey? + +`string` + +public key to use for authentication. If not provided, a new key pair will be generated. + +###### sessionKey? + +`string` + +session key to use for session creation (defaults to the default session key). + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to a signed JWT session token. + +#### Throws + +If there is an error during the passkey login process or if the user cancels the passkey prompt. + +*** + +### loginWithWallet() + +> **loginWithWallet**(`params`): `Promise`\<`string`\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:633](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L633) + +Logs in a user using the specified wallet provider. + +- This function logs in a user by authenticating with the provided wallet provider via a wallet-based signature. +- If a public key is not provided, a new one will be generated for authentication. +- Optionally accepts a custom session key and session expiration time. +- Stores the resulting session token under the specified session key, or the default session key if not provided. +- Throws an error if a public key cannot be found or generated, or if the login process fails. + +#### Parameters + +##### params + +###### expirationSeconds? + +`string` + +optional session expiration time in seconds (defaults to the configured default). + +###### publicKey? + +`string` + +optional public key to associate with the session (generated if not provided). + +###### sessionKey? + +`string` + +optional key to store the session under (defaults to the default session key). + +###### walletProvider + +[`WalletProvider`](../../../react-wallet-kit/index/WalletProvider/readme) + +wallet provider to use for authentication. + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to the created session token. + +#### Throws + +If the wallet stamper is uninitialized, a public key cannot be found or generated, or login fails. + +*** + +### logout() + +> **logout**(`params?`): `Promise`\<`void`\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:252](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L252) + +Logs out the current client session. + +- This function clears the specified session and removes any associated key pairs from storage. +- If a sessionKey is provided, it logs out from that session; otherwise, it logs out from the active session. +- Cleans up any api keys associated with the session. + +#### Parameters + +##### params? + +###### sessionKey? + +`string` + +session key to specify which session to log out from (defaults to the active session). + +#### Returns + +`Promise`\<`void`\> + +A promise that resolves when the logout process is complete. + +#### Throws + +If there is no active session or if there is an error during the logout process. + +*** + +### refreshSession() + +> **refreshSession**(`params?`): `Promise`\<`undefined` \| [`TStampLoginResponse`](../../../_turnkey/sdk-types/TStampLoginResponse/readme)\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:3162](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L3162) + +Refreshes the session associated with the specified session key, or the active session by default. + +- This function refreshes the session and updates the session token and key pair associated with the given session key. +- If a sessionKey is provided, it will refresh the session under that key; otherwise, it will use the current active session key. +- Optionally allows specifying a new expiration time for the session, a custom public key, and whether to invalidate the existing session after refreshing. +- Makes a request to the Turnkey API to stamp a new login and stores the refreshed session token. +- Automatically manages key pair cleanup and session storage to ensure consistency. +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Parameters + +##### params? + +###### expirationSeconds? + +`string` + +expiration time in seconds for the refreshed session (defaults to the configured default). + +###### invalidateExisitng? + +`boolean` + +flag to invalidate the existing session before refreshing (defaults to false). + +###### publicKey? + +`string` + +public key to use for the refreshed session (if not provided, a new key pair will be generated). + +###### sessionKey? + +`string` + +session key to refresh the session under (defaults to the active session key). + +###### stampWith? + +[`StamperType`](../../../react-wallet-kit/index/StamperType/readme) + +parameter to stamp the request with a specific stamper. + +#### Returns + +`Promise`\<`undefined` \| [`TStampLoginResponse`](../../../_turnkey/sdk-types/TStampLoginResponse/readme)\> + +A promise that resolves to a `TStampLoginResponse` object containing the refreshed session details. + +#### Throws + +If the session key does not exist, if there is no active session, or if there is an error refreshing the session. + +*** + +### removeOauthProviders() + +> **removeOauthProviders**(`params`): `Promise`\<`string`[]\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:2564](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L2564) + +Removes a list of OAuth providers from the user. + +- This function removes OAuth providers (e.g., Google, Apple) from the user's account. +- If a userId is provided, it removes the providers for that specific user; otherwise, it uses the current session's userId. +- Automatically ensures an active session exists before making the request. +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). +- Returns an array of remaining provider IDs associated with the user after removal. + +#### Parameters + +##### params + +###### providerIds + +`string`[] + +IDs of the OAuth providers to remove. + +###### stampWith? + +[`StamperType`](../../../react-wallet-kit/index/StamperType/readme) + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### userId? + +`string` + +user ID to remove the provider for a specific user (defaults to the current session's userId). + +#### Returns + +`Promise`\<`string`[]\> + +A promise that resolves to an array of provider IDs that were removed. + +#### Throws + +If there is no active session, if the userId is missing, or if there is an error removing the OAuth provider. + +*** + +### removePasskeys() + +> **removePasskeys**(`params`): `Promise`\<`string`[]\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:2684](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L2684) + +Removes passkeys (authenticator) from the user. + +- This function removes passkeys (WebAuthn/FIDO2 authenticators) from the user's account. +- If a userId is provided, it removes the passkeys for that specific user; otherwise, it uses the current session's userId. +- Automatically ensures an active session exists before making the request. +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). +- Returns an array of remaining authenticator IDs for the user after removal. + +#### Parameters + +##### params + +###### authenticatorIds + +`string`[] + +IDs of the authenticators (passkeys) to remove. + +###### stampWith? + +[`StamperType`](../../../react-wallet-kit/index/StamperType/readme) + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### userId? + +`string` + +user ID to remove the passkeys for a specific user (defaults to the current session's userId). + +#### Returns + +`Promise`\<`string`[]\> + +A promise that resolves to an array of authenticator IDs that were removed. + +#### Throws + +If there is no active session, if the userId is missing, or if there is an error removing the passkeys. + +*** + +### removeUserEmail() + +> **removeUserEmail**(`params?`): `Promise`\<`string`\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:2253](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L2253) + +Removes the user's email address. + +- This function removes the user's email address by setting it to an empty string. +- If a userId is provided, it removes the email for that specific user; otherwise, it uses the current session's userId. +- Automatically ensures an active session exists before making the request. +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Parameters + +##### params? + +###### stampWith? + +[`StamperType`](../../../react-wallet-kit/index/StamperType/readme) + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### userId? + +`string` + +user ID to remove a specific user's email address (defaults to the current session's userId). + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to the userId of the user whose email was removed. + +#### Throws + +If there is no active session, if the userId is missing, or if there is an error removing the user email. + +*** + +### removeUserPhoneNumber() + +> **removeUserPhoneNumber**(`params?`): `Promise`\<`string`\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:2355](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L2355) + +Removes the user's phone number. + +- This function removes the user's phone number by setting it to an empty string. +- If a userId is provided, it removes the phone number for that specific user; otherwise, it uses the current session's userId. +- Automatically ensures an active session exists before making the request. +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Parameters + +##### params? + +###### stampWith? + +[`StamperType`](../../../react-wallet-kit/index/StamperType/readme) + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### userId? + +`string` + +user ID to remove a specific user's phone number (defaults to the current session's userId). + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to the userId of the user whose phone number was removed. + +#### Throws + +If there is no active session, if the userId is missing, or if there is an error removing the user phone number. + +*** + +### setActiveSession() + +> **setActiveSession**(`params`): `Promise`\<`void`\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:3313](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L3313) + +Sets the active session to the specified session key. + +- This function updates the `activeSessionKey` in persistent storage to the specified session key. +- Ensures that subsequent operations use the session associated with this key as the active session. +- Does not validate whether the session key exists or is valid; it simply updates the pointer. +- Useful for switching between multiple stored sessions or restoring a previous session context. + +#### Parameters + +##### params + +###### sessionKey + +`string` + +session key to set as the active session. + +#### Returns + +`Promise`\<`void`\> + +A promise that resolves when the active session key is successfully set. + +#### Throws + +If the client is not initialized or if there is an error setting the active session key. + +*** + +### signAndSendTransaction() + +> **signAndSendTransaction**(`params`): `Promise`\<`string`\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:2006](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L2006) + +Signs and broadcasts a transaction using the specified wallet account. + +- For **connected wallets**: + - Calls the wallet’s native `signAndSendTransaction` method. + - Does **not** require an `rpcUrl`. + +- For **embedded wallets**: + - Signs the transaction using the Turnkey API. + - Requires an `rpcUrl` to broadcast the transaction. + - Broadcasts the transaction using a JSON-RPC client. + +#### Parameters + +##### params + +###### rpcUrl? + +`string` + +required for embedded wallets to broadcast the signed transaction. + +###### stampWith? + +[`StamperType`](../../../react-wallet-kit/index/StamperType/readme) + +optional stamper to tag the signing request. + +###### transactionType + +[`v1TransactionType`](../../../_turnkey/sdk-types/v1TransactionType/readme) + +transaction type (e.g., "TRANSACTION_TYPE_SOLANA"). + +###### unsignedTransaction + +`string` + +unsigned transaction (serialized string). + +###### walletAccount + +[`WalletAccount`](../../../react-wallet-kit/index/WalletAccount/readme) + +wallet account to use for signing and sending. + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to a transaction signature or hash. + +#### Throws + +If signing or broadcasting fails. + +*** + +### signMessage() + +> **signMessage**(`params`): `Promise`\<[`v1SignRawPayloadResult`](../../../_turnkey/sdk-types/v1SignRawPayloadResult/readme)\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:1835](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L1835) + +Signs a message using the specified wallet account. + +- Supports both embedded and connected wallets. +- For **connected wallets**: + - Delegates signing to the wallet provider’s native signing method. + - **Important:** For Ethereum wallets (e.g., MetaMask), signatures follow [EIP-191](https://eips.ethereum.org/EIPS/eip-191). + The message is automatically prefixed with `"\x19Ethereum Signed Message:\n" + message length` + before signing. As a result, this signature **cannot be used as a raw transaction signature** + or broadcast on-chain. +- For **embedded wallets**, uses the Turnkey API to sign the message directly. +- Automatically handles message encoding and hashing based on the wallet account’s address format, + unless explicitly overridden. + +#### Parameters + +##### params + +###### addEthereumPrefix? + +`boolean` + +whether to prefix the message with Ethereum's `"\x19Ethereum Signed Message:\n"` string. + - If `true` (default for Ethereum), the message is prefixed before signing. + - If `false`: + - Connected wallets will throw an error because they always prefix automatically. + - Embedded wallets will sign the raw message without any prefix. + +###### encoding? + +[`v1PayloadEncoding`](../../../_turnkey/sdk-types/v1PayloadEncoding/readme) + +override for the payload encoding (defaults to the encoding appropriate for the address type). + +###### hashFunction? + +[`v1HashFunction`](../../../_turnkey/sdk-types/v1HashFunction/readme) + +override for the hash function (defaults to the hash function appropriate for the address type). + +###### message + +`string` + +message to sign. + +###### stampWith? + +[`StamperType`](../../../react-wallet-kit/index/StamperType/readme) + +stamper to tag the signing request (e.g., Passkey, ApiKey, or Wallet). + +###### walletAccount + +[`WalletAccount`](../../../react-wallet-kit/index/WalletAccount/readme) + +wallet account to use for signing. + +#### Returns + +`Promise`\<[`v1SignRawPayloadResult`](../../../_turnkey/sdk-types/v1SignRawPayloadResult/readme)\> + +A promise resolving to a `v1SignRawPayloadResult` containing the signature and metadata. + +#### Throws + +If signing fails, if the wallet account does not support signing, or if the response is invalid. + +*** + +### signTransaction() + +> **signTransaction**(`params`): `Promise`\<`string`\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:1933](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L1933) + +Signs a transaction using the specified wallet account. + +- This function signs a blockchain transaction using the provided wallet address and transaction data. +- Supports all Turnkey-supported blockchain networks (e.g., Ethereum, Solana, Tron). +- Automatically determines the appropriate signing method based on the transaction type. +- Delegates signing to the Turnkey API, which returns the signed transaction and related metadata. +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Parameters + +##### params + +###### stampWith? + +[`StamperType`](../../../react-wallet-kit/index/StamperType/readme) + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### transactionType + +[`v1TransactionType`](../../../_turnkey/sdk-types/v1TransactionType/readme) + +type of transaction (e.g., "TRANSACTION_TYPE_ETHEREUM", "TRANSACTION_TYPE_SOLANA", "TRANSACTION_TYPE_TRON"). + +###### unsignedTransaction + +`string` + +unsigned transaction data (serialized as a string) to be signed. + +###### walletAccount + +[`WalletAccount`](../../../react-wallet-kit/index/WalletAccount/readme) + +wallet account to use for signing the transaction. + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to a `TSignTransactionResponse` object containing the signed transaction and any additional signing metadata. + +#### Throws + +If there is an error signing the transaction or if the response is invalid. + +*** + +### signUpWithOauth() + +> **signUpWithOauth**(`params`): `Promise`\<`string`\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:1538](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L1538) + +Signs up a user using OAuth authentication. + +- This function creates a new sub-organization for the user using the provided OIDC token, public key, and provider name. +- Handles the full OAuth sign-up flow, including sub-organization creation and session management. +- Optionally accepts additional sub-organization creation parameters and a custom session key. +- After successful sign-up, automatically logs in the user and returns a signed JWT session token. + +#### Parameters + +##### params + +###### createSubOrgParams? + +[`CreateSubOrgParams`](../../../react-wallet-kit/index/CreateSubOrgParams/readme) + +parameters for sub-organization creation (e.g., authenticators, user metadata). + +###### oidcToken + +`string` + +OIDC token received after successful authentication with the OAuth provider. + +###### providerName + +`string` + +name of the OAuth provider (e.g., "Google", "Apple"). + +###### publicKey + +`string` + +public key to associate with the new sub-organization. + +###### sessionKey? + +`string` + +session key to use for session creation (defaults to the default session key). + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to a signed JWT session token for the new sub-organization. + +#### Throws + +If there is an error during the OAuth sign-up or login process. + +*** + +### signUpWithOtp() + +> **signUpWithOtp**(`params`): `Promise`\<`string`\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:1223](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L1223) + +Signs up a user using an OTP verification token. + +- This function signs up a user using the verification token received after OTP verification (from email or SMS). +- Creates a new sub-organization for the user with the provided parameters and associates the contact (email or phone) with the sub-organization. +- Automatically generates a new API key pair for authentication and session management. +- Stores the resulting session token under the specified session key, or the default session key if not provided. +- Handles both email and SMS OTP types, and supports additional sub-organization creation parameters. + +#### Parameters + +##### params + +###### contact + +`string` + +contact information for the user (e.g., email address or phone number). + +###### createSubOrgParams? + +[`CreateSubOrgParams`](../../../react-wallet-kit/index/CreateSubOrgParams/readme) + +parameters for creating a sub-organization (e.g., authenticators, user metadata). + +###### invalidateExisting? + +`boolean` + +flag to invalidate existing session for the user. + +###### otpType + +[`OtpType`](../../../react-wallet-kit/index/OtpType/readme) + +type of OTP being used (OtpType.Email or OtpType.Sms). + +###### sessionKey? + +`string` + +session key to use for session creation (defaults to the default session key). + +###### verificationToken + +`string` + +verification token received after OTP verification. + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to a signed JWT session token for the new sub-organization. + +#### Throws + +If there is an error during the OTP sign-up process or session storage. + +*** + +### signUpWithPasskey() + +> **signUpWithPasskey**(`params?`): `Promise`\<`string`\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:378](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L378) + +Signs up a user using a passkey, creating a new sub-organization and session. + +- This function creates a new passkey authenticator and uses it to register a new sub-organization for the user. +- Handles both passkey creation and sub-organization creation in a single flow. +- Optionally accepts additional sub-organization parameters, a custom session key, a custom passkey display name, and a custom session expiration. +- Automatically generates a new API key pair for authentication and session management. +- Stores the resulting session token and manages cleanup of unused key pairs. + +#### Parameters + +##### params? + +###### createSubOrgParams? + +[`CreateSubOrgParams`](../../../react-wallet-kit/index/CreateSubOrgParams/readme) + +parameters for creating a sub-organization (e.g., authenticators, user metadata). + +###### expirationSeconds? + +`string` + +session expiration time in seconds (defaults to the configured default). + +###### passkeyDisplayName? + +`string` + +display name for the passkey (defaults to a generated name based on the current timestamp). + +###### sessionKey? + +`string` + +session key to use for storing the session (defaults to the default session key). + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to a signed JWT session token for the new sub-organization. + +#### Throws + +If there is an error during passkey creation, sub-organization creation, or session storage. + +*** + +### signUpWithWallet() + +> **signUpWithWallet**(`params`): `Promise`\<`string`\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:708](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L708) + +Signs up a user using a wallet, creating a new sub-organization and session. + +- This function creates a new wallet authenticator and uses it to register a new sub-organization for the user. +- Handles both wallet authentication and sub-organization creation in a single flow. +- Optionally accepts additional sub-organization parameters, a custom session key, and a custom session expiration. +- Automatically generates additional API key pairs for authentication and session management. +- Stores the resulting session token under the specified session key, or the default session key if not provided, and manages cleanup of unused key pairs. + +#### Parameters + +##### params + +###### createSubOrgParams? + +[`CreateSubOrgParams`](../../../react-wallet-kit/index/CreateSubOrgParams/readme) + +parameters for creating a sub-organization (e.g., authenticators, user metadata). + +###### expirationSeconds? + +`string` + +session expiration time in seconds (defaults to the configured default). + +###### sessionKey? + +`string` + +session key to use for storing the session (defaults to the default session key). + +###### walletProvider + +[`WalletProvider`](../../../react-wallet-kit/index/WalletProvider/readme) + +wallet provider to use for authentication. + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to a signed JWT session token for the new sub-organization. + +#### Throws + +If there is an error during wallet authentication, sub-organization creation, session storage, or cleanup. + +*** + +### storeSession() + +> **storeSession**(`params`): `Promise`\<`void`\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:3049](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L3049) + +Stores a session token and updates the session associated with the specified session key, or by default the active session. + +- This function parses and stores a signed JWT session token in local storage, associating it with the given session key. +- If a sessionKey is provided, the session will be stored under that key; otherwise, it will use the default session key. +- If a session already exists for the session key, its associated key pair will be deleted before storing the new session. +- After storing the session, any unused key pairs are automatically cleared from storage. +- Ensures that session management is consistent and prevents orphaned key pairs. + +#### Parameters + +##### params + +###### sessionKey? + +`string` + +session key to store the session under (defaults to the default session key). + +###### sessionToken + +`string` + +JWT session token to store. + +#### Returns + +`Promise`\<`void`\> + +A promise that resolves when the session is successfully stored. + +#### Throws + +If there is an error storing the session or cleaning up key pairs. + +*** + +### switchWalletProviderChain() + +> **switchWalletProviderChain**(`walletProvider`, `chainOrId`): `Promise`\<`void`\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:583](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L583) + +Switches the specified wallet provider to a different blockchain chain. + +- Requires the wallet manager and its connector to be initialized. +- The wallet provider must have at least one connected address. +- Does nothing if the wallet provider is already on the desired chain. + +#### Parameters + +##### walletProvider + +[`WalletProvider`](../../../react-wallet-kit/index/WalletProvider/readme) + +wallet provider to switch. + +##### chainOrId + +target chain as a chain ID string or SwitchableChain object. + +`string` | [`SwitchableChain`](../../../react-wallet-kit/index/SwitchableChain/readme) + +#### Returns + +`Promise`\<`void`\> + +A promise that resolves once the chain switch is complete. + +#### Throws + +If the wallet manager is uninitialized, the provider is not connected, or the switch fails. + +*** + +### updateUserEmail() + +> **updateUserEmail**(`params`): `Promise`\<`string`\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:2183](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L2183) + +Updates the user's email address. + +- This function updates the user's email address and, if provided, verifies it using a verification token (typically from an OTP flow). +- If a userId is provided, it updates the email for that specific user; otherwise, it uses the current session's userId. +- If a verificationToken is not provided, the email will be updated but will not be marked as verified. +- Automatically ensures an active session exists before making the request. +- Handles session management and error reporting for both update and verification flows. + +#### Parameters + +##### params + +###### email + +`string` + +new email address to set for the user. + +###### stampWith? + +[`StamperType`](../../../react-wallet-kit/index/StamperType/readme) + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### userId? + +`string` + +user ID to update a specific user's email (defaults to the current session's userId). + +###### verificationToken? + +`string` + +verification token from OTP email verification (required if verifying the email). + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to the userId of the updated user. + +#### Throws + +If there is no active session, if the userId is missing, or if there is an error updating or verifying the user email. + +*** + +### updateUserName() + +> **updateUserName**(`params`): `Promise`\<`string`\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:2399](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L2399) + +Updates the user's name. + +- This function updates the user's display name. +- If a userId is provided, it updates the name for that specific user; otherwise, it uses the current session's userId. +- Automatically ensures an active session exists before making the request. +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). +- Handles session management and error reporting for the update flow. + +#### Parameters + +##### params + +###### stampWith? + +[`StamperType`](../../../react-wallet-kit/index/StamperType/readme) + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### userId? + +`string` + +user ID to update a specific user's name (defaults to the current session's userId). + +###### userName + +`string` + +new name to set for the user. + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to the userId of the updated user. + +#### Throws + +If there is no active session, if the userId is missing, or if there is an error updating the user name. + +*** + +### updateUserPhoneNumber() + +> **updateUserPhoneNumber**(`params`): `Promise`\<`string`\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:2298](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L2298) + +Updates the user's phone number. + +- This function updates the user's phone number and, if provided, verifies it using a verification token (from an OTP flow). +- If a userId is provided, it updates the phone number for that specific user; otherwise, it uses the current session's userId. +- If a verificationToken is not provided, the phone number will be updated but will not be marked as verified. +- Automatically ensures an active session exists before making the request. +- Handles session management and error reporting for both update and verification flows. + +#### Parameters + +##### params + +###### phoneNumber + +`string` + +new phone number to set for the user. + +###### stampWith? + +[`StamperType`](../../../react-wallet-kit/index/StamperType/readme) + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### userId? + +`string` + +user ID to update a specific user's phone number (defaults to the current session's userId). + +###### verificationToken? + +`string` + +verification token from OTP phone verification (required if verifying the phone number). + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to the userId of the updated user. + +#### Throws + +If there is no active session, if the userId is missing, or if there is an error updating or verifying the user phone number. + +*** + +### verifyOtp() + +> **verifyOtp**(`params`): `Promise`\<\{ `subOrganizationId`: `string`; `verificationToken`: `string`; \}\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:1070](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L1070) + +Verifies the OTP code sent to the user. + +- This function verifies the OTP code entered by the user against the OTP sent to their contact information (email or phone) using the auth proxy. +- If verification is successful, it returns the sub-organization ID associated with the contact (if it exists) and a verification token. +- The verification token can be used for subsequent login or sign-up flows. +- Handles both email and SMS OTP types. + +#### Parameters + +##### params + +###### contact + +`string` + +contact information for the user (e.g., email address or phone number). + +###### otpCode + +`string` + +OTP code entered by the user. + +###### otpId + +`string` + +ID of the OTP to verify (returned from `initOtp`). + +###### otpType + +[`OtpType`](../../../react-wallet-kit/index/OtpType/readme) + +type of OTP being verified (OtpType.Email or OtpType.Sms). + +#### Returns + +`Promise`\<\{ `subOrganizationId`: `string`; `verificationToken`: `string`; \}\> + +A promise that resolves to an object containing: + - subOrganizationId: sub-organization ID if the contact is already associated with a sub-organization, or an empty string if not. + - verificationToken: verification token to be used for login or sign-up. + +#### Throws + +If there is an error during the OTP verification process, such as an invalid code or network failure. diff --git a/generated-docs/sdks/core/index/TurnkeyClientMethods/readme.mdx b/generated-docs/sdks/core/index/TurnkeyClientMethods/readme.mdx new file mode 100644 index 000000000..db7ff3431 --- /dev/null +++ b/generated-docs/sdks/core/index/TurnkeyClientMethods/readme.mdx @@ -0,0 +1,10 @@ +--- +title: "TurnkeyClientMethods" +mode: wide +--- + +# Type Alias: TurnkeyClientMethods + +> **TurnkeyClientMethods** = `PublicMethods`\<[`TurnkeyClient`](../TurnkeyClient/readme)\> + +Defined in: [core/src/\_\_clients\_\_/core.ts:88](https://github.com/tkhq/sdk/blob/main/packages/core/src/__clients__/core.ts#L88) diff --git a/generated-docs/sdks/core/index/WebauthnStamper/readme.mdx b/generated-docs/sdks/core/index/WebauthnStamper/readme.mdx new file mode 100644 index 000000000..a710408e0 --- /dev/null +++ b/generated-docs/sdks/core/index/WebauthnStamper/readme.mdx @@ -0,0 +1,78 @@ +--- +title: "WebauthnStamper" +mode: wide +--- + +# Class: WebauthnStamper + +Defined in: webauthn-stamper/dist/index.d.ts:11 + +Stamper to use with `@turnkey/http`'s `TurnkeyClient` + +## Constructors + +### Constructor + +> **new WebauthnStamper**(`config`): `WebauthnStamper` + +Defined in: webauthn-stamper/dist/index.d.ts:16 + +#### Parameters + +##### config + +`TWebauthnStamperConfig` + +#### Returns + +`WebauthnStamper` + +## Properties + +### allowCredentials + +> **allowCredentials**: `PublicKeyCredentialDescriptor`[] + +Defined in: webauthn-stamper/dist/index.d.ts:15 + +*** + +### rpId + +> **rpId**: `string` + +Defined in: webauthn-stamper/dist/index.d.ts:12 + +*** + +### timeout + +> **timeout**: `number` + +Defined in: webauthn-stamper/dist/index.d.ts:13 + +*** + +### userVerification + +> **userVerification**: `UserVerificationRequirement` + +Defined in: webauthn-stamper/dist/index.d.ts:14 + +## Methods + +### stamp() + +> **stamp**(`payload`): `Promise`\<\{ `stampHeaderName`: `string`; `stampHeaderValue`: `string`; \}\> + +Defined in: webauthn-stamper/dist/index.d.ts:17 + +#### Parameters + +##### payload + +`string` + +#### Returns + +`Promise`\<\{ `stampHeaderName`: `string`; `stampHeaderValue`: `string`; \}\> diff --git a/generated-docs/sdks/core/index/addressFormatConfig/readme.mdx b/generated-docs/sdks/core/index/addressFormatConfig/readme.mdx new file mode 100644 index 000000000..8cc1e8130 --- /dev/null +++ b/generated-docs/sdks/core/index/addressFormatConfig/readme.mdx @@ -0,0 +1,10 @@ +--- +title: "AddressFormatConfig" +mode: wide +--- + +# Variable: addressFormatConfig + +> `const` **addressFormatConfig**: `Record`\<[`v1AddressFormat`](../../../_turnkey/sdk-types/v1AddressFormat/readme), `AddressFormatConfig`\> + +Defined in: [core/src/utils.ts:76](https://github.com/tkhq/sdk/blob/main/packages/core/src/utils.ts#L76) diff --git a/generated-docs/sdks/core/index/generateWalletAccountsFromAddressFormat/readme.mdx b/generated-docs/sdks/core/index/generateWalletAccountsFromAddressFormat/readme.mdx new file mode 100644 index 000000000..27ae05793 --- /dev/null +++ b/generated-docs/sdks/core/index/generateWalletAccountsFromAddressFormat/readme.mdx @@ -0,0 +1,26 @@ +--- +title: "GenerateWalletAccountsFromAddressFormat" +mode: wide +--- + +# Function: generateWalletAccountsFromAddressFormat() + +> **generateWalletAccountsFromAddressFormat**(`params`): [`v1WalletAccountParams`](../../../_turnkey/sdk-types/v1WalletAccountParams/readme)[] + +Defined in: [core/src/utils.ts:614](https://github.com/tkhq/sdk/blob/main/packages/core/src/utils.ts#L614) + +## Parameters + +### params + +#### addresses + +[`v1AddressFormat`](../../../_turnkey/sdk-types/v1AddressFormat/readme)[] + +#### existingWalletAccounts? + +[`v1WalletAccount`](../../../_turnkey/sdk-types/v1WalletAccount/readme)[] + +## Returns + +[`v1WalletAccountParams`](../../../_turnkey/sdk-types/v1WalletAccountParams/readme)[] diff --git a/generated-docs/sdks/core/index/getAuthProxyConfig/readme.mdx b/generated-docs/sdks/core/index/getAuthProxyConfig/readme.mdx new file mode 100644 index 000000000..454931eb5 --- /dev/null +++ b/generated-docs/sdks/core/index/getAuthProxyConfig/readme.mdx @@ -0,0 +1,24 @@ +--- +title: "GetAuthProxyConfig" +mode: wide +--- + +# Function: getAuthProxyConfig() + +> **getAuthProxyConfig**(`authProxyConfigId`, `authProxyUrl?`): `Promise`\<[`ProxyTGetWalletKitConfigResponse`](../../../_turnkey/sdk-types/ProxyTGetWalletKitConfigResponse/readme)\> + +Defined in: [core/src/utils.ts:771](https://github.com/tkhq/sdk/blob/main/packages/core/src/utils.ts#L771) + +## Parameters + +### authProxyConfigId + +`string` + +### authProxyUrl? + +`string` + +## Returns + +`Promise`\<[`ProxyTGetWalletKitConfigResponse`](../../../_turnkey/sdk-types/ProxyTGetWalletKitConfigResponse/readme)\> diff --git a/generated-docs/sdks/core/index/isEthereumWallet/readme.mdx b/generated-docs/sdks/core/index/isEthereumWallet/readme.mdx new file mode 100644 index 000000000..2c8daeb08 --- /dev/null +++ b/generated-docs/sdks/core/index/isEthereumWallet/readme.mdx @@ -0,0 +1,20 @@ +--- +title: "IsEthereumWallet" +mode: wide +--- + +# Function: isEthereumWallet() + +> **isEthereumWallet**(`wallet`): `boolean` + +Defined in: [core/src/utils.ts:761](https://github.com/tkhq/sdk/blob/main/packages/core/src/utils.ts#L761) + +## Parameters + +### wallet + +[`WalletProvider`](../../../react-wallet-kit/index/WalletProvider/readme) + +## Returns + +`boolean` diff --git a/generated-docs/sdks/core/index/isSolanaWallet/readme.mdx b/generated-docs/sdks/core/index/isSolanaWallet/readme.mdx new file mode 100644 index 000000000..c88b5dae9 --- /dev/null +++ b/generated-docs/sdks/core/index/isSolanaWallet/readme.mdx @@ -0,0 +1,20 @@ +--- +title: "IsSolanaWallet" +mode: wide +--- + +# Function: isSolanaWallet() + +> **isSolanaWallet**(`wallet`): `boolean` + +Defined in: [core/src/utils.ts:766](https://github.com/tkhq/sdk/blob/main/packages/core/src/utils.ts#L766) + +## Parameters + +### wallet + +[`WalletProvider`](../../../react-wallet-kit/index/WalletProvider/readme) + +## Returns + +`boolean` diff --git a/generated-docs/sdks/core/index/readme.mdx b/generated-docs/sdks/core/index/readme.mdx new file mode 100644 index 000000000..f6e4e892d --- /dev/null +++ b/generated-docs/sdks/core/index/readme.mdx @@ -0,0 +1,28 @@ +--- +title: "Index" +mode: wide +--- + +# index + +## Classes + +- [ApiKeyStamper](ApiKeyStamper/readme) +- [TurnkeyClient](TurnkeyClient/readme) +- [WebauthnStamper](WebauthnStamper/readme) + +## Type Aliases + +- [TurnkeyClientMethods](TurnkeyClientMethods/readme) + +## Variables + +- [addressFormatConfig](addressFormatConfig/readme) +- [signWithApiKey](signWithApiKey/readme) + +## Functions + +- [generateWalletAccountsFromAddressFormat](generateWalletAccountsFromAddressFormat/readme) +- [getAuthProxyConfig](getAuthProxyConfig/readme) +- [isEthereumWallet](isEthereumWallet/readme) +- [isSolanaWallet](isSolanaWallet/readme) diff --git a/generated-docs/sdks/core/index/signWithApiKey/readme.mdx b/generated-docs/sdks/core/index/signWithApiKey/readme.mdx new file mode 100644 index 000000000..eb7a2d916 --- /dev/null +++ b/generated-docs/sdks/core/index/signWithApiKey/readme.mdx @@ -0,0 +1,36 @@ +--- +title: "SignWithApiKey" +mode: wide +--- + +# Variable: signWithApiKey() + +> `const` **signWithApiKey**: (`input`, `runtimeOverride?`) => `Promise`\<`string`\> + +Defined in: api-key-stamper/dist/index.d.ts:11 + +Signature function abstracting the differences between NodeJS and web environments for signing with API keys. + +## Parameters + +### input + +#### content + +`string` + +#### privateKey + +`string` + +#### publicKey + +`string` + +### runtimeOverride? + +[`Runtime`](../../../api-key-stamper/index/Runtime/readme) + +## Returns + +`Promise`\<`string`\> diff --git a/generated-docs/sdks/core/readme.mdx b/generated-docs/sdks/core/readme.mdx new file mode 100644 index 000000000..96b1b9f42 --- /dev/null +++ b/generated-docs/sdks/core/readme.mdx @@ -0,0 +1,10 @@ +--- +title: "Core" +mode: wide +--- + +# core + +## Modules + +- [index](index/readme) diff --git a/generated-docs/sdks/react-wallet-kit/README.mdx b/generated-docs/sdks/react-wallet-kit/README.mdx new file mode 100644 index 000000000..1f014a67d --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/README.mdx @@ -0,0 +1,10 @@ +--- +title: "React Wallet Kit" +mode: wide +--- + +# react-wallet-kit + +## Modules + +- [index](index/readme) diff --git a/generated-docs/sdks/react-wallet-kit/index/ActivityMetadata/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/ActivityMetadata/readme.mdx new file mode 100644 index 000000000..44218f11b --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/ActivityMetadata/readme.mdx @@ -0,0 +1,24 @@ +--- +title: "ActivityMetadata" +mode: wide +--- + +# Interface: ActivityMetadata + +Defined in: core/dist/\_\_types\_\_/base.d.ts:40 + +## Properties + +### activity + +> **activity**: `object` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:41 + +#### id + +> **id**: `string` + +#### status + +> **status**: `"ACTIVITY_STATUS_CREATED"` \| `"ACTIVITY_STATUS_PENDING"` \| `"ACTIVITY_STATUS_COMPLETED"` \| `"ACTIVITY_STATUS_FAILED"` \| `"ACTIVITY_STATUS_CONSENSUS_NEEDED"` \| `"ACTIVITY_STATUS_REJECTED"` diff --git a/generated-docs/sdks/react-wallet-kit/index/ActivityResponse/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/ActivityResponse/readme.mdx new file mode 100644 index 000000000..7188c156e --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/ActivityResponse/readme.mdx @@ -0,0 +1,28 @@ +--- +title: "ActivityResponse" +mode: wide +--- + +# Interface: ActivityResponse + +Defined in: core/dist/\_\_types\_\_/base.d.ts:33 + +## Properties + +### activity + +> **activity**: `object` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:34 + +#### id + +> **id**: `string` + +#### result + +> **result**: `Record`\<`string`, `any`\> + +#### status + +> **status**: `"ACTIVITY_STATUS_CREATED"` \| `"ACTIVITY_STATUS_PENDING"` \| `"ACTIVITY_STATUS_COMPLETED"` \| `"ACTIVITY_STATUS_FAILED"` \| `"ACTIVITY_STATUS_CONSENSUS_NEEDED"` \| `"ACTIVITY_STATUS_REJECTED"` diff --git a/generated-docs/sdks/react-wallet-kit/index/ApiKeyStamperBase/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/ApiKeyStamperBase/readme.mdx new file mode 100644 index 000000000..382f9b2cf --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/ApiKeyStamperBase/readme.mdx @@ -0,0 +1,90 @@ +--- +title: "ApiKeyStamperBase" +mode: wide +--- + +# Interface: ApiKeyStamperBase + +Defined in: core/dist/\_\_types\_\_/base.d.ts:290 + +## Methods + +### clearKeyPairs() + +> **clearKeyPairs**(): `Promise`\<`void`\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:297 + +#### Returns + +`Promise`\<`void`\> + +*** + +### createKeyPair() + +> **createKeyPair**(`externalKeyPair?`): `Promise`\<`string`\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:292 + +#### Parameters + +##### externalKeyPair? + +`CryptoKeyPair` | \{ `privateKey`: `string`; `publicKey`: `string`; \} + +#### Returns + +`Promise`\<`string`\> + +*** + +### deleteKeyPair() + +> **deleteKeyPair**(`publicKeyHex`): `Promise`\<`void`\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:296 + +#### Parameters + +##### publicKeyHex + +`string` + +#### Returns + +`Promise`\<`void`\> + +*** + +### listKeyPairs() + +> **listKeyPairs**(): `Promise`\<`string`[]\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:291 + +#### Returns + +`Promise`\<`string`[]\> + +*** + +### stamp() + +> **stamp**(`payload`, `publicKeyHex`): `Promise`\<[`TStamp`](../TStamp/readme)\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:298 + +#### Parameters + +##### payload + +`string` + +##### publicKeyHex + +`string` + +#### Returns + +`Promise`\<[`TStamp`](../TStamp/readme)\> diff --git a/generated-docs/sdks/react-wallet-kit/index/AuthClient/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/AuthClient/readme.mdx new file mode 100644 index 000000000..f9653b284 --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/AuthClient/readme.mdx @@ -0,0 +1,34 @@ +--- +title: "AuthClient" +mode: wide +--- + +# Enumeration: AuthClient + +Defined in: core/dist/\_\_types\_\_/base.d.ts:208 + +The Client used to authenticate the user. + +## Enumeration Members + +### IndexedDb + +> **IndexedDb**: `"indexed-db"` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:211 + +*** + +### Passkey + +> **Passkey**: `"passkey"` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:209 + +*** + +### Wallet + +> **Wallet**: `"wallet"` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:210 diff --git a/generated-docs/sdks/react-wallet-kit/index/BaseWalletInterface/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/BaseWalletInterface/readme.mdx new file mode 100644 index 000000000..4ce6ded0b --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/BaseWalletInterface/readme.mdx @@ -0,0 +1,141 @@ +--- +title: "BaseWalletInterface" +mode: wide +--- + +# Interface: BaseWalletInterface + +Defined in: core/dist/\_\_types\_\_/base.d.ts:361 + +Base interface for wallet functionalities common across different blockchain chains. + BaseWalletInterface + +## Extended by + +- [`SolanaWalletInterface`](../SolanaWalletInterface/readme) +- [`EthereumWalletInterface`](../EthereumWalletInterface/readme) +- [`WalletConnectInterface`](../WalletConnectInterface/readme) + +## Properties + +### connectWalletAccount() + +> **connectWalletAccount**: (`provider`) => `Promise`\<`void`\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:366 + +#### Parameters + +##### provider + +[`WalletProvider`](../WalletProvider/readme) + +#### Returns + +`Promise`\<`void`\> + +*** + +### disconnectWalletAccount() + +> **disconnectWalletAccount**: (`provider`) => `Promise`\<`void`\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:367 + +#### Parameters + +##### provider + +[`WalletProvider`](../WalletProvider/readme) + +#### Returns + +`Promise`\<`void`\> + +*** + +### getProviders() + +> **getProviders**: () => `Promise`\<[`WalletProvider`](../WalletProvider/readme)[]\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:365 + +#### Returns + +`Promise`\<[`WalletProvider`](../WalletProvider/readme)[]\> + +*** + +### getPublicKey() + +> **getPublicKey**: (`provider`) => `Promise`\<`string`\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:364 + +Retrieves the public key as a string. + +#### Parameters + +##### provider + +[`WalletProvider`](../WalletProvider/readme) + +#### Returns + +`Promise`\<`string`\> + +*** + +### interfaceType + +> **interfaceType**: [`WalletInterfaceType`](../WalletInterfaceType/readme) + +Defined in: core/dist/\_\_types\_\_/base.d.ts:362 + +*** + +### sign() + +> **sign**: (`message`, `provider`, `intent`) => `Promise`\<`string`\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:363 + +#### Parameters + +##### message + +`string` + +##### provider + +[`WalletProvider`](../WalletProvider/readme) + +##### intent + +[`SignIntent`](../SignIntent/readme) + +#### Returns + +`Promise`\<`string`\> + +*** + +### switchChain()? + +> `optional` **switchChain**: (`provider`, `chainOrId`) => `Promise`\<`void`\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:368 + +#### Parameters + +##### provider + +[`WalletProvider`](../WalletProvider/readme) + +##### chainOrId + +`string` | [`SwitchableChain`](../SwitchableChain/readme) + +#### Returns + +`Promise`\<`void`\> diff --git a/generated-docs/sdks/react-wallet-kit/index/Chain/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/Chain/readme.mdx new file mode 100644 index 000000000..2711c00dc --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/Chain/readme.mdx @@ -0,0 +1,24 @@ +--- +title: "Chain" +mode: wide +--- + +# Enumeration: Chain + +Defined in: core/dist/\_\_types\_\_/base.d.ts:306 + +## Enumeration Members + +### Ethereum + +> **Ethereum**: `"ethereum"` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:307 + +*** + +### Solana + +> **Solana**: `"solana"` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:308 diff --git a/generated-docs/sdks/react-wallet-kit/index/ChainInfo/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/ChainInfo/readme.mdx new file mode 100644 index 000000000..93c05f9c5 --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/ChainInfo/readme.mdx @@ -0,0 +1,10 @@ +--- +title: "ChainInfo" +mode: wide +--- + +# Type Alias: ChainInfo + +> **ChainInfo** = [`EvmChainInfo`](../EvmChainInfo/readme) \| [`SolanaChainInfo`](../SolanaChainInfo/readme) + +Defined in: core/dist/\_\_types\_\_/base.d.ts:329 diff --git a/generated-docs/sdks/react-wallet-kit/index/ClientContextType/README.mdx b/generated-docs/sdks/react-wallet-kit/index/ClientContextType/README.mdx new file mode 100644 index 000000000..06796816f --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/ClientContextType/README.mdx @@ -0,0 +1,3748 @@ +--- +title: "ClientContextType" +mode: wide +--- + +# Interface: ClientContextType + +Defined in: [react-wallet-kit/src/providers/client/Types.tsx:41](https://github.com/tkhq/sdk/blob/main/packages/react-wallet-kit/src/providers/client/Types.tsx#L41) + +## Extends + +- [`TurnkeyClientMethods`](../../../core/index/TurnkeyClientMethods/readme) + +## Properties + +### addOauthProvider() + +> **addOauthProvider**: (`params`) => `Promise`\<`string`[]\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:657 + +Adds an OAuth provider to the user. + +- This function adds an OAuth provider (e.g., Google, Apple) to the user account. +- If a userId is provided, it adds the provider for that specific user; otherwise, it uses the current session's userId. +- Automatically checks if an account already exists for the provided OIDC token and prevents duplicate associations. +- If the user's email is not set or not verified, attempts to update and verify the email using the email from the OIDC token. +- Handles session management and error reporting for the add provider flow. +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Parameters + +##### params + +###### oidcToken + +`string` + +OIDC token for the OAuth provider. + +###### providerName + +`string` + +name of the OAuth provider to add (e.g., "Google", "Apple"). + +###### stampWith? + +[`StamperType`](../StamperType/readme) + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### userId? + +`string` + +user ID to add the provider for a specific user (defaults to current session's userId). + +#### Returns + +`Promise`\<`string`[]\> + +A promise that resolves to an array of provider IDs associated with the user. + +#### Throws + +If there is no active session, if the account already exists, or if there is an error adding the OAuth provider. + +#### Inherited from + +`TurnkeyClientMethods.addOauthProvider` + +*** + +### addPasskey() + +> **addPasskey**: (`params?`) => `Promise`\<`string`[]\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:699 + +Adds a new passkey authenticator for the user. + +- This function prompts the user to create a new passkey (WebAuthn/FIDO2) and adds it as an authenticator for the user. +- Handles both web and React Native environments, automatically selecting the appropriate passkey creation flow. +- If a userId is provided, the passkey is added for that specific user; otherwise, it uses the current session's userId. +- The passkey's name and display name can be customized; if not provided, defaults are generated. +- The resulting passkey attestation and challenge are registered with Turnkey as a new authenticator. + +#### Parameters + +##### params? + +###### displayName? + +`string` + +display name of the passkey (defaults to the value of `name`). + +###### name? + +`string` + +name of the passkey (defaults to "Turnkey Passkey-`timestamp`"). + +###### stampWith? + +[`StamperType`](../StamperType/readme) + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### userId? + +`string` + +user ID to add the passkey for a specific user (defaults to the current session's userId). + +#### Returns + +`Promise`\<`string`[]\> + +A promise that resolves to an array of authenticator IDs for the newly added passkey(s). + +#### Throws + +If there is no active session, if passkey creation fails, or if there is an error adding the passkey. + +#### Inherited from + +`TurnkeyClientMethods.addPasskey` + +*** + +### allSessions? + +> `optional` **allSessions**: `Record`\<`string`, [`Session`](../../../sdk-browser/index/Session/readme)\> + +Defined in: [react-wallet-kit/src/providers/client/Types.tsx:44](https://github.com/tkhq/sdk/blob/main/packages/react-wallet-kit/src/providers/client/Types.tsx#L44) + +*** + +### authState + +> **authState**: `AuthState` + +Defined in: [react-wallet-kit/src/providers/client/Types.tsx:46](https://github.com/tkhq/sdk/blob/main/packages/react-wallet-kit/src/providers/client/Types.tsx#L46) + +*** + +### clearAllSessions() + +> **clearAllSessions**: () => `Promise`\<`void`\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:884 + +Clears all sessions and resets the active session state. + +- This function removes all session data from the client and persistent storage, including all associated key pairs. +- Iterates through all stored session keys, clearing each session and deleting its corresponding API key pair. +- After clearing, there will be no active session, and all session-related data will be removed from local storage. +- Throws an error if no sessions exist or if there is an error during the clearing process. + +#### Returns + +`Promise`\<`void`\> + +A promise that resolves when all sessions are successfully cleared. + +#### Throws + +If no sessions exist or if there is an error clearing all sessions. + +#### Inherited from + +`TurnkeyClientMethods.clearAllSessions` + +*** + +### clearSession() + +> **clearSession**: (`params?`) => `Promise`\<`void`\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:870 + +Clears the session associated with the specified session key, or the active session by default. + +- This function deletes the session and its associated key pair from storage. +- If a sessionKey is provided, it will clear the session under that key; otherwise, it will clear the default (active) session. +- Removes the session data from local storage and deletes the corresponding API key pair from the key store. +- Throws an error if the session does not exist or if there is an error during the clearing process. + +#### Parameters + +##### params? + +###### sessionKey? + +`string` + +session key to clear the session under (defaults to the default session key). + +#### Returns + +`Promise`\<`void`\> + +A promise that resolves when the session is successfully cleared. + +#### Throws + +If the session does not exist or if there is an error clearing the session. + +#### Inherited from + +`TurnkeyClientMethods.clearSession` + +*** + +### clearUnusedKeyPairs() + +> **clearUnusedKeyPairs**: () => `Promise`\<`void`\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:974 + +Clears any unused API key pairs from persistent storage. + +- This function scans all API key pairs stored in indexedDB and removes any key pairs that are not associated with a session in persistent storage. +- Ensures that only key pairs referenced by existing sessions are retained, preventing orphaned or stale key pairs from accumulating. +- Iterates through all stored session keys and builds a map of in-use public keys, then deletes any key pairs not present in this map. +- Intended to be called after session changes (e.g., login, logout, session replacement) to keep key storage clean and secure. + +#### Returns + +`Promise`\<`void`\> + +A promise that resolves when all unused key pairs are successfully cleared. + +#### Throws + +If there is an error listing, checking, or deleting unused key pairs. + +#### Inherited from + +`TurnkeyClientMethods.clearUnusedKeyPairs` + +*** + +### clientState + +> **clientState**: `ClientState` + +Defined in: [react-wallet-kit/src/providers/client/Types.tsx:45](https://github.com/tkhq/sdk/blob/main/packages/react-wallet-kit/src/providers/client/Types.tsx#L45) + +*** + +### completeOauth() + +> **completeOauth**: (`params`) => `Promise`\<`string`\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:347 + +Completes the OAuth authentication flow by either signing up or logging in the user, depending on whether a sub-organization already exists for the provided OIDC token. + +- This function first checks if there is an existing sub-organization associated with the OIDC token. +- If a sub-organization exists, it proceeds with the OAuth login flow. +- If no sub-organization exists, it creates a new sub-organization and completes the sign-up flow. +- Optionally accepts a custom OAuth provider name, session key, and additional sub-organization creation parameters. +- Handles session storage and management, and supports invalidating existing sessions if specified. + +#### Parameters + +##### params + +###### createSubOrgParams? + +[`CreateSubOrgParams`](../CreateSubOrgParams/readme) + +parameters for sub-organization creation (e.g., authenticators, user metadata). + +###### invalidateExisting? + +`boolean` + +flag to invalidate existing sessions for the user. + +###### oidcToken + +`string` + +OIDC token received after successful authentication with the OAuth provider. + +###### providerName? + +`string` + +name of the OAuth provider (defaults to a generated name with a timestamp). + +###### publicKey + +`string` + +public key to use for authentication. Must be generated prior to calling this function. + +###### sessionKey? + +`string` + +session key to use for session creation (defaults to the default session key). + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to a signed JWT session token for the user. + +#### Throws + +If there is an error during the OAuth completion process, such as account lookup, sign-up, or login. + +#### Inherited from + +`TurnkeyClientMethods.completeOauth` + +*** + +### completeOtp() + +> **completeOtp**: (`params`) => `Promise`\<`string`\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:319 + +Completes the OTP authentication flow by verifying the OTP code and then either signing up or logging in the user. + +- This function first verifies the OTP code for the provided contact and OTP type. +- If the contact is not associated with an existing sub-organization, it will automatically create a new sub-organization and complete the sign-up flow. +- If the contact is already associated with a sub-organization, it will complete the login flow. +- Supports passing a custom public key for authentication, invalidating existing session, specifying a session key, and providing additional sub-organization creation parameters. +- Handles both email and SMS OTP types. + +#### Parameters + +##### params + +###### contact + +`string` + +contact information for the user (e.g., email address or phone number). + +###### createSubOrgParams? + +[`CreateSubOrgParams`](../CreateSubOrgParams/readme) + +parameters for sub-organization creation (e.g., authenticators, user metadata). + +###### invalidateExisting? + +`boolean` + +flag to invalidate existing sessions for the user. + +###### otpCode + +`string` + +OTP code entered by the user. + +###### otpId + +`string` + +ID of the OTP to complete (returned from `initOtp`). + +###### otpType + +[`OtpType`](../OtpType/readme) + +type of OTP being completed (OtpType.Email or OtpType.Sms). + +###### publicKey? + +`string` + +public key to use for authentication. If not provided, a new key pair may be generated. + +###### sessionKey? + +`string` + +session key to use for session creation (defaults to the default session key). + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to a signed JWT session token for the user. + +#### Throws + +If there is an error during OTP verification, sign-up, or login. + +#### Inherited from + +`TurnkeyClientMethods.completeOtp` + +*** + +### config? + +> `optional` **config**: `TurnkeyProviderConfig` + +Defined in: [react-wallet-kit/src/providers/client/Types.tsx:47](https://github.com/tkhq/sdk/blob/main/packages/react-wallet-kit/src/providers/client/Types.tsx#L47) + +*** + +### connectWalletAccount() + +> **connectWalletAccount**: (`walletProvider`) => `Promise`\<`void`\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:118 + +Connects the specified wallet account. + +- Requires the wallet manager and its connector to be initialized. + +#### Parameters + +##### walletProvider + +[`WalletProvider`](../WalletProvider/readme) + +wallet provider to connect. + +#### Returns + +`Promise`\<`void`\> + +A promise that resolves once the wallet account is connected. + +#### Throws + +If the wallet manager is uninitialized or the connection fails. + +#### Inherited from + +`TurnkeyClientMethods.connectWalletAccount` + +*** + +### createApiKeyPair() + +> **createApiKeyPair**: (`params?`) => `Promise`\<`string`\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:989 + +Creates a new API key pair and returns the public key. + +- This function generates a new API key pair and stores it in the underlying key store (IndexedDB). +- If an external key pair is provided, it will use that key pair for creation instead of generating a new one. +- If `storeOverride` is set to true, the generated or provided public key will be set as the override key in the API key stamper, making it the active key for subsequent signing operations. +- Ensures the API key stamper is initialized before proceeding. +- Handles both native CryptoKeyPair objects and raw key material. + +#### Parameters + +##### params? + +###### externalKeyPair? + +`CryptoKeyPair` \| \{ `privateKey`: `string`; `publicKey`: `string`; \} + +An externally generated key pair (either a CryptoKeyPair or an object with publicKey/privateKey strings) to use instead of generating a new one. + +###### storeOverride? + +`boolean` + +If true, sets the generated or provided public key as the override key in the API key stamper (defaults to false). +@returnparams.s A promise that resolves to the public key of the created or provided API key pair as a string. + +#### Returns + +`Promise`\<`string`\> + +#### Throws + +If the API key stamper is not initialized or if there is an error during key pair creation or storage. + +#### Inherited from + +`TurnkeyClientMethods.createApiKeyPair` + +*** + +### createPasskey() + +> **createPasskey**: (`params?`) => `Promise`\<\{ `attestation`: [`v1Attestation`](../../../_turnkey/sdk-types/v1Attestation/readme); `encodedChallenge`: `string`; \}\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:34 + +Creates a new passkey authenticator for the user. + +- This function generates a new passkey attestation and challenge, suitable for registration with the user's device. +- Handles both web and React Native environments, automatically selecting the appropriate passkey creation flow. +- The resulting attestation and challenge can be used to register the passkey with Turnkey. + +#### Parameters + +##### params? + +###### displayName? + +`string` + +display name for the passkey. If not provided, defaults to "A Passkey". + +###### name? + +`string` + +name of the passkey. If not provided, defaults to "A Passkey". + +###### stampWith? + +[`StamperType`](../StamperType/readme) + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Returns + +`Promise`\<\{ `attestation`: [`v1Attestation`](../../../_turnkey/sdk-types/v1Attestation/readme); `encodedChallenge`: `string`; \}\> + +A promise that resolves to an object containing: + - attestation: attestation object returned from the passkey creation process. + - encodedChallenge: encoded challenge string used for passkey registration. + +#### Throws + +If there is an error during passkey creation, or if the platform is unsupported. + +#### Inherited from + +`TurnkeyClientMethods.createPasskey` + +*** + +### createWallet() + +> **createWallet**: (`params`) => `Promise`\<`string`\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:744 + +Creates a new wallet for sub-organization. + +- This function creates a new wallet for the current sub-organization. +- If an organizationId is provided, the wallet will be created under that specific sub-organization; otherwise, it uses the current session's organizationId. +- If a list of address formats is provided, accounts will be created in the wallet based on those formats (starting from path index 0). +- If a list of account parameters is provided, those accounts will be created in the wallet. +- If no accounts or address formats are provided, default Ethereum and Solana accounts will be created. +- Optionally allows specifying the mnemonic length for the wallet seed phrase (defaults to 12). +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Parameters + +##### params + +###### accounts? + +[`v1AddressFormat`](../../../_turnkey/sdk-types/v1AddressFormat/readme)[] \| [`v1WalletAccountParams`](../../../_turnkey/sdk-types/v1WalletAccountParams/readme)[] + +array of account parameters or address formats to create in the wallet. + +###### mnemonicLength? + +`number` + +mnemonic length for the wallet seed phrase (defaults to 12). + +###### organizationId? + +`string` + +organization ID to create the wallet under a specific sub-organization (defaults to the current session's organizationId). + +###### stampWith? + +[`StamperType`](../StamperType/readme) + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### walletName + +`string` + +name of the wallet to create. + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to the ID of the newly created wallet. + +#### Throws + +If there is no active session or if there is an error creating the wallet. + +#### Inherited from + +`TurnkeyClientMethods.createWallet` + +*** + +### createWalletAccounts() + +> **createWalletAccounts**: (`params`) => `Promise`\<`string`[]\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:768 + +Creates new accounts in the specified wallet. + +- This function creates new wallet accounts based on the provided account parameters or address formats. +- If a walletId is provided, it creates the accounts in that specific wallet; otherwise, it uses the current session's wallet. +- If a list of address formats is provided, it will create accounts in the wallet based on those formats, automatically determining the next available path indexes to avoid duplicates with existing accounts. +- If account parameters are provided, they are used directly for account creation. +- Automatically queries existing wallet accounts to prevent duplicate account creation for the same address format and path. +- Supports stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Parameters + +##### params + +###### accounts + +[`v1AddressFormat`](../../../_turnkey/sdk-types/v1AddressFormat/readme)[] \| [`v1WalletAccountParams`](../../../_turnkey/sdk-types/v1WalletAccountParams/readme)[] + +An array of account parameters or address formats to create in the wallet. + +###### organizationId? + +`string` + +organization ID to create the accounts under a specific organization (walletId must be associated with the sub-organization). + +###### stampWith? + +[`StamperType`](../StamperType/readme) + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### walletId + +`string` + +ID of the wallet to create accounts in. + +#### Returns + +`Promise`\<`string`[]\> + +A promise that resolves to an array of addresses for the newly created accounts. + +#### Throws + +If there is no active session, if the wallet does not exist, or if there is an error creating the wallet accounts. + +#### Inherited from + +`TurnkeyClientMethods.createWalletAccounts` + +*** + +### deleteSubOrganization() + +> **deleteSubOrganization**: (`params?`) => `Promise`\<[`TDeleteSubOrganizationResponse`](../../../_turnkey/sdk-types/TDeleteSubOrganizationResponse/readme)\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:836 + +Deletes the current sub-organization (sub-org) for the active session. + +- This function deletes the sub-organization associated with the current active session. +- By default, the deletion will fail if any wallets associated with the sub-organization have not been exported. +- If `deleteWithoutExport` is set to true, the sub-organization will be deleted even if its wallets have not been exported (potentially resulting in loss of access to those wallets). +- Requires an active session; otherwise, an error is thrown. +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Parameters + +##### params? + +###### deleteWithoutExport? + +`boolean` + +flag to delete the sub-organization without requiring all wallets to be exported first (defaults to false). + +###### stampWith? + +[`StamperType`](../StamperType/readme) + +parameter to stamp the request with a specific stamper. + +#### Returns + +`Promise`\<[`TDeleteSubOrganizationResponse`](../../../_turnkey/sdk-types/TDeleteSubOrganizationResponse/readme)\> + +A promise that resolves to a `TDeleteSubOrganizationResponse` object containing the result of the deletion. + +#### Throws + +If there is no active session or if there is an error deleting the sub-organization. + +#### Inherited from + +`TurnkeyClientMethods.deleteSubOrganization` + +*** + +### disconnectWalletAccount() + +> **disconnectWalletAccount**: (`walletProvider`) => `Promise`\<`void`\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:128 + +Disconnects the specified wallet account. + +- Requires the wallet manager and its connector to be initialized. + +#### Parameters + +##### walletProvider + +[`WalletProvider`](../WalletProvider/readme) + +wallet provider to disconnect. + +#### Returns + +`Promise`\<`void`\> + +A promise that resolves once the wallet account is disconnected. + +#### Throws + +If the wallet manager is uninitialized or the disconnection fails. + +#### Inherited from + +`TurnkeyClientMethods.disconnectWalletAccount` + +*** + +### exportWallet() + +> **exportWallet**: (`params`) => `Promise`\<`string`\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:791 + +Exports a wallet as an encrypted bundle. + +- This function exports the specified wallet and its accounts as an encrypted bundle, suitable for backup or transfer. +- The exported bundle contains the wallet's seed phrase, encrypted to the provided target public key. +- If a targetPublicKey is provided, the bundle will be encrypted to that public key; otherwise, an error will be thrown. +- If an organizationId is provided, the wallet will be exported under that sub-organization; otherwise, the current session's organizationId is used. +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). +- The exported bundle can later be imported using the `importWallet` method. + +#### Parameters + +##### params + +###### organizationId? + +`string` + +organization ID to export the wallet under a specific sub-organization (walletId must be associated with the sub-organization). + +###### stampWith? + +[`StamperType`](../StamperType/readme) + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### targetPublicKey + +`string` + +public key to encrypt the bundle to (required). + +###### walletId + +`string` + +ID of the wallet to export. + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to an `ExportBundle` object containing the encrypted wallet seed phrase and metadata. + +#### Throws + +If there is no active session, if the targetPublicKey is missing, or if there is an error exporting the wallet. + +#### Inherited from + +`TurnkeyClientMethods.exportWallet` + +*** + +### fetchUser() + +> **fetchUser**: (`params?`) => `Promise`\<[`v1User`](../../../_turnkey/sdk-types/v1User/readme)\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:537 + +Fetches the user details for the current session or a specified user. + +- Retrieves user details from the Turnkey API using the provided userId and organizationId, or defaults to those from the active session. +- If no userId is provided, the userId from the current session is used. +- If no organizationId is provided, the organizationId from the current session is used. +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). +- Ensures that an active session exists before making the request. + +#### Parameters + +##### params? + +###### organizationId? + +`string` + +organization ID to specify the sub-organization (defaults to the current session's organizationId). + +###### stampWith? + +[`StamperType`](../StamperType/readme) + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### userId? + +`string` + +user ID to fetch specific user details (defaults to the current session's userId). + +#### Returns + +`Promise`\<[`v1User`](../../../_turnkey/sdk-types/v1User/readme)\> + +A promise that resolves to a `v1User` object containing the user details. + +#### Throws + +If there is no active session, if there is no userId, or if there is an error fetching user details. + +#### Inherited from + +`TurnkeyClientMethods.fetchUser` + +*** + +### fetchWalletAccounts() + +> **fetchWalletAccounts**: (`params`) => `Promise`\<[`WalletAccount`](../WalletAccount/readme)[]\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:431 + +Fetches all accounts for a specific wallet, including both embedded and connected wallet accounts. + +- For embedded wallets, retrieves accounts from the Turnkey API, supporting pagination (defaults to the first page with a limit of 100 accounts). +- For connected wallets (e.g., browser extensions or external providers), constructs account objects for each connected address from the provided or discovered wallet providers. +- Automatically determines the account type and populates relevant fields such as address, curve, and signing capability. +- Optionally allows filtering by a specific set of wallet providers and supports custom pagination options. +- Supports stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Parameters + +##### params + +###### paginationOptions? + +[`v1Pagination`](../../../_turnkey/sdk-types/v1Pagination/readme) + +pagination options for embedded wallets. + +###### stampWith? + +[`StamperType`](../StamperType/readme) + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### wallet + +[`Wallet`](../Wallet/readme) + +wallet for which to fetch accounts. + +###### walletProviders? + +[`WalletProvider`](../WalletProvider/readme)[] + +list of wallet providers to filter by (used for connected wallets). + +#### Returns + +`Promise`\<[`WalletAccount`](../WalletAccount/readme)[]\> + +A promise that resolves to an array of `v1WalletAccount` objects. + +#### Throws + +If no active session is found or if there is an error fetching wallet accounts. + +#### Inherited from + +`TurnkeyClientMethods.fetchWalletAccounts` + +*** + +### fetchWallets() + +> **fetchWallets**: (`params?`) => `Promise`\<[`Wallet`](../Wallet/readme)[]\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:412 + +Fetches all wallets for the current user, including both embedded and connected wallets. + +- Retrieves all wallets associated with the organizationId from the current active session. +- For each embedded wallet, automatically fetches and attaches all associated wallet accounts. +- For connected wallets (e.g., browser extensions or external providers), groups providers by wallet name and attaches all connected accounts. +- Returns both embedded and connected wallets in a single array, each with their respective accounts populated. +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Parameters + +##### params? + +###### stampWith? + +[`StamperType`](../StamperType/readme) + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Returns + +`Promise`\<[`Wallet`](../Wallet/readme)[]\> + +A promise that resolves to an array of `Wallet` objects. + +#### Throws + +If no active session is found or if there is an error fetching wallets. + +#### Inherited from + +`TurnkeyClientMethods.fetchWallets` + +*** + +### getActiveSessionKey() + +> **getActiveSessionKey**: () => `Promise`\<`undefined` \| `string`\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:962 + +Retrieves the active session key currently set in persistent storage. + +- This function fetches the session key that is currently marked as active in the client's persistent storage. +- The active session key determines which session is used for all session-dependent operations. +- If no active session key is set, returns `undefined`. +- Useful for determining which session is currently in use, especially when managing multiple sessions. + +#### Returns + +`Promise`\<`undefined` \| `string`\> + +A promise that resolves to the active session key as a string, or `undefined` if no active session is set. + +#### Throws + +If there is an error retrieving the active session key from storage. + +#### Inherited from + +`TurnkeyClientMethods.getActiveSessionKey` + +*** + +### getAllSessions() + +> **getAllSessions**: () => `Promise`\<`undefined` \| `Record`\<`string`, [`Session`](../../../sdk-browser/index/Session/readme)\>\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:935 + +Retrieves all sessions stored in persistent storage. + +- This function fetches all session objects currently stored by the client, including those that are not active. +- Returns a record mapping each session key to its corresponding `Session` object. +- Useful for session management, auditing, or displaying all available sessions to the user. +- Automatically skips any session keys that do not have a valid session object. + +#### Returns + +`Promise`\<`undefined` \| `Record`\<`string`, [`Session`](../../../sdk-browser/index/Session/readme)\>\> + +A promise that resolves to a record of session keys and their corresponding `Session` objects, or `undefined` if no sessions exist. + +#### Throws + +If there is an error retrieving sessions from storage. + +#### Inherited from + +`TurnkeyClientMethods.getAllSessions` + +*** + +### getProxyAuthConfig() + +> **getProxyAuthConfig**: () => `Promise`\<[`ProxyTGetWalletKitConfigResponse`](../../../_turnkey/sdk-types/ProxyTGetWalletKitConfigResponse/readme)\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:1007 + +Fetches the WalletKit proxy authentication configuration from the auth proxy. + +- This function makes a request to the Turnkey auth proxy to retrieve the current WalletKit configuration, + including supported authentication methods, OAuth providers, and any custom proxy settings. +- Useful for dynamically configuring the client UI or authentication flows based on the proxy's capabilities. +- Ensures that the client is aware of the latest proxy-side configuration, which may affect available login/signup options. + +#### Returns + +`Promise`\<[`ProxyTGetWalletKitConfigResponse`](../../../_turnkey/sdk-types/ProxyTGetWalletKitConfigResponse/readme)\> + +A promise that resolves to a `ProxyTGetWalletKitConfigResponse` object containing the proxy authentication configuration. + +#### Throws + +If there is an error retrieving the proxy authentication configuration from the auth proxy. + +#### Inherited from + +`TurnkeyClientMethods.getProxyAuthConfig` + +*** + +### getSession() + +> **getSession**: (`params?`) => `Promise`\<`undefined` \| [`Session`](../../../sdk-browser/index/Session/readme)\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:921 + +Retrieves the session associated with the specified session key, or the active session by default. + +- This function retrieves the session object from storage, using the provided session key or, if not specified, the current active session key. +- If no session key is provided and there is no active session, it returns undefined. +- Returns the session details, including public key, organization ID, user ID, and expiration. + +#### Parameters + +##### params? + +###### sessionKey? + +`string` + +session key to retrieve a specific session (defaults to the current active session key). + +#### Returns + +`Promise`\<`undefined` \| [`Session`](../../../sdk-browser/index/Session/readme)\> + +A promise that resolves to a `Session` object containing the session details, or undefined if not found. + +#### Throws + +If there is an error retrieving the session from storage. + +#### Inherited from + +`TurnkeyClientMethods.getSession` + +*** + +### getWalletProviders() + +> **getWalletProviders**: (`chain?`) => `Promise`\<[`WalletProvider`](../WalletProvider/readme)[]\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:108 + +Retrieves wallet providers from the initialized wallet manager. + +- Optionally filters providers by the specified blockchain chain. +- Throws an error if the wallet manager is not initialized. + +#### Parameters + +##### chain? + +[`Chain`](../Chain/readme) + +optional blockchain chain to filter the returned providers. + +#### Returns + +`Promise`\<[`WalletProvider`](../WalletProvider/readme)[]\> + +A promise that resolves to an array of wallet providers. + +#### Throws + +If the wallet manager is uninitialized or provider retrieval fails. + +#### Inherited from + +`TurnkeyClientMethods.getWalletProviders` + +*** + +### handleAddEmail() + +> **handleAddEmail**: (`params?`) => `Promise`\<`string`\> + +Defined in: [react-wallet-kit/src/providers/client/Types.tsx:356](https://github.com/tkhq/sdk/blob/main/packages/react-wallet-kit/src/providers/client/Types.tsx#L356) + +Handles the add user email flow. + +- This function opens a modal with the UpdateEmail component, using a modified title and flow for adding and verifying the user's email address. +- If an email is provided, it will immediately send an OTP request to the user and display the OTP verification modal. +- Supports both manual entry and pre-filled email addresses, as well as custom modal titles and subtitles. +- Uses the addEmailContinue helper to manage the OTP flow, verification, and update logic. +- After successful verification and update, the user details state is refreshed and an optional success page can be shown. +- Supports customizing the duration of the success page after update. +- Handles all error cases and throws a TurnkeyError with appropriate error codes. + +#### Parameters + +##### params? + +###### email? + +`string` + +parameter to specify the new email address. + +###### subTitle? + +`string` + +subtitle for the modal. + +###### successPageDuration? + +`number` + +duration (in ms) for the success page after update (default: 0, no success page). + +###### title? + +`string` + +title for the modal (defaults to "Connect an email" if the user does not have an email). + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to the userId of the user that was changed. + +#### Throws + +If the client is not initialized, no active session is found, or if there is an error adding the email. + +*** + +### handleUpdateUserName() + +> **handleUpdateUserName**: (`params?`) => `Promise`\<`string`\> + +Defined in: [react-wallet-kit/src/providers/client/Types.tsx:330](https://github.com/tkhq/sdk/blob/main/packages/react-wallet-kit/src/providers/client/Types.tsx#L330) + +Handles the update user email flow. + +- This function opens a modal with the UpdateEmail component for updating and verifying the user's email address. +- If an email is provided, it will immediately send an OTP request to the user and display the OTP verification modal. +- Supports both manual entry and pre-filled email addresses, as well as custom modal titles and subtitles. +- Uses the updateEmailContinue helper to manage the OTP flow, verification, and update logic. +- After successful verification and update, the user details state is refreshed and an optional success page can be shown. +- Supports customizing the duration of the success page after update. +- Handles all error cases and throws a TurnkeyError with appropriate error codes. + +#### Parameters + +##### params? + +###### stampWith? + +[`StamperType`](../StamperType/readme) + +parameter to specify the stamper to use for the update (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### subTitle? + +`string` + +subtitle for the modal. + +###### successPageDuration? + +`number` + +duration (in ms) for the success page after update (default: 0, no success page). + +###### title? + +`string` + +title for the modal. + +###### userName? + +`string` + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to the userId of the user that was changed. + +#### Throws + +If the client is not initialized, no active session is found, or if there is an error updating the email. + +*** + +### httpClient + +> **httpClient**: `undefined` \| `TurnkeySDKClientBase` + +Defined in: [react-wallet-kit/src/providers/client/Types.tsx:42](https://github.com/tkhq/sdk/blob/main/packages/react-wallet-kit/src/providers/client/Types.tsx#L42) + +*** + +### importWallet() + +> **importWallet**: (`params`) => `Promise`\<`string`\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:815 + +Imports a wallet from an encrypted bundle. + +- This function imports a wallet using the provided encrypted bundle and creates accounts based on the provided parameters. +- If a userId is provided, the wallet will be imported for that specific user; otherwise, it uses the current session's userId. +- If an accounts array is provided, those accounts will be created in the imported wallet; otherwise, default Ethereum and Solana accounts will be created. +- The encrypted bunlde MUST be encrypted to +- Automatically ensures an active session exists before making the request. +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Parameters + +##### params + +###### accounts? + +[`v1WalletAccountParams`](../../../_turnkey/sdk-types/v1WalletAccountParams/readme)[] + +array of account parameters to create in the imported wallet (defaults to standard Ethereum and Solana accounts). + +###### encryptedBundle + +`string` + +encrypted bundle containing the wallet seed phrase and metadata. + +###### stampWith? + +[`StamperType`](../StamperType/readme) + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### userId? + +`string` + +user ID to import the wallet for a specific user (defaults to the current session's userId). + +###### walletName + +`string` + +name of the wallet to create upon import. + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to the ID of the imported wallet. + +#### Throws + +If there is no active session, if the encrypted bundle is invalid, or if there is an error importing the wallet. + +#### Inherited from + +`TurnkeyClientMethods.importWallet` + +*** + +### initOtp() + +> **initOtp**: (`params`) => `Promise`\<`string`\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:221 + +Initializes the OTP process by sending an OTP code to the provided contact. + +- This function initiates the OTP flow by sending a one-time password (OTP) code to the user's contact information (email address or phone number) via the auth proxy. +- Supports both email and SMS OTP types. +- Returns an OTP ID that is required for subsequent OTP verification. + +#### Parameters + +##### params + +###### contact + +`string` + +contact information for the user (e.g., email address or phone number). + +###### otpType + +[`OtpType`](../OtpType/readme) + +type of OTP to initialize (OtpType.Email or OtpType.Sms). + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to the OTP ID required for verification. + +#### Throws + +If there is an error during the OTP initialization process or if the maximum number of OTPs has been reached. + +#### Inherited from + +`TurnkeyClientMethods.initOtp` + +*** + +### loginOrSignupWithWallet() + +> **loginOrSignupWithWallet**: (`params`) => `Promise`\<`string`\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:203 + +Logs in an existing user or signs up a new user using a wallet, creating a new sub-organization if needed. + +- This function attempts to log in the user by stamping a login request with the provided wallet. +- If the wallet’s public key is not associated with an existing sub-organization, a new one is created. +- Handles both wallet authentication and sub-organization creation in a single flow. +- For Ethereum wallets, derives the public key from the signed request header; for Solana wallets, retrieves it directly from the wallet. +- Optionally accepts additional sub-organization parameters, a custom session key, and a custom session expiration. +- Stores the resulting session token under the specified session key, or the default session key if not provided. + +#### Parameters + +##### params + +###### createSubOrgParams? + +[`CreateSubOrgParams`](../CreateSubOrgParams/readme) + +optional parameters for creating a sub-organization (e.g., authenticators, user metadata). + +###### expirationSeconds? + +`string` + +session expiration time in seconds (defaults to the configured default). + +###### sessionKey? + +`string` + +session key to use for storing the session (defaults to the default session key). + +###### walletProvider + +[`WalletProvider`](../WalletProvider/readme) + +wallet provider to use for authentication. + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to a signed JWT session token for the sub-organization (new or existing). + +#### Throws + +If there is an error during wallet authentication, sub-organization creation, or session storage. + +#### Inherited from + +`TurnkeyClientMethods.loginOrSignupWithWallet` + +*** + +### loginWithOauth() + +> **loginWithOauth**: (`params`) => `Promise`\<`string`\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:370 + +Logs in a user using OAuth authentication. + +- This function logs in a user using the provided OIDC token and public key. +- Optionally invalidates any existing sessions for the user if `invalidateExisting` is set to true. +- Stores the resulting session token under the specified session key, or the default session key if not provided. +- Handles cleanup of unused key pairs if login fails. + +#### Parameters + +##### params + +###### invalidateExisting? + +`boolean` + +flag to invalidate existing sessions for the user. + +###### oidcToken + +`string` + +OIDC token received after successful authentication with the OAuth provider. + +###### publicKey + +`string` + +public key to use for authentication. Must be generated prior to calling this function. + +###### sessionKey? + +`string` + +session key to use for session creation (defaults to the default session key). + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to a signed JWT session token. + +#### Throws + +If there is an error during the OAuth login process or if key pair cleanup fails. + +#### Inherited from + +`TurnkeyClientMethods.loginWithOauth` + +*** + +### loginWithOtp() + +> **loginWithOtp**: (`params`) => `Promise`\<`string`\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:267 + +Logs in a user using an OTP verification token. + +- This function logs in a user using the verification token received after OTP verification (from email or SMS). +- If a public key is not provided, a new API key pair will be generated for authentication. +- Optionally invalidates any existing sessions for the user if `invalidateExisting` is set to true. +- Stores the resulting session token under the specified session key, or the default session key if not provided. +- Handles cleanup of unused key pairs if login fails. + +#### Parameters + +##### params + +###### invalidateExisting? + +`boolean` + +flag to invalidate existing session for the user. + +###### publicKey? + +`string` + +public key to use for authentication. If not provided, a new key pair will be generated. + +###### sessionKey? + +`string` + +session key to use for session creation (defaults to the default session key). + +###### verificationToken + +`string` + +verification token received after OTP verification. + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to a signed JWT session token. + +#### Throws + +If there is an error during the OTP login process or if key pair cleanup fails. + +#### Inherited from + +`TurnkeyClientMethods.loginWithOtp` + +*** + +### loginWithPasskey() + +> **loginWithPasskey**: (`params?`) => `Promise`\<`string`\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:71 + +Logs in a user using a passkey, optionally specifying the public key, session key, and session expiration. + +- This function initiates the login process with a passkey and handles session creation and storage. +- If a public key is not provided, a new key pair will be generated for authentication. +- If a session key is not provided, the default session key will be used. +- The session expiration can be customized via the expirationSeconds parameter. +- Handles cleanup of unused key pairs if login fails. + +#### Parameters + +##### params? + +###### expirationSeconds? + +`string` + +session expiration time in seconds (defaults to the configured default). + +###### publicKey? + +`string` + +public key to use for authentication. If not provided, a new key pair will be generated. + +###### sessionKey? + +`string` + +session key to use for session creation (defaults to the default session key). + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to a signed JWT session token. + +#### Throws + +If there is an error during the passkey login process or if the user cancels the passkey prompt. + +#### Inherited from + +`TurnkeyClientMethods.loginWithPasskey` + +*** + +### loginWithWallet() + +> **loginWithWallet**: (`params`) => `Promise`\<`string`\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:158 + +Logs in a user using the specified wallet provider. + +- This function logs in a user by authenticating with the provided wallet provider via a wallet-based signature. +- If a public key is not provided, a new one will be generated for authentication. +- Optionally accepts a custom session key and session expiration time. +- Stores the resulting session token under the specified session key, or the default session key if not provided. +- Throws an error if a public key cannot be found or generated, or if the login process fails. + +#### Parameters + +##### params + +###### expirationSeconds? + +`string` + +optional session expiration time in seconds (defaults to the configured default). + +###### publicKey? + +`string` + +optional public key to associate with the session (generated if not provided). + +###### sessionKey? + +`string` + +optional key to store the session under (defaults to the default session key). + +###### walletProvider + +[`WalletProvider`](../WalletProvider/readme) + +wallet provider to use for authentication. + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to the created session token. + +#### Throws + +If the wallet stamper is uninitialized, a public key cannot be found or generated, or login fails. + +#### Inherited from + +`TurnkeyClientMethods.loginWithWallet` + +*** + +### logout() + +> **logout**: (`params?`) => `Promise`\<`void`\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:53 + +Logs out the current client session. + +- This function clears the specified session and removes any associated key pairs from storage. +- If a sessionKey is provided, it logs out from that session; otherwise, it logs out from the active session. +- Cleans up any api keys associated with the session. + +#### Parameters + +##### params? + +###### sessionKey? + +`string` + +session key to specify which session to log out from (defaults to the active session). + +#### Returns + +`Promise`\<`void`\> + +A promise that resolves when the logout process is complete. + +#### Throws + +If there is no active session or if there is an error during the logout process. + +#### Inherited from + +`TurnkeyClientMethods.logout` + +*** + +### refreshSession() + +> **refreshSession**: (`params?`) => `Promise`\<`undefined` \| [`TStampLoginResponse`](../../../_turnkey/sdk-types/TStampLoginResponse/readme)\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:903 + +Refreshes the session associated with the specified session key, or the active session by default. + +- This function refreshes the session and updates the session token and key pair associated with the given session key. +- If a sessionKey is provided, it will refresh the session under that key; otherwise, it will use the current active session key. +- Optionally allows specifying a new expiration time for the session, a custom public key, and whether to invalidate the existing session after refreshing. +- Makes a request to the Turnkey API to stamp a new login and stores the refreshed session token. +- Automatically manages key pair cleanup and session storage to ensure consistency. +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Parameters + +##### params? + +###### expirationSeconds? + +`string` + +expiration time in seconds for the refreshed session (defaults to the configured default). + +###### invalidateExisitng? + +`boolean` + +flag to invalidate the existing session before refreshing (defaults to false). + +###### publicKey? + +`string` + +public key to use for the refreshed session (if not provided, a new key pair will be generated). + +###### sessionKey? + +`string` + +session key to refresh the session under (defaults to the active session key). + +###### stampWith? + +[`StamperType`](../StamperType/readme) + +parameter to stamp the request with a specific stamper. + +#### Returns + +`Promise`\<`undefined` \| [`TStampLoginResponse`](../../../_turnkey/sdk-types/TStampLoginResponse/readme)\> + +A promise that resolves to a `TStampLoginResponse` object containing the refreshed session details. + +#### Throws + +If the session key does not exist, if there is no active session, or if there is an error refreshing the session. + +#### Inherited from + +`TurnkeyClientMethods.refreshSession` + +*** + +### removeOauthProviders() + +> **removeOauthProviders**: (`params`) => `Promise`\<`string`[]\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:678 + +Removes a list of OAuth providers from the user. + +- This function removes OAuth providers (e.g., Google, Apple) from the user's account. +- If a userId is provided, it removes the providers for that specific user; otherwise, it uses the current session's userId. +- Automatically ensures an active session exists before making the request. +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). +- Returns an array of remaining provider IDs associated with the user after removal. + +#### Parameters + +##### params + +###### providerIds + +`string`[] + +IDs of the OAuth providers to remove. + +###### stampWith? + +[`StamperType`](../StamperType/readme) + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### userId? + +`string` + +user ID to remove the provider for a specific user (defaults to the current session's userId). + +#### Returns + +`Promise`\<`string`[]\> + +A promise that resolves to an array of provider IDs that were removed. + +#### Throws + +If there is no active session, if the userId is missing, or if there is an error removing the OAuth provider. + +#### Inherited from + +`TurnkeyClientMethods.removeOauthProviders` + +*** + +### removePasskeys() + +> **removePasskeys**: (`params`) => `Promise`\<`string`[]\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:720 + +Removes passkeys (authenticator) from the user. + +- This function removes passkeys (WebAuthn/FIDO2 authenticators) from the user's account. +- If a userId is provided, it removes the passkeys for that specific user; otherwise, it uses the current session's userId. +- Automatically ensures an active session exists before making the request. +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). +- Returns an array of remaining authenticator IDs for the user after removal. + +#### Parameters + +##### params + +###### authenticatorIds + +`string`[] + +IDs of the authenticators (passkeys) to remove. + +###### stampWith? + +[`StamperType`](../StamperType/readme) + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### userId? + +`string` + +user ID to remove the passkeys for a specific user (defaults to the current session's userId). + +#### Returns + +`Promise`\<`string`[]\> + +A promise that resolves to an array of authenticator IDs that were removed. + +#### Throws + +If there is no active session, if the userId is missing, or if there is an error removing the passkeys. + +#### Inherited from + +`TurnkeyClientMethods.removePasskeys` + +*** + +### removeUserEmail() + +> **removeUserEmail**: (`params?`) => `Promise`\<`string`\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:577 + +Removes the user's email address. + +- This function removes the user's email address by setting it to an empty string. +- If a userId is provided, it removes the email for that specific user; otherwise, it uses the current session's userId. +- Automatically ensures an active session exists before making the request. +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Parameters + +##### params? + +###### stampWith? + +[`StamperType`](../StamperType/readme) + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### userId? + +`string` + +user ID to remove a specific user's email address (defaults to the current session's userId). + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to the userId of the user whose email was removed. + +#### Throws + +If there is no active session, if the userId is missing, or if there is an error removing the user email. + +#### Inherited from + +`TurnkeyClientMethods.removeUserEmail` + +*** + +### removeUserPhoneNumber() + +> **removeUserPhoneNumber**: (`params?`) => `Promise`\<`string`\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:616 + +Removes the user's phone number. + +- This function removes the user's phone number by setting it to an empty string. +- If a userId is provided, it removes the phone number for that specific user; otherwise, it uses the current session's userId. +- Automatically ensures an active session exists before making the request. +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Parameters + +##### params? + +###### stampWith? + +[`StamperType`](../StamperType/readme) + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### userId? + +`string` + +user ID to remove a specific user's phone number (defaults to the current session's userId). + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to the userId of the user whose phone number was removed. + +#### Throws + +If there is no active session, if the userId is missing, or if there is an error removing the user phone number. + +#### Inherited from + +`TurnkeyClientMethods.removeUserPhoneNumber` + +*** + +### session + +> **session**: `undefined` \| [`Session`](../../../sdk-browser/index/Session/readme) + +Defined in: [react-wallet-kit/src/providers/client/Types.tsx:43](https://github.com/tkhq/sdk/blob/main/packages/react-wallet-kit/src/providers/client/Types.tsx#L43) + +*** + +### setActiveSession() + +> **setActiveSession**: (`params`) => `Promise`\<`void`\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:948 + +Sets the active session to the specified session key. + +- This function updates the `activeSessionKey` in persistent storage to the specified session key. +- Ensures that subsequent operations use the session associated with this key as the active session. +- Does not validate whether the session key exists or is valid; it simply updates the pointer. +- Useful for switching between multiple stored sessions or restoring a previous session context. + +#### Parameters + +##### params + +###### sessionKey + +`string` + +session key to set as the active session. + +#### Returns + +`Promise`\<`void`\> + +A promise that resolves when the active session key is successfully set. + +#### Throws + +If the client is not initialized or if there is an error setting the active session key. + +#### Inherited from + +`TurnkeyClientMethods.setActiveSession` + +*** + +### signAndSendTransaction() + +> **signAndSendTransaction**: (`params`) => `Promise`\<`string`\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:515 + +Signs and broadcasts a transaction using the specified wallet account. + +- For **connected wallets**: + - Calls the wallet’s native `signAndSendTransaction` method. + - Does **not** require an `rpcUrl`. + +- For **embedded wallets**: + - Signs the transaction using the Turnkey API. + - Requires an `rpcUrl` to broadcast the transaction. + - Broadcasts the transaction using a JSON-RPC client. + +#### Parameters + +##### params + +###### rpcUrl? + +`string` + +required for embedded wallets to broadcast the signed transaction. + +###### stampWith? + +[`StamperType`](../StamperType/readme) + +optional stamper to tag the signing request. + +###### transactionType + +[`v1TransactionType`](../../../_turnkey/sdk-types/v1TransactionType/readme) + +transaction type (e.g., "TRANSACTION_TYPE_SOLANA"). + +###### unsignedTransaction + +`string` + +unsigned transaction (serialized string). + +###### walletAccount + +[`WalletAccount`](../WalletAccount/readme) + +wallet account to use for signing and sending. + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to a transaction signature or hash. + +#### Throws + +If signing or broadcasting fails. + +#### Inherited from + +`TurnkeyClientMethods.signAndSendTransaction` + +*** + +### signMessage() + +> **signMessage**: (`params`) => `Promise`\<[`v1SignRawPayloadResult`](../../../_turnkey/sdk-types/v1SignRawPayloadResult/readme)\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:465 + +Signs a message using the specified wallet account. + +- Supports both embedded and connected wallets. +- For **connected wallets**: + - Delegates signing to the wallet provider’s native signing method. + - **Important:** For Ethereum wallets (e.g., MetaMask), signatures follow [EIP-191](https://eips.ethereum.org/EIPS/eip-191). + The message is automatically prefixed with `"\x19Ethereum Signed Message:\n" + message length` + before signing. As a result, this signature **cannot be used as a raw transaction signature** + or broadcast on-chain. +- For **embedded wallets**, uses the Turnkey API to sign the message directly. +- Automatically handles message encoding and hashing based on the wallet account’s address format, + unless explicitly overridden. + +#### Parameters + +##### params + +###### addEthereumPrefix? + +`boolean` + +whether to prefix the message with Ethereum's `"\x19Ethereum Signed Message:\n"` string. + - If `true` (default for Ethereum), the message is prefixed before signing. + - If `false`: + - Connected wallets will throw an error because they always prefix automatically. + - Embedded wallets will sign the raw message without any prefix. + +###### encoding? + +[`v1PayloadEncoding`](../../../_turnkey/sdk-types/v1PayloadEncoding/readme) + +override for the payload encoding (defaults to the encoding appropriate for the address type). + +###### hashFunction? + +[`v1HashFunction`](../../../_turnkey/sdk-types/v1HashFunction/readme) + +override for the hash function (defaults to the hash function appropriate for the address type). + +###### message + +`string` + +message to sign. + +###### stampWith? + +[`StamperType`](../StamperType/readme) + +stamper to tag the signing request (e.g., Passkey, ApiKey, or Wallet). + +###### walletAccount + +[`WalletAccount`](../WalletAccount/readme) + +wallet account to use for signing. + +#### Returns + +`Promise`\<[`v1SignRawPayloadResult`](../../../_turnkey/sdk-types/v1SignRawPayloadResult/readme)\> + +A promise resolving to a `v1SignRawPayloadResult` containing the signature and metadata. + +#### Throws + +If signing fails, if the wallet account does not support signing, or if the response is invalid. + +#### Inherited from + +`TurnkeyClientMethods.signMessage` + +*** + +### signTransaction() + +> **signTransaction**: (`params`) => `Promise`\<`string`\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:489 + +Signs a transaction using the specified wallet account. + +- This function signs a blockchain transaction using the provided wallet address and transaction data. +- Supports all Turnkey-supported blockchain networks (e.g., Ethereum, Solana, Tron). +- Automatically determines the appropriate signing method based on the transaction type. +- Delegates signing to the Turnkey API, which returns the signed transaction and related metadata. +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Parameters + +##### params + +###### stampWith? + +[`StamperType`](../StamperType/readme) + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### transactionType + +[`v1TransactionType`](../../../_turnkey/sdk-types/v1TransactionType/readme) + +type of transaction (e.g., "TRANSACTION_TYPE_ETHEREUM", "TRANSACTION_TYPE_SOLANA", "TRANSACTION_TYPE_TRON"). + +###### unsignedTransaction + +`string` + +unsigned transaction data (serialized as a string) to be signed. + +###### walletAccount + +[`WalletAccount`](../WalletAccount/readme) + +wallet account to use for signing the transaction. + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to a `TSignTransactionResponse` object containing the signed transaction and any additional signing metadata. + +#### Throws + +If there is an error signing the transaction or if the response is invalid. + +#### Inherited from + +`TurnkeyClientMethods.signTransaction` + +*** + +### signUpWithOauth() + +> **signUpWithOauth**: (`params`) => `Promise`\<`string`\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:392 + +Signs up a user using OAuth authentication. + +- This function creates a new sub-organization for the user using the provided OIDC token, public key, and provider name. +- Handles the full OAuth sign-up flow, including sub-organization creation and session management. +- Optionally accepts additional sub-organization creation parameters and a custom session key. +- After successful sign-up, automatically logs in the user and returns a signed JWT session token. + +#### Parameters + +##### params + +###### createSubOrgParams? + +[`CreateSubOrgParams`](../CreateSubOrgParams/readme) + +parameters for sub-organization creation (e.g., authenticators, user metadata). + +###### oidcToken + +`string` + +OIDC token received after successful authentication with the OAuth provider. + +###### providerName + +`string` + +name of the OAuth provider (e.g., "Google", "Apple"). + +###### publicKey + +`string` + +public key to associate with the new sub-organization. + +###### sessionKey? + +`string` + +session key to use for session creation (defaults to the default session key). + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to a signed JWT session token for the new sub-organization. + +#### Throws + +If there is an error during the OAuth sign-up or login process. + +#### Inherited from + +`TurnkeyClientMethods.signUpWithOauth` + +*** + +### signUpWithOtp() + +> **signUpWithOtp**: (`params`) => `Promise`\<`string`\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:291 + +Signs up a user using an OTP verification token. + +- This function signs up a user using the verification token received after OTP verification (from email or SMS). +- Creates a new sub-organization for the user with the provided parameters and associates the contact (email or phone) with the sub-organization. +- Automatically generates a new API key pair for authentication and session management. +- Stores the resulting session token under the specified session key, or the default session key if not provided. +- Handles both email and SMS OTP types, and supports additional sub-organization creation parameters. + +#### Parameters + +##### params + +###### contact + +`string` + +contact information for the user (e.g., email address or phone number). + +###### createSubOrgParams? + +[`CreateSubOrgParams`](../CreateSubOrgParams/readme) + +parameters for creating a sub-organization (e.g., authenticators, user metadata). + +###### invalidateExisting? + +`boolean` + +flag to invalidate existing session for the user. + +###### otpType + +[`OtpType`](../OtpType/readme) + +type of OTP being used (OtpType.Email or OtpType.Sms). + +###### sessionKey? + +`string` + +session key to use for session creation (defaults to the default session key). + +###### verificationToken + +`string` + +verification token received after OTP verification. + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to a signed JWT session token for the new sub-organization. + +#### Throws + +If there is an error during the OTP sign-up process or session storage. + +#### Inherited from + +`TurnkeyClientMethods.signUpWithOtp` + +*** + +### signUpWithPasskey() + +> **signUpWithPasskey**: (`params?`) => `Promise`\<`string`\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:92 + +Signs up a user using a passkey, creating a new sub-organization and session. + +- This function creates a new passkey authenticator and uses it to register a new sub-organization for the user. +- Handles both passkey creation and sub-organization creation in a single flow. +- Optionally accepts additional sub-organization parameters, a custom session key, a custom passkey display name, and a custom session expiration. +- Automatically generates a new API key pair for authentication and session management. +- Stores the resulting session token and manages cleanup of unused key pairs. + +#### Parameters + +##### params? + +###### createSubOrgParams? + +[`CreateSubOrgParams`](../CreateSubOrgParams/readme) + +parameters for creating a sub-organization (e.g., authenticators, user metadata). + +###### expirationSeconds? + +`string` + +session expiration time in seconds (defaults to the configured default). + +###### passkeyDisplayName? + +`string` + +display name for the passkey (defaults to a generated name based on the current timestamp). + +###### sessionKey? + +`string` + +session key to use for storing the session (defaults to the default session key). + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to a signed JWT session token for the new sub-organization. + +#### Throws + +If there is an error during passkey creation, sub-organization creation, or session storage. + +#### Inherited from + +`TurnkeyClientMethods.signUpWithPasskey` + +*** + +### signUpWithWallet() + +> **signUpWithWallet**: (`params`) => `Promise`\<`string`\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:180 + +Signs up a user using a wallet, creating a new sub-organization and session. + +- This function creates a new wallet authenticator and uses it to register a new sub-organization for the user. +- Handles both wallet authentication and sub-organization creation in a single flow. +- Optionally accepts additional sub-organization parameters, a custom session key, and a custom session expiration. +- Automatically generates additional API key pairs for authentication and session management. +- Stores the resulting session token under the specified session key, or the default session key if not provided, and manages cleanup of unused key pairs. + +#### Parameters + +##### params + +###### createSubOrgParams? + +[`CreateSubOrgParams`](../CreateSubOrgParams/readme) + +parameters for creating a sub-organization (e.g., authenticators, user metadata). + +###### expirationSeconds? + +`string` + +session expiration time in seconds (defaults to the configured default). + +###### sessionKey? + +`string` + +session key to use for storing the session (defaults to the default session key). + +###### walletProvider + +[`WalletProvider`](../WalletProvider/readme) + +wallet provider to use for authentication. + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to a signed JWT session token for the new sub-organization. + +#### Throws + +If there is an error during wallet authentication, sub-organization creation, session storage, or cleanup. + +#### Inherited from + +`TurnkeyClientMethods.signUpWithWallet` + +*** + +### storeSession() + +> **storeSession**: (`params`) => `Promise`\<`void`\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:854 + +Stores a session token and updates the session associated with the specified session key, or by default the active session. + +- This function parses and stores a signed JWT session token in local storage, associating it with the given session key. +- If a sessionKey is provided, the session will be stored under that key; otherwise, it will use the default session key. +- If a session already exists for the session key, its associated key pair will be deleted before storing the new session. +- After storing the session, any unused key pairs are automatically cleared from storage. +- Ensures that session management is consistent and prevents orphaned key pairs. + +#### Parameters + +##### params + +###### sessionKey? + +`string` + +session key to store the session under (defaults to the default session key). + +###### sessionToken + +`string` + +JWT session token to store. + +#### Returns + +`Promise`\<`void`\> + +A promise that resolves when the session is successfully stored. + +#### Throws + +If there is an error storing the session or cleaning up key pairs. + +#### Inherited from + +`TurnkeyClientMethods.storeSession` + +*** + +### switchWalletProviderChain() + +> **switchWalletProviderChain**: (`walletProvider`, `chainOrId`) => `Promise`\<`void`\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:141 + +Switches the specified wallet provider to a different blockchain chain. + +- Requires the wallet manager and its connector to be initialized. +- The wallet provider must have at least one connected address. +- Does nothing if the wallet provider is already on the desired chain. + +#### Parameters + +##### walletProvider + +[`WalletProvider`](../WalletProvider/readme) + +wallet provider to switch. + +##### chainOrId + +target chain as a chain ID string or SwitchableChain object. + +`string` | [`SwitchableChain`](../SwitchableChain/readme) + +#### Returns + +`Promise`\<`void`\> + +A promise that resolves once the chain switch is complete. + +#### Throws + +If the wallet manager is uninitialized, the provider is not connected, or the switch fails. + +#### Inherited from + +`TurnkeyClientMethods.switchWalletProviderChain` + +*** + +### updateUserEmail() + +> **updateUserEmail**: (`params`) => `Promise`\<`string`\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:558 + +Updates the user's email address. + +- This function updates the user's email address and, if provided, verifies it using a verification token (typically from an OTP flow). +- If a userId is provided, it updates the email for that specific user; otherwise, it uses the current session's userId. +- If a verificationToken is not provided, the email will be updated but will not be marked as verified. +- Automatically ensures an active session exists before making the request. +- Handles session management and error reporting for both update and verification flows. + +#### Parameters + +##### params + +###### email + +`string` + +new email address to set for the user. + +###### stampWith? + +[`StamperType`](../StamperType/readme) + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### userId? + +`string` + +user ID to update a specific user's email (defaults to the current session's userId). + +###### verificationToken? + +`string` + +verification token from OTP email verification (required if verifying the email). + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to the userId of the updated user. + +#### Throws + +If there is no active session, if the userId is missing, or if there is an error updating or verifying the user email. + +#### Inherited from + +`TurnkeyClientMethods.updateUserEmail` + +*** + +### updateUserName() + +> **updateUserName**: (`params`) => `Promise`\<`string`\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:635 + +Updates the user's name. + +- This function updates the user's display name. +- If a userId is provided, it updates the name for that specific user; otherwise, it uses the current session's userId. +- Automatically ensures an active session exists before making the request. +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). +- Handles session management and error reporting for the update flow. + +#### Parameters + +##### params + +###### stampWith? + +[`StamperType`](../StamperType/readme) + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### userId? + +`string` + +user ID to update a specific user's name (defaults to the current session's userId). + +###### userName + +`string` + +new name to set for the user. + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to the userId of the updated user. + +#### Throws + +If there is no active session, if the userId is missing, or if there is an error updating the user name. + +#### Inherited from + +`TurnkeyClientMethods.updateUserName` + +*** + +### updateUserPhoneNumber() + +> **updateUserPhoneNumber**: (`params`) => `Promise`\<`string`\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:597 + +Updates the user's phone number. + +- This function updates the user's phone number and, if provided, verifies it using a verification token (from an OTP flow). +- If a userId is provided, it updates the phone number for that specific user; otherwise, it uses the current session's userId. +- If a verificationToken is not provided, the phone number will be updated but will not be marked as verified. +- Automatically ensures an active session exists before making the request. +- Handles session management and error reporting for both update and verification flows. + +#### Parameters + +##### params + +###### phoneNumber + +`string` + +new phone number to set for the user. + +###### stampWith? + +[`StamperType`](../StamperType/readme) + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### userId? + +`string` + +user ID to update a specific user's phone number (defaults to the current session's userId). + +###### verificationToken? + +`string` + +verification token from OTP phone verification (required if verifying the phone number). + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to the userId of the updated user. + +#### Throws + +If there is no active session, if the userId is missing, or if there is an error updating or verifying the user phone number. + +#### Inherited from + +`TurnkeyClientMethods.updateUserPhoneNumber` + +*** + +### user + +> **user**: `undefined` \| [`v1User`](../../../_turnkey/sdk-types/v1User/readme) + +Defined in: [react-wallet-kit/src/providers/client/Types.tsx:48](https://github.com/tkhq/sdk/blob/main/packages/react-wallet-kit/src/providers/client/Types.tsx#L48) + +*** + +### verifyOtp() + +> **verifyOtp**: (`params`) => `Promise`\<\{ `subOrganizationId`: `string`; `verificationToken`: `string`; \}\> + +Defined in: core/dist/\_\_clients\_\_/core.d.ts:242 + +Verifies the OTP code sent to the user. + +- This function verifies the OTP code entered by the user against the OTP sent to their contact information (email or phone) using the auth proxy. +- If verification is successful, it returns the sub-organization ID associated with the contact (if it exists) and a verification token. +- The verification token can be used for subsequent login or sign-up flows. +- Handles both email and SMS OTP types. + +#### Parameters + +##### params + +###### contact + +`string` + +contact information for the user (e.g., email address or phone number). + +###### otpCode + +`string` + +OTP code entered by the user. + +###### otpId + +`string` + +ID of the OTP to verify (returned from `initOtp`). + +###### otpType + +[`OtpType`](../OtpType/readme) + +type of OTP being verified (OtpType.Email or OtpType.Sms). + +#### Returns + +`Promise`\<\{ `subOrganizationId`: `string`; `verificationToken`: `string`; \}\> + +A promise that resolves to an object containing: + - subOrganizationId: sub-organization ID if the contact is already associated with a sub-organization, or an empty string if not. + - verificationToken: verification token to be used for login or sign-up. + +#### Throws + +If there is an error during the OTP verification process, such as an invalid code or network failure. + +#### Inherited from + +`TurnkeyClientMethods.verifyOtp` + +*** + +### wallets + +> **wallets**: [`Wallet`](../Wallet/readme)[] + +Defined in: [react-wallet-kit/src/providers/client/Types.tsx:49](https://github.com/tkhq/sdk/blob/main/packages/react-wallet-kit/src/providers/client/Types.tsx#L49) + +## Methods + +### handleAddOauthProvider() + +> **handleAddOauthProvider**(`params`): `Promise`\<`void`\> + +Defined in: [react-wallet-kit/src/providers/client/Types.tsx:408](https://github.com/tkhq/sdk/blob/main/packages/react-wallet-kit/src/providers/client/Types.tsx#L408) + +Handles the addition of an OAuth provider for the user. + +- This function opens a modal-driven flow for linking a new OAuth provider (Google, Apple, or Facebook) to the user's account. +- It supports all enabled OAuth providers as defined in the configuration and dynamically triggers the appropriate OAuth flow. +- Uses the handleGoogleOauth, handleAppleOauth, and handleFacebookOauth functions to initiate the provider-specific OAuth authentication process. +- After successful authentication, the provider is linked to the user's account and a success page is shown. +- Automatically refreshes the user details state after linking to ensure the latest provider list is available in the provider. +- Optionally allows specifying the stamper to use for the addition (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet) for granular authentication control. +- Handles all error cases and throws a TurnkeyError with appropriate error codes. + +#### Parameters + +##### params + +###### providerName + +[`OAuthProviders`](../../../_turnkey/sdk-types/OAuthProviders/readme) + +The name of the OAuth provider to add (OAuthProviders.GOOGLE, OAuthProviders.APPLE, OAuthProviders.FACEBOOK). + +###### stampWith? + +[`StamperType`](../StamperType/readme) + +parameter to specify the stamper to use for the addition (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Returns + +`Promise`\<`void`\> + +A void promise. + +#### Throws + +If the client is not initialized, no active session is found, or if there is an error adding the provider. + +*** + +### handleAddPasskey() + +> **handleAddPasskey**(`params?`): `Promise`\<`string`[]\> + +Defined in: [react-wallet-kit/src/providers/client/Types.tsx:461](https://github.com/tkhq/sdk/blob/main/packages/react-wallet-kit/src/providers/client/Types.tsx#L461) + +Handles the addition of a passkey (authenticator) for the user. + +- This function opens a modal-driven flow for adding a new passkey authenticator (WebAuthn/FIDO2) to the user's account. +- If a `name` or `displayName` is provided, those will be used for the passkey metadata; otherwise, defaults are generated based on the website and timestamp. +- The passkey is created and linked to the specified user (by `userId`) or the current session's user if not provided. +- After successful addition, a success page is shown for the specified duration (or skipped if `successPageDuration` is 0). +- Supports stamping the request with a specific stamper (`StamperType.Passkey`, `StamperType.ApiKey`, or `StamperType.Wallet`) for granular authentication control. +- Automatically refreshes the user details state after successful addition to ensure the latest authenticators list is available in the provider. +- Handles all error cases and throws a `TurnkeyError` with appropriate error codes. + +#### Parameters + +##### params? + +###### displayName? + +`string` + +display name for the passkey (shown to the user in the UI). + +###### name? + +`string` + +internal name for the passkey (for backend or developer reference). + +###### stampWith? + +[`StamperType`](../StamperType/readme) + +parameter to stamp the request with a specific stamper (`StamperType.Passkey`, `StamperType.ApiKey`, or `StamperType.Wallet`). + +###### successPageDuration? + +`number` + +duration (in ms) for the success page after addition (default: 0, no success page). + +###### userId? + +`string` + +user ID to add the passkey for a specific user (defaults to current session's userId). + +#### Returns + +`Promise`\<`string`[]\> + +A promise that resolves to the user's updated passkeys. + +#### Throws + +If the client is not initialized, no active session is found, or if there is an error adding the passkey. + +*** + +### handleAddPhoneNumber() + +> **handleAddPhoneNumber**(`params?`): `Promise`\<`string`\> + +Defined in: [react-wallet-kit/src/providers/client/Types.tsx:383](https://github.com/tkhq/sdk/blob/main/packages/react-wallet-kit/src/providers/client/Types.tsx#L383) + +Handles the add phone number flow. + +- This function opens a modal with the UpdatePhoneNumber component for adding and verifying the user's phone number. +- If a phone number is provided, it will immediately send an OTP request to the user and display the OTP verification modal. +- Supports both manual entry and pre-filled phone numbers, as well as custom modal titles and subtitles. +- Uses the addPhoneNumberContinue helper to manage the OTP flow, verification, and update logic. +- After successful verification and update, the user details state is refreshed and an optional success page can be shown. +- Supports customizing the duration of the success page after update. +- Handles all error cases and throws a TurnkeyError with appropriate error codes. + +#### Parameters + +##### params? + +###### formattedPhone? + +`string` + +parameter to specify the formatted phone number. + +###### phoneNumber? + +`string` + +parameter to specify the new phone number. + +###### subTitle? + +`string` + +subtitle for the modal. + +###### successPageDuration? + +`number` + +duration (in ms) for the success page after update (default: 0, no success page). + +###### title? + +`string` + +title for the modal. + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to the userId of the user that was changed. + +#### Throws + +If the client is not initialized, no active session is found, or if there is an error adding the phone number. + +*** + +### handleAppleOauth() + +> **handleAppleOauth**(`params?`): `Promise`\<`void`\> + +Defined in: [react-wallet-kit/src/providers/client/Types.tsx:160](https://github.com/tkhq/sdk/blob/main/packages/react-wallet-kit/src/providers/client/Types.tsx#L160) + +Handles the Apple OAuth flow. + +- This function initiates the Apple OAuth flow by either redirecting the user to the Apple authorization page or opening it in a popup window. +- The flow type is determined by the `openInPage` parameter: if true, the current page is redirected; if false (default), a popup window is used. +- Generates a new ephemeral API key pair and uses its public key as the nonce for the OAuth request, ensuring cryptographic binding of the session. +- Constructs the Apple OAuth URL with all required parameters, including client ID, redirect URI, response type, response mode, nonce, and state. +- The `state` parameter includes the provider, flow type, public key, and any additional state parameters for tracking or custom logic. +- If `openInPage` is true, the function redirects and returns a promise that resolves on redirect or times out after 5 minutes. +- If `openInPage` is false, a popup window is opened and the function returns a promise that resolves when the flow completes, or rejects if the window is closed or times out. +- On successful authentication, the function either calls the provided `onOauthSuccess` callback, triggers the `onOauthRedirect` callback from provider callbacks, or completes the OAuth flow internally by calling `completeOauth`. +- Handles all error cases, including missing configuration, popup failures, and timeouts, and throws a `TurnkeyError` with appropriate error codes. + +#### Parameters + +##### params? + +###### additionalState? + +`Record`\<`string`, `string`\> + +Additional key-value pairs to include in the OAuth state parameter for custom tracking or logic. + +###### clientId? + +`string` + +The Apple Client ID to use (defaults to the client ID from configuration). + +###### onOauthSuccess? + +(`params`) => `any` + +Callback function to handle the successful OAuth response (receives `{ oidcToken, providerName }`). + +onOauthSuccess params: +- oidcToken: The OIDC token received from the OAuth flow. +- providerName: The name of the OAuth provider ("apple"). + +###### openInPage? + +`boolean` + +Whether to open the OAuth flow in the current page (redirect) or a popup window (default: false). + +#### Returns + +`Promise`\<`void`\> + +A promise that resolves when the OAuth flow is successfully initiated and completed, or rejects on error or timeout. + +#### Throws + +If the configuration is not ready, required parameters are missing, or if there is an error initiating or completing the OAuth flow. + +*** + +### handleExport() + +> **handleExport**(`params`): `Promise`\<`void`\> + +Defined in: [react-wallet-kit/src/providers/client/Types.tsx:226](https://github.com/tkhq/sdk/blob/main/packages/react-wallet-kit/src/providers/client/Types.tsx#L226) + +Handles the export flow. + +- This function opens a modal with the ExportComponent for exporting a wallet or private key. +- Uses Turnkey's export iframe flow to securely export wallet or private key material. +- The export process encrypts the exported bundle to a target public key, which is generated and managed inside the iframe for maximum security. +- A request is made to the Turnkey API to export the wallet or private key, encrypted to the target public key. +- The resulting export bundle is injected into the iframe, where it is decrypted and displayed to the user. +- Supports both full wallet exports (ExportType.Wallet) and single private key exports (ExportType.PrivateKey). +- If a custom iframe URL is used, a target public key can be provided explicitly. +- Optionally allows specifying the stamper to use for the export (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet) for granular authentication control. +- The modal-driven UI ensures the user is guided through the export process and can securely retrieve their exported material. + +#### Parameters + +##### params + +###### exportType + +`ExportType` + +The type of export to perform (ExportType.Wallet or ExportType.PrivateKey). + +###### stampWith? + +[`StamperType`](../StamperType/readme) + +The stamper to use for the export (Passkey, ApiKey, or Wallet). + +###### targetPublicKey? + +`string` + +The target public key to encrypt the export bundle to (required for custom iframe flows). + +###### walletId + +`string` + +The ID of the wallet to export. + +#### Returns + +`Promise`\<`void`\> + +A void promise. + +*** + +### handleFacebookOauth() + +> **handleFacebookOauth**(`params?`): `Promise`\<`void`\> + +Defined in: [react-wallet-kit/src/providers/client/Types.tsx:196](https://github.com/tkhq/sdk/blob/main/packages/react-wallet-kit/src/providers/client/Types.tsx#L196) + +Handles the Facebook OAuth flow. + +- This function initiates the Facebook OAuth flow by either redirecting the user to the Facebook authorization page or opening it in a popup window. +- The flow type is determined by the `openInPage` parameter: if true, the current page is redirected; if false (default), a popup window is used. +- Generates a new ephemeral API key pair and uses its public key as the nonce for the OAuth request, ensuring cryptographic binding of the session. +- Uses PKCE (Proof Key for Code Exchange) for enhanced security, generating a code verifier and challenge for the Facebook OAuth flow. +- Constructs the Facebook OAuth URL with all required parameters, including client ID, redirect URI, response type, code challenge, nonce, and state. +- The `state` parameter includes the provider, flow type, public key, and any additional state parameters for tracking or custom logic. +- If `openInPage` is true, the function redirects and returns a promise that resolves on redirect or times out after 5 minutes. +- If `openInPage` is false, a popup window is opened and the function returns a promise that resolves when the flow completes, or rejects if the window is closed or times out. +- On successful authentication, the function either calls the provided `onOauthSuccess` callback, triggers the `onOauthRedirect` callback from provider callbacks, or completes the OAuth flow internally by calling `completeOauth`. +- Handles all error cases, including missing configuration, popup failures, and timeouts, and throws a `TurnkeyError` with appropriate error codes. + +#### Parameters + +##### params? + +###### additionalState? + +`Record`\<`string`, `string`\> + +Additional key-value pairs to include in the OAuth state parameter for custom tracking or logic. + +###### clientId? + +`string` + +The Facebook Client ID to use (defaults to the client ID from configuration). + +###### onOauthSuccess? + +(`params`) => `any` + +Callback function to handle the successful OAuth response (receives `{ oidcToken, providerName }`). + +onOauthSuccess params: +- oidcToken: The OIDC token received from the OAuth flow. +- providerName: The name of the OAuth provider ("facebook"). + +###### openInPage? + +`boolean` + +Whether to open the OAuth flow in the current page (redirect) or a popup window (default: false). + +#### Returns + +`Promise`\<`void`\> + +A promise that resolves when the OAuth flow is successfully initiated and completed, or rejects on error or timeout. + +#### Throws + +If the configuration is not ready, required parameters are missing, or if there is an error initiating or completing the OAuth flow. + +*** + +### handleGoogleOauth() + +> **handleGoogleOauth**(`params?`): `Promise`\<`void`\> + +Defined in: [react-wallet-kit/src/providers/client/Types.tsx:125](https://github.com/tkhq/sdk/blob/main/packages/react-wallet-kit/src/providers/client/Types.tsx#L125) + +Handles the Google OAuth flow. + +- This function initiates the Google OAuth flow by redirecting the user to the Google authorization page or opening it in a popup window. +- It supports both "popup" and "redirect" flows, determined by the `openInPage` parameter. +- Generates a new ephemeral API key pair and uses its public key as the nonce for the OAuth request, ensuring cryptographic binding of the session. +- Constructs the Google OAuth URL with all required parameters, including client ID, redirect URI, response type, scope, nonce, and state. +- The `state` parameter includes the provider, flow type, public key, and any additional state parameters for tracking or custom logic. +- If `openInPage` is true, the current page is redirected to the Google OAuth URL and the function returns a promise that resolves on redirect or times out after 5 minutes. +- If `openInPage` is false, a popup window is opened for the OAuth flow, and the function returns a promise that resolves when the flow completes or rejects if the window is closed or times out. +- On successful authentication, the function either calls the provided `onOauthSuccess` callback, triggers the `onOauthRedirect` callback from provider callbacks, or completes the OAuth flow internally by calling `completeOauth`. +- Handles all error cases, including missing configuration, popup failures, and timeouts, and throws a `TurnkeyError` with appropriate error codes. + +#### Parameters + +##### params? + +###### additionalState? + +`Record`\<`string`, `string`\> + +Additional key-value pairs to include in the OAuth state parameter for custom tracking or logic. + +###### clientId? + +`string` + +The Google Client ID to use (defaults to the client ID from configuration). + +###### onOauthSuccess? + +(`params`) => `any` + +Callback function to handle the successful OAuth response (receives `{ oidcToken, providerName }`). + +onOauthSuccess params: +- oidcToken: The OIDC token received from the OAuth flow. +- providerName: The name of the OAuth provider ("google"). + +###### openInPage? + +`boolean` + +Whether to open the OAuth flow in the current page (redirect) or a popup window (default: false). + +#### Returns + +`Promise`\<`void`\> + +A promise that resolves when the OAuth flow is successfully initiated and completed, or rejects on error or timeout. + +#### Throws + +If the configuration is not ready, required parameters are missing, or if there is an error initiating or completing the OAuth flow. + +*** + +### handleImport() + +> **handleImport**(`params?`): `Promise`\<`string`\> + +Defined in: [react-wallet-kit/src/providers/client/Types.tsx:250](https://github.com/tkhq/sdk/blob/main/packages/react-wallet-kit/src/providers/client/Types.tsx#L250) + +Handles the import flow. + +- This function opens a modal with the ImportComponent for importing a wallet or private key. +- Supports importing wallets using an encrypted bundle, with optional default accounts or custom account parameters. +- Allows users to specify default wallet accounts (address formats or account params) to pre-fill the import form. +- Optionally accepts a callback to handle successful import, which receives the imported wallet's ID. +- Supports customizing the duration of the success page shown after a successful import. +- Allows specifying the stamper to use for the import (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet) for granular authentication control. +- Ensures the imported wallet is added to the user's wallet list and the provider state is refreshed. + +#### Parameters + +##### params? + +###### defaultWalletAccounts? + +[`v1AddressFormat`](../../../_turnkey/sdk-types/v1AddressFormat/readme)[] \| [`v1WalletAccountParams`](../../../_turnkey/sdk-types/v1WalletAccountParams/readme)[] + +array of default wallet accounts (v1AddressFormat[] or v1WalletAccountParams[]) to pre-fill the import form. + +###### stampWith? + +[`StamperType`](../StamperType/readme) + +parameter to specify the stamper to use for the import (Passkey, ApiKey, or Wallet). + +###### successPageDuration? + +`number` + +duration (in ms) for the success page after import (default: 0, no success page). + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to the new wallet's ID. + +*** + +### handleLinkExternalWallet() + +> **handleLinkExternalWallet**(`params?`): `Promise`\<`void`\> + +Defined in: [react-wallet-kit/src/providers/client/Types.tsx:544](https://github.com/tkhq/sdk/blob/main/packages/react-wallet-kit/src/providers/client/Types.tsx#L544) + +Handles the linking of an external wallet account to the user's Turnkey account. + +- This function opens a modal with the LinkWalletModal component, allowing the user to select and connect an external wallet provider (such as MetaMask, Phantom, etc.). +- It fetches the list of available wallet providers (for all supported chains) and passes them to the modal for user selection. +- After a successful wallet connection, the provider state is refreshed to include the newly linked wallet account. +- Optionally, a success page is shown for the specified duration after linking (default: 2000ms). +- Supports both Ethereum and Solana wallet providers, and can be extended to additional chains as supported by Turnkey. +- Handles all error cases and throws a TurnkeyError with appropriate error codes if the client is not initialized or no active session is found. + +#### Parameters + +##### params? + +###### successPageDuration? + +`number` + +duration (in ms) for the success page after linking (default: 2000ms). + +#### Returns + +`Promise`\<`void`\> + +A void promise. + +#### Throws + +If the client is not initialized or if no active session is found. + +*** + +### handleLogin() + +> **handleLogin**(): `Promise`\<`void`\> + +Defined in: [react-wallet-kit/src/providers/client/Types.tsx:98](https://github.com/tkhq/sdk/blob/main/packages/react-wallet-kit/src/providers/client/Types.tsx#L98) + +Handles the login or sign-up flow. + +- This function opens a modal with the AuthComponent, allowing the user to log in or sign up using any enabled authentication method (Passkey, Wallet, OTP, or OAuth). +- It automatically determines available authentication methods based on the current provider configuration and proxy settings. +- The modal-driven flow guides the user through the appropriate authentication steps, including social login if enabled. +- After successful authentication, the provider state is updated and all relevant session, user, and wallet data are refreshed. +- This function is typically used to trigger authentication from a UI button or navigation event. + +#### Returns + +`Promise`\<`void`\> + +A void promise. + +*** + +### handleRemoveOauthProvider() + +> **handleRemoveOauthProvider**(`params`): `Promise`\<`string`[]\> + +Defined in: [react-wallet-kit/src/providers/client/Types.tsx:433](https://github.com/tkhq/sdk/blob/main/packages/react-wallet-kit/src/providers/client/Types.tsx#L433) + +Handles the removal of an OAuth provider. + +- This function opens a modal with the RemoveOAuthProvider component, allowing the user to confirm and remove an OAuth provider (such as Google, Apple, or Facebook) from their account. +- It supports specifying the provider ID to remove, as well as optional modal title and subtitle for custom UI messaging. +- After successful removal, the user details state is refreshed to reflect the updated list of linked OAuth providers. +- Optionally, a callback can be provided to handle successful removal, receiving the updated list of provider IDs. +- Supports customizing the duration of the success page shown after removal. +- Allows specifying the stamper to use for the removal (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet) for granular authentication control. +- Handles all error cases and throws a TurnkeyError with appropriate error codes. + +#### Parameters + +##### params + +###### providerId + +`string` + +The ID of the OAuth provider to remove (as found in the user's provider list). + +###### stampWith? + +[`StamperType`](../StamperType/readme) + +parameter to specify the stamper to use for the removal (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### subTitle? + +`string` + +subtitle for the modal. + +###### successPageDuration? + +`number` + +duration (in ms) for the success page after removal (default: 0, no success page). + +###### title? + +`string` + +title for the modal. + +#### Returns + +`Promise`\<`string`[]\> + +A promise that resolves to an array of provider IDs that were removed. + +#### Throws + +If the client is not initialized, no active session is found, or if there is an error removing the provider. + +*** + +### handleRemovePasskey() + +> **handleRemovePasskey**(`params`): `Promise`\<`string`[]\> + +Defined in: [react-wallet-kit/src/providers/client/Types.tsx:489](https://github.com/tkhq/sdk/blob/main/packages/react-wallet-kit/src/providers/client/Types.tsx#L489) + +Handles the removal of a passkey (authenticator) for the user. + +- This function opens a modal with the RemovePasskey component, allowing the user to confirm and remove a passkey authenticator from their account. +- It supports specifying the authenticator ID to remove, as well as optional modal title and subtitle for custom UI messaging. +- After successful removal, the user details state is refreshed to reflect the updated list of authenticators. +- Supports customizing the duration of the success page shown after removal. +- Allows specifying the stamper to use for the removal (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet) for granular authentication control. +- Handles all error cases and throws a TurnkeyError with appropriate error codes. + +#### Parameters + +##### params + +###### authenticatorId + +`string` + +The ID of the authenticator (passkey) to remove. + +###### stampWith? + +[`StamperType`](../StamperType/readme) + +parameter to specify the stamper to use for the removal (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### subTitle? + +`string` + +subtitle for the modal. + +###### successPageDuration? + +`number` + +duration (in ms) for the success page after removal (default: 0, no success page). + +###### title? + +`string` + +title for the modal. + +###### userId? + +`string` + +user ID to remove the passkey for a specific user (defaults to current session's userId). + +#### Returns + +`Promise`\<`string`[]\> + +A promise that resolves to an array of authenticator IDs that were removed. + +#### Throws + +If the client is not initialized, no active session is found, or if there is an error removing the passkey. + +*** + +### handleRemoveUserEmail() + +> **handleRemoveUserEmail**(`params?`): `Promise`\<`string`\> + +Defined in: [react-wallet-kit/src/providers/client/Types.tsx:557](https://github.com/tkhq/sdk/blob/main/packages/react-wallet-kit/src/providers/client/Types.tsx#L557) + +Handles the removal of a user's email address from their Turnkey account. + +- This function opens a modal with the RemoveUserEmail component, allowing the user to confirm and remove their email address. + +#### Parameters + +##### params? + +###### stampWith? + +[`StamperType`](../StamperType/readme) + +parameter to specify the stamper to use for the removal (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### successPageDuration? + +`number` + +duration (in ms) for the success page after removal (default: 0, no success page). + +###### userId? + +`string` + +The user ID to remove the email for (defaults to current session's userId). + +#### Returns + +`Promise`\<`string`\> + +*** + +### handleRemoveUserPhoneNumber() + +> **handleRemoveUserPhoneNumber**(`params?`): `Promise`\<`string`\> + +Defined in: [react-wallet-kit/src/providers/client/Types.tsx:572](https://github.com/tkhq/sdk/blob/main/packages/react-wallet-kit/src/providers/client/Types.tsx#L572) + +Handles the removal of a user's phone number from their Turnkey account. + +- This function opens a modal with the RemoveUserPhoneNumber component, allowing the user to confirm and remove their phone number. + +#### Parameters + +##### params? + +###### stampWith? + +[`StamperType`](../StamperType/readme) + +parameter to specify the stamper to use for the removal (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### successPageDuration? + +`number` + +duration (in ms) for the success page after removal (default: 0, no success page). + +###### userId? + +`string` + +The user ID to remove the phone number for (defaults to current session's userId). + +#### Returns + +`Promise`\<`string`\> + +*** + +### handleSignMessage() + +> **handleSignMessage**(`params`): `Promise`\<[`v1SignRawPayloadResult`](../../../_turnkey/sdk-types/v1SignRawPayloadResult/readme)\> + +Defined in: [react-wallet-kit/src/providers/client/Types.tsx:518](https://github.com/tkhq/sdk/blob/main/packages/react-wallet-kit/src/providers/client/Types.tsx#L518) + +Handles the signing of a message by displaying a modal for user interaction. + +- This function opens a modal with the SignMessageModal component, prompting the user to review and approve the message signing request. +- Supports signing with any wallet account managed by Turnkey, including externally linked wallets. +- Allows for optional overrides of the encoding and hash function used for the payload, enabling advanced use cases or compatibility with specific blockchains. +- Optionally displays a subtext in the modal for additional context or instructions to the user. +- Returns a promise that resolves to a `v1SignRawPayloadResult` object containing the signed message, signature, and metadata. + +#### Parameters + +##### params + +###### addEthereumPrefix? + +`boolean` + +whether to add the Ethereum prefix to the message (default: false). + +###### encoding? + +[`v1PayloadEncoding`](../../../_turnkey/sdk-types/v1PayloadEncoding/readme) + +encoding for the payload (defaults to the proper encoding for the account type). + +###### hashFunction? + +[`v1HashFunction`](../../../_turnkey/sdk-types/v1HashFunction/readme) + +hash function to use (defaults to the appropriate function for the account type). + +###### message + +`string` + +The message to sign. + +###### stampWith? + +[`StamperType`](../StamperType/readme) + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### subText? + +`string` + +subtext to display in the modal. + +###### successPageDuration? + +`number` + +duration in seconds to display the success page after signing. + +###### walletAccount + +[`WalletAccount`](../WalletAccount/readme) + +The wallet account to use for signing. + +#### Returns + +`Promise`\<[`v1SignRawPayloadResult`](../../../_turnkey/sdk-types/v1SignRawPayloadResult/readme)\> + +A promise that resolves to a `v1SignRawPayloadResult` object containing the signed message. + +#### Throws + +If the client is not initialized or if there is an error during the signing process. + +*** + +### handleUpdateUserEmail() + +> **handleUpdateUserEmail**(`params?`): `Promise`\<`string`\> + +Defined in: [react-wallet-kit/src/providers/client/Types.tsx:275](https://github.com/tkhq/sdk/blob/main/packages/react-wallet-kit/src/providers/client/Types.tsx#L275) + +Handles the update user name flow. + +- This function opens a modal with the UpdateUserName component for updating and verifying the user's name. +- If a userName is provided, it will directly update the user name without showing the modal. +- Uses updateUserName under the hood to perform the update and automatically refreshes the user details state after a successful update. +- Optionally displays a success page after the update, with customizable duration. +- Supports passing a custom title and subtitle for the modal UI. +- Handles all error cases and throws a TurnkeyError with appropriate error codes. + +#### Parameters + +##### params? + +###### email? + +`string` + +###### subTitle? + +`string` + +subtitle for the modal. + +###### successPageDuration? + +`number` + +duration (in ms) for the success page after update (default: 0, no success page). + +###### title? + +`string` + +title for the modal. + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to the userId of the user that was changed. + +#### Throws + +If the client is not initialized, no active session is found, or if there is an error updating the user name. + +*** + +### handleUpdateUserPhoneNumber() + +> **handleUpdateUserPhoneNumber**(`params?`): `Promise`\<`string`\> + +Defined in: [react-wallet-kit/src/providers/client/Types.tsx:302](https://github.com/tkhq/sdk/blob/main/packages/react-wallet-kit/src/providers/client/Types.tsx#L302) + +Handles the update user phone number flow. + +- This function opens a modal with the UpdatePhoneNumber component for updating and verifying the user's phone number. +- If a phoneNumber is provided, it will directly send an OTP request to the user and display the OTP verification modal. +- Supports both manual entry and pre-filled phone numbers, as well as custom modal titles and subtitles. +- Uses the updatePhoneNumberContinue helper to manage the OTP flow, verification, and update logic. +- After successful verification and update, the user details state is refreshed and an optional success page can be shown. +- Supports customizing the duration of the success page after update. +- Throws a TurnkeyError if the client is not initialized, no active session is found, SMS OTP is not enabled, or if there is an error updating the phone number. + +#### Parameters + +##### params? + +###### formattedPhone? + +`string` + +parameter to specify the formatted phone number. + +###### phoneNumber? + +`string` + +parameter to specify the new phone number. + +###### subTitle? + +`string` + +subtitle for the modal. + +###### successPageDuration? + +`number` + +duration for the success page (default: 0, no success page). + +###### title? + +`string` + +title for the modal. + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to the userId of the user that was changed. + +#### Throws + +If the client is not initialized, no active session is found, SMS OTP is not enabled, or if there is an error updating the phone number. + +*** + +### refreshUser() + +> **refreshUser**(`params?`): `Promise`\<`void`\> + +Defined in: [react-wallet-kit/src/providers/client/Types.tsx:65](https://github.com/tkhq/sdk/blob/main/packages/react-wallet-kit/src/providers/client/Types.tsx#L65) + +Refreshes the user details. + +- This function fetches the latest user details for the current session (or optionally for a specific user/organization if provided) + and updates the `user` state variable in the provider. +- If a `stampWith` parameter is provided, it will use that stamper to fetch the user details (supports Passkey, ApiKey, or Wallet stampers). +- Automatically handles error reporting via the configured callbacks. +- Typically used after authentication, user profile updates, or linking/unlinking authenticators to ensure the provider state is up to date. +- If no user is found, the state will not be updated. + +#### Parameters + +##### params? + +###### stampWith? + +[`StamperType`](../StamperType/readme) + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Returns + +`Promise`\<`void`\> + +A promise that resolves when the user details are successfully refreshed and state is updated. + +#### Throws + +If the client is not initialized or if there is an error refreshing the user details. + +*** + +### refreshWallets() + +> **refreshWallets**(`params?`): `Promise`\<`void`\> + +Defined in: [react-wallet-kit/src/providers/client/Types.tsx:83](https://github.com/tkhq/sdk/blob/main/packages/react-wallet-kit/src/providers/client/Types.tsx#L83) + +Refreshes the wallets state for the current user session. + +- This function fetches the latest list of wallets associated with the current session or user, + and updates the `wallets` state variable in the provider. +- If a `stampWith` parameter is provided, it will use that stamper to fetch the wallets + (supports Passkey, ApiKey, or Wallet stampers for granular authentication control). +- Automatically handles error reporting via the configured callbacks. +- Typically used after wallet creation, import, export, account changes, or authentication + to ensure the provider state is up to date. +- If no wallets are found, the state will be set to an empty array. + +#### Parameters + +##### params? + +###### stampWith? + +[`StamperType`](../StamperType/readme) + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Returns + +`Promise`\<`void`\> + +A promise that resolves when the wallets are successfully refreshed and state is updated. + +#### Throws + +If the client is not initialized or if there is an error refreshing the wallets. diff --git a/generated-docs/sdks/react-wallet-kit/index/ConnectedWallet/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/ConnectedWallet/readme.mdx new file mode 100644 index 000000000..848e80b3d --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/ConnectedWallet/readme.mdx @@ -0,0 +1,108 @@ +--- +title: "ConnectedWallet" +mode: wide +--- + +# Interface: ConnectedWallet + +Defined in: core/dist/\_\_types\_\_/base.d.ts:144 + +## Extends + +- [`v1Wallet`](../../../_turnkey/sdk-types/v1Wallet/readme) + +## Properties + +### accounts + +> **accounts**: [`WalletAccount`](../WalletAccount/readme)[] + +Defined in: core/dist/\_\_types\_\_/base.d.ts:146 + +*** + +### createdAt + +> **createdAt**: [`externaldatav1Timestamp`](../../../_turnkey/sdk-types/externaldatav1Timestamp/readme) + +Defined in: sdk-types/dist/\_\_generated\_\_/types.d.ts:2729 + +#### Inherited from + +[`v1Wallet`](../../../_turnkey/sdk-types/v1Wallet/readme).[`createdAt`](../../../_turnkey/sdk-types/v1Wallet/readme#createdat) + +*** + +### exported + +> **exported**: `boolean` + +Defined in: sdk-types/dist/\_\_generated\_\_/types.d.ts:2732 + +True when a given Wallet is exported, false otherwise. + +#### Inherited from + +[`v1Wallet`](../../../_turnkey/sdk-types/v1Wallet/readme).[`exported`](../../../_turnkey/sdk-types/v1Wallet/readme#exported) + +*** + +### imported + +> **imported**: `boolean` + +Defined in: sdk-types/dist/\_\_generated\_\_/types.d.ts:2734 + +True when a given Wallet is imported, false otherwise. + +#### Inherited from + +[`v1Wallet`](../../../_turnkey/sdk-types/v1Wallet/readme).[`imported`](../../../_turnkey/sdk-types/v1Wallet/readme#imported) + +*** + +### source + +> **source**: [`Connected`](../WalletSource/readme#connected) + +Defined in: core/dist/\_\_types\_\_/base.d.ts:145 + +*** + +### updatedAt + +> **updatedAt**: [`externaldatav1Timestamp`](../../../_turnkey/sdk-types/externaldatav1Timestamp/readme) + +Defined in: sdk-types/dist/\_\_generated\_\_/types.d.ts:2730 + +#### Inherited from + +[`v1Wallet`](../../../_turnkey/sdk-types/v1Wallet/readme).[`updatedAt`](../../../_turnkey/sdk-types/v1Wallet/readme#updatedat) + +*** + +### walletId + +> **walletId**: `string` + +Defined in: sdk-types/dist/\_\_generated\_\_/types.d.ts:2726 + +Unique identifier for a given Wallet. + +#### Inherited from + +[`v1Wallet`](../../../_turnkey/sdk-types/v1Wallet/readme).[`walletId`](../../../_turnkey/sdk-types/v1Wallet/readme#walletid) + +*** + +### walletName + +> **walletName**: `string` + +Defined in: sdk-types/dist/\_\_generated\_\_/types.d.ts:2728 + +Human-readable name for a Wallet. + +#### Inherited from + +[`v1Wallet`](../../../_turnkey/sdk-types/v1Wallet/readme).[`walletName`](../../../_turnkey/sdk-types/v1Wallet/readme#walletname) diff --git a/generated-docs/sdks/react-wallet-kit/index/ConnectedWalletAccount/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/ConnectedWalletAccount/readme.mdx new file mode 100644 index 000000000..f4a72b26f --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/ConnectedWalletAccount/readme.mdx @@ -0,0 +1,224 @@ +--- +title: "ConnectedWalletAccount" +mode: wide +--- + +# Interface: ConnectedWalletAccount + +Defined in: core/dist/\_\_types\_\_/base.d.ts:133 + +## Extends + +- [`v1WalletAccount`](../../../_turnkey/sdk-types/v1WalletAccount/readme) + +## Properties + +### address + +> **address**: `string` + +Defined in: sdk-types/dist/\_\_generated\_\_/types.d.ts:2752 + +Address generated using the Wallet seed and Account parameters. + +#### Inherited from + +[`v1WalletAccount`](../../../_turnkey/sdk-types/v1WalletAccount/readme).[`address`](../../../_turnkey/sdk-types/v1WalletAccount/readme#address) + +*** + +### addressFormat + +> **addressFormat**: [`v1AddressFormat`](../../../_turnkey/sdk-types/v1AddressFormat/readme) + +Defined in: sdk-types/dist/\_\_generated\_\_/types.d.ts:2750 + +Address format used to generate the Account. + +#### Inherited from + +[`v1WalletAccount`](../../../_turnkey/sdk-types/v1WalletAccount/readme).[`addressFormat`](../../../_turnkey/sdk-types/v1WalletAccount/readme#addressformat) + +*** + +### createdAt + +> **createdAt**: [`externaldatav1Timestamp`](../../../_turnkey/sdk-types/externaldatav1Timestamp/readme) + +Defined in: sdk-types/dist/\_\_generated\_\_/types.d.ts:2753 + +#### Inherited from + +[`v1WalletAccount`](../../../_turnkey/sdk-types/v1WalletAccount/readme).[`createdAt`](../../../_turnkey/sdk-types/v1WalletAccount/readme#createdat) + +*** + +### curve + +> **curve**: [`v1Curve`](../../../_turnkey/sdk-types/v1Curve/readme) + +Defined in: sdk-types/dist/\_\_generated\_\_/types.d.ts:2744 + +Cryptographic curve used to generate the Account. + +#### Inherited from + +[`v1WalletAccount`](../../../_turnkey/sdk-types/v1WalletAccount/readme).[`curve`](../../../_turnkey/sdk-types/v1WalletAccount/readme#curve) + +*** + +### organizationId + +> **organizationId**: `string` + +Defined in: sdk-types/dist/\_\_generated\_\_/types.d.ts:2740 + +The Organization the Account belongs to. + +#### Inherited from + +[`v1WalletAccount`](../../../_turnkey/sdk-types/v1WalletAccount/readme).[`organizationId`](../../../_turnkey/sdk-types/v1WalletAccount/readme#organizationid) + +*** + +### path + +> **path**: `string` + +Defined in: sdk-types/dist/\_\_generated\_\_/types.d.ts:2748 + +Path used to generate the Account. + +#### Inherited from + +[`v1WalletAccount`](../../../_turnkey/sdk-types/v1WalletAccount/readme).[`path`](../../../_turnkey/sdk-types/v1WalletAccount/readme#path) + +*** + +### pathFormat + +> **pathFormat**: `"PATH_FORMAT_BIP32"` + +Defined in: sdk-types/dist/\_\_generated\_\_/types.d.ts:2746 + +Path format used to generate the Account. + +#### Inherited from + +[`v1WalletAccount`](../../../_turnkey/sdk-types/v1WalletAccount/readme).[`pathFormat`](../../../_turnkey/sdk-types/v1WalletAccount/readme#pathformat) + +*** + +### publicKey? + +> `optional` **publicKey**: `string` + +Defined in: sdk-types/dist/\_\_generated\_\_/types.d.ts:2756 + +The public component of this wallet account's underlying cryptographic key pair. + +#### Inherited from + +[`v1WalletAccount`](../../../_turnkey/sdk-types/v1WalletAccount/readme).[`publicKey`](../../../_turnkey/sdk-types/v1WalletAccount/readme#publickey) + +*** + +### signAndSendTransaction()? + +> `optional` **signAndSendTransaction**: (`unsignedTransaction`) => `Promise`\<`string`\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:137 + +#### Parameters + +##### unsignedTransaction + +`string` + +#### Returns + +`Promise`\<`string`\> + +*** + +### signMessage() + +> **signMessage**: (`message`) => `Promise`\<`string`\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:135 + +#### Parameters + +##### message + +`string` + +#### Returns + +`Promise`\<`string`\> + +*** + +### signTransaction()? + +> `optional` **signTransaction**: (`unsignedTransaction`) => `Promise`\<`string`\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:136 + +#### Parameters + +##### unsignedTransaction + +`string` + +#### Returns + +`Promise`\<`string`\> + +*** + +### source + +> **source**: [`Connected`](../WalletSource/readme#connected) + +Defined in: core/dist/\_\_types\_\_/base.d.ts:134 + +*** + +### updatedAt + +> **updatedAt**: [`externaldatav1Timestamp`](../../../_turnkey/sdk-types/externaldatav1Timestamp/readme) + +Defined in: sdk-types/dist/\_\_generated\_\_/types.d.ts:2754 + +#### Inherited from + +[`v1WalletAccount`](../../../_turnkey/sdk-types/v1WalletAccount/readme).[`updatedAt`](../../../_turnkey/sdk-types/v1WalletAccount/readme#updatedat) + +*** + +### walletAccountId + +> **walletAccountId**: `string` + +Defined in: sdk-types/dist/\_\_generated\_\_/types.d.ts:2738 + +Unique identifier for a given Wallet Account. + +#### Inherited from + +[`v1WalletAccount`](../../../_turnkey/sdk-types/v1WalletAccount/readme).[`walletAccountId`](../../../_turnkey/sdk-types/v1WalletAccount/readme#walletaccountid) + +*** + +### walletId + +> **walletId**: `string` + +Defined in: sdk-types/dist/\_\_generated\_\_/types.d.ts:2742 + +The Wallet the Account was derived from. + +#### Inherited from + +[`v1WalletAccount`](../../../_turnkey/sdk-types/v1WalletAccount/readme).[`walletId`](../../../_turnkey/sdk-types/v1WalletAccount/readme#walletid) diff --git a/generated-docs/sdks/react-wallet-kit/index/CreateSubOrgParams/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/CreateSubOrgParams/readme.mdx new file mode 100644 index 000000000..f49da9778 --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/CreateSubOrgParams/readme.mdx @@ -0,0 +1,126 @@ +--- +title: "CreateSubOrgParams" +mode: wide +--- + +# Type Alias: CreateSubOrgParams + +> **CreateSubOrgParams** = `object` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:157 + +## Properties + +### apiKeys? + +> `optional` **apiKeys**: `object`[] + +Defined in: core/dist/\_\_types\_\_/base.d.ts:169 + +#### apiKeyName? + +> `optional` **apiKeyName**: `string` + +#### curveType? + +> `optional` **curveType**: [`v1ApiKeyCurve`](../../../_turnkey/sdk-types/v1ApiKeyCurve/readme) + +#### expirationSeconds? + +> `optional` **expirationSeconds**: `string` + +#### publicKey + +> **publicKey**: `string` + +*** + +### authenticators? + +> `optional` **authenticators**: `object`[] + +Defined in: core/dist/\_\_types\_\_/base.d.ts:162 + +#### attestation + +> **attestation**: [`v1Attestation`](../../../_turnkey/sdk-types/v1Attestation/readme) + +#### authenticatorName + +> **authenticatorName**: `string` + +#### challenge + +> **challenge**: `string` + +*** + +### customWallet? + +> `optional` **customWallet**: `object` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:175 + +#### walletAccounts + +> **walletAccounts**: [`v1WalletAccountParams`](../../../_turnkey/sdk-types/v1WalletAccountParams/readme)[] + +#### walletName + +> **walletName**: `string` + +*** + +### oauthProviders? + +> `optional` **oauthProviders**: [`Provider`](../Provider/readme)[] + +Defined in: core/dist/\_\_types\_\_/base.d.ts:179 + +*** + +### subOrgName? + +> `optional` **subOrgName**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:159 + +*** + +### userEmail? + +> `optional` **userEmail**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:160 + +*** + +### userName? + +> `optional` **userName**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:158 + +*** + +### userPhoneNumber? + +> `optional` **userPhoneNumber**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:167 + +*** + +### userTag? + +> `optional` **userTag**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:161 + +*** + +### verificationToken? + +> `optional` **verificationToken**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:168 diff --git a/generated-docs/sdks/react-wallet-kit/index/CreateSuborgResponse/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/CreateSuborgResponse/readme.mdx new file mode 100644 index 000000000..894443ad6 --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/CreateSuborgResponse/readme.mdx @@ -0,0 +1,18 @@ +--- +title: "CreateSuborgResponse" +mode: wide +--- + +# Type Alias: CreateSuborgResponse + +> **CreateSuborgResponse** = `object` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:154 + +## Properties + +### subOrganizationId + +> **subOrganizationId**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:155 diff --git a/generated-docs/sdks/react-wallet-kit/index/Curve/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/Curve/readme.mdx new file mode 100644 index 000000000..e02d0d884 --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/Curve/readme.mdx @@ -0,0 +1,24 @@ +--- +title: "Curve" +mode: wide +--- + +# Enumeration: Curve + +Defined in: core/dist/\_\_types\_\_/base.d.ts:122 + +## Enumeration Members + +### ED25519 + +> **ED25519**: `"CURVE_ED25519"` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:124 + +*** + +### SECP256K1 + +> **SECP256K1**: `"CURVE_SECP256K1"` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:123 diff --git a/generated-docs/sdks/react-wallet-kit/index/DEFAULT_SESSION_EXPIRATION_IN_SECONDS/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/DEFAULT_SESSION_EXPIRATION_IN_SECONDS/readme.mdx new file mode 100644 index 000000000..921a7e220 --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/DEFAULT_SESSION_EXPIRATION_IN_SECONDS/readme.mdx @@ -0,0 +1,10 @@ +--- +title: "DEFAULT_SESSION_EXPIRATION_IN_SECONDS" +mode: wide +--- + +# Variable: DEFAULT\_SESSION\_EXPIRATION\_IN\_SECONDS + +> `const` **DEFAULT\_SESSION\_EXPIRATION\_IN\_SECONDS**: `"900"` = `"900"` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:7 diff --git a/generated-docs/sdks/react-wallet-kit/index/EmbeddedAPIKey/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/EmbeddedAPIKey/readme.mdx new file mode 100644 index 000000000..a4dde5dfe --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/EmbeddedAPIKey/readme.mdx @@ -0,0 +1,26 @@ +--- +title: "EmbeddedAPIKey" +mode: wide +--- + +# Type Alias: EmbeddedAPIKey + +> **EmbeddedAPIKey** = `object` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:54 + +## Properties + +### authBundle + +> **authBundle**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:55 + +*** + +### publicKey + +> **publicKey**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:56 diff --git a/generated-docs/sdks/react-wallet-kit/index/EmbeddedWallet/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/EmbeddedWallet/readme.mdx new file mode 100644 index 000000000..a37e7cdf0 --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/EmbeddedWallet/readme.mdx @@ -0,0 +1,108 @@ +--- +title: "EmbeddedWallet" +mode: wide +--- + +# Interface: EmbeddedWallet + +Defined in: core/dist/\_\_types\_\_/base.d.ts:140 + +## Extends + +- [`v1Wallet`](../../../_turnkey/sdk-types/v1Wallet/readme) + +## Properties + +### accounts + +> **accounts**: [`WalletAccount`](../WalletAccount/readme)[] + +Defined in: core/dist/\_\_types\_\_/base.d.ts:142 + +*** + +### createdAt + +> **createdAt**: [`externaldatav1Timestamp`](../../../_turnkey/sdk-types/externaldatav1Timestamp/readme) + +Defined in: sdk-types/dist/\_\_generated\_\_/types.d.ts:2729 + +#### Inherited from + +[`v1Wallet`](../../../_turnkey/sdk-types/v1Wallet/readme).[`createdAt`](../../../_turnkey/sdk-types/v1Wallet/readme#createdat) + +*** + +### exported + +> **exported**: `boolean` + +Defined in: sdk-types/dist/\_\_generated\_\_/types.d.ts:2732 + +True when a given Wallet is exported, false otherwise. + +#### Inherited from + +[`v1Wallet`](../../../_turnkey/sdk-types/v1Wallet/readme).[`exported`](../../../_turnkey/sdk-types/v1Wallet/readme#exported) + +*** + +### imported + +> **imported**: `boolean` + +Defined in: sdk-types/dist/\_\_generated\_\_/types.d.ts:2734 + +True when a given Wallet is imported, false otherwise. + +#### Inherited from + +[`v1Wallet`](../../../_turnkey/sdk-types/v1Wallet/readme).[`imported`](../../../_turnkey/sdk-types/v1Wallet/readme#imported) + +*** + +### source + +> **source**: [`Embedded`](../WalletSource/readme#embedded) + +Defined in: core/dist/\_\_types\_\_/base.d.ts:141 + +*** + +### updatedAt + +> **updatedAt**: [`externaldatav1Timestamp`](../../../_turnkey/sdk-types/externaldatav1Timestamp/readme) + +Defined in: sdk-types/dist/\_\_generated\_\_/types.d.ts:2730 + +#### Inherited from + +[`v1Wallet`](../../../_turnkey/sdk-types/v1Wallet/readme).[`updatedAt`](../../../_turnkey/sdk-types/v1Wallet/readme#updatedat) + +*** + +### walletId + +> **walletId**: `string` + +Defined in: sdk-types/dist/\_\_generated\_\_/types.d.ts:2726 + +Unique identifier for a given Wallet. + +#### Inherited from + +[`v1Wallet`](../../../_turnkey/sdk-types/v1Wallet/readme).[`walletId`](../../../_turnkey/sdk-types/v1Wallet/readme#walletid) + +*** + +### walletName + +> **walletName**: `string` + +Defined in: sdk-types/dist/\_\_generated\_\_/types.d.ts:2728 + +Human-readable name for a Wallet. + +#### Inherited from + +[`v1Wallet`](../../../_turnkey/sdk-types/v1Wallet/readme).[`walletName`](../../../_turnkey/sdk-types/v1Wallet/readme#walletname) diff --git a/generated-docs/sdks/react-wallet-kit/index/EmbeddedWalletAccount/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/EmbeddedWalletAccount/readme.mdx new file mode 100644 index 000000000..1d05df87a --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/EmbeddedWalletAccount/readme.mdx @@ -0,0 +1,170 @@ +--- +title: "EmbeddedWalletAccount" +mode: wide +--- + +# Interface: EmbeddedWalletAccount + +Defined in: core/dist/\_\_types\_\_/base.d.ts:130 + +## Extends + +- [`v1WalletAccount`](../../../_turnkey/sdk-types/v1WalletAccount/readme) + +## Properties + +### address + +> **address**: `string` + +Defined in: sdk-types/dist/\_\_generated\_\_/types.d.ts:2752 + +Address generated using the Wallet seed and Account parameters. + +#### Inherited from + +[`v1WalletAccount`](../../../_turnkey/sdk-types/v1WalletAccount/readme).[`address`](../../../_turnkey/sdk-types/v1WalletAccount/readme#address) + +*** + +### addressFormat + +> **addressFormat**: [`v1AddressFormat`](../../../_turnkey/sdk-types/v1AddressFormat/readme) + +Defined in: sdk-types/dist/\_\_generated\_\_/types.d.ts:2750 + +Address format used to generate the Account. + +#### Inherited from + +[`v1WalletAccount`](../../../_turnkey/sdk-types/v1WalletAccount/readme).[`addressFormat`](../../../_turnkey/sdk-types/v1WalletAccount/readme#addressformat) + +*** + +### createdAt + +> **createdAt**: [`externaldatav1Timestamp`](../../../_turnkey/sdk-types/externaldatav1Timestamp/readme) + +Defined in: sdk-types/dist/\_\_generated\_\_/types.d.ts:2753 + +#### Inherited from + +[`v1WalletAccount`](../../../_turnkey/sdk-types/v1WalletAccount/readme).[`createdAt`](../../../_turnkey/sdk-types/v1WalletAccount/readme#createdat) + +*** + +### curve + +> **curve**: [`v1Curve`](../../../_turnkey/sdk-types/v1Curve/readme) + +Defined in: sdk-types/dist/\_\_generated\_\_/types.d.ts:2744 + +Cryptographic curve used to generate the Account. + +#### Inherited from + +[`v1WalletAccount`](../../../_turnkey/sdk-types/v1WalletAccount/readme).[`curve`](../../../_turnkey/sdk-types/v1WalletAccount/readme#curve) + +*** + +### organizationId + +> **organizationId**: `string` + +Defined in: sdk-types/dist/\_\_generated\_\_/types.d.ts:2740 + +The Organization the Account belongs to. + +#### Inherited from + +[`v1WalletAccount`](../../../_turnkey/sdk-types/v1WalletAccount/readme).[`organizationId`](../../../_turnkey/sdk-types/v1WalletAccount/readme#organizationid) + +*** + +### path + +> **path**: `string` + +Defined in: sdk-types/dist/\_\_generated\_\_/types.d.ts:2748 + +Path used to generate the Account. + +#### Inherited from + +[`v1WalletAccount`](../../../_turnkey/sdk-types/v1WalletAccount/readme).[`path`](../../../_turnkey/sdk-types/v1WalletAccount/readme#path) + +*** + +### pathFormat + +> **pathFormat**: `"PATH_FORMAT_BIP32"` + +Defined in: sdk-types/dist/\_\_generated\_\_/types.d.ts:2746 + +Path format used to generate the Account. + +#### Inherited from + +[`v1WalletAccount`](../../../_turnkey/sdk-types/v1WalletAccount/readme).[`pathFormat`](../../../_turnkey/sdk-types/v1WalletAccount/readme#pathformat) + +*** + +### publicKey? + +> `optional` **publicKey**: `string` + +Defined in: sdk-types/dist/\_\_generated\_\_/types.d.ts:2756 + +The public component of this wallet account's underlying cryptographic key pair. + +#### Inherited from + +[`v1WalletAccount`](../../../_turnkey/sdk-types/v1WalletAccount/readme).[`publicKey`](../../../_turnkey/sdk-types/v1WalletAccount/readme#publickey) + +*** + +### source + +> **source**: [`Embedded`](../WalletSource/readme#embedded) + +Defined in: core/dist/\_\_types\_\_/base.d.ts:131 + +*** + +### updatedAt + +> **updatedAt**: [`externaldatav1Timestamp`](../../../_turnkey/sdk-types/externaldatav1Timestamp/readme) + +Defined in: sdk-types/dist/\_\_generated\_\_/types.d.ts:2754 + +#### Inherited from + +[`v1WalletAccount`](../../../_turnkey/sdk-types/v1WalletAccount/readme).[`updatedAt`](../../../_turnkey/sdk-types/v1WalletAccount/readme#updatedat) + +*** + +### walletAccountId + +> **walletAccountId**: `string` + +Defined in: sdk-types/dist/\_\_generated\_\_/types.d.ts:2738 + +Unique identifier for a given Wallet Account. + +#### Inherited from + +[`v1WalletAccount`](../../../_turnkey/sdk-types/v1WalletAccount/readme).[`walletAccountId`](../../../_turnkey/sdk-types/v1WalletAccount/readme#walletaccountid) + +*** + +### walletId + +> **walletId**: `string` + +Defined in: sdk-types/dist/\_\_generated\_\_/types.d.ts:2742 + +The Wallet the Account was derived from. + +#### Inherited from + +[`v1WalletAccount`](../../../_turnkey/sdk-types/v1WalletAccount/readme).[`walletId`](../../../_turnkey/sdk-types/v1WalletAccount/readme#walletid) diff --git a/generated-docs/sdks/react-wallet-kit/index/EthereumWalletInterface/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/EthereumWalletInterface/readme.mdx new file mode 100644 index 000000000..d08df9fcf --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/EthereumWalletInterface/readme.mdx @@ -0,0 +1,173 @@ +--- +title: "EthereumWalletInterface" +mode: wide +--- + +# Interface: EthereumWalletInterface + +Defined in: core/dist/\_\_types\_\_/base.d.ts:391 + +Ethereum wallets require a signed message to derive the public key. + +## Remarks + +This is the SECP256K1 public key of the Ethereum wallet, not the address. +This requires that the wallet signs a message in order to derive the public key. + + EthereumWalletInterface + +## Extends + +- [`BaseWalletInterface`](../BaseWalletInterface/readme) + +## Properties + +### connectWalletAccount() + +> **connectWalletAccount**: (`provider`) => `Promise`\<`void`\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:366 + +#### Parameters + +##### provider + +[`WalletProvider`](../WalletProvider/readme) + +#### Returns + +`Promise`\<`void`\> + +#### Inherited from + +[`BaseWalletInterface`](../BaseWalletInterface/readme).[`connectWalletAccount`](../BaseWalletInterface/readme#connectwalletaccount) + +*** + +### disconnectWalletAccount() + +> **disconnectWalletAccount**: (`provider`) => `Promise`\<`void`\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:367 + +#### Parameters + +##### provider + +[`WalletProvider`](../WalletProvider/readme) + +#### Returns + +`Promise`\<`void`\> + +#### Inherited from + +[`BaseWalletInterface`](../BaseWalletInterface/readme).[`disconnectWalletAccount`](../BaseWalletInterface/readme#disconnectwalletaccount) + +*** + +### getProviders() + +> **getProviders**: () => `Promise`\<[`WalletProvider`](../WalletProvider/readme)[]\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:365 + +#### Returns + +`Promise`\<[`WalletProvider`](../WalletProvider/readme)[]\> + +#### Inherited from + +[`BaseWalletInterface`](../BaseWalletInterface/readme).[`getProviders`](../BaseWalletInterface/readme#getproviders) + +*** + +### getPublicKey() + +> **getPublicKey**: (`provider`) => `Promise`\<`string`\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:364 + +Returns the public key, which is the SECP256K1 hex encoded public key from your Ethereum wallet. + +#### Parameters + +##### provider + +[`WalletProvider`](../WalletProvider/readme) + +#### Returns + +`Promise`\<`string`\> + +#### Inherited from + +[`BaseWalletInterface`](../BaseWalletInterface/readme).[`getPublicKey`](../BaseWalletInterface/readme#getpublickey) + +*** + +### interfaceType + +> **interfaceType**: [`Ethereum`](../WalletInterfaceType/readme#ethereum) + +Defined in: core/dist/\_\_types\_\_/base.d.ts:392 + +#### Overrides + +[`BaseWalletInterface`](../BaseWalletInterface/readme).[`interfaceType`](../BaseWalletInterface/readme#interfacetype) + +*** + +### sign() + +> **sign**: (`message`, `provider`, `intent`) => `Promise`\<`string`\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:363 + +#### Parameters + +##### message + +`string` + +##### provider + +[`WalletProvider`](../WalletProvider/readme) + +##### intent + +[`SignIntent`](../SignIntent/readme) + +#### Returns + +`Promise`\<`string`\> + +#### Inherited from + +[`BaseWalletInterface`](../BaseWalletInterface/readme).[`sign`](../BaseWalletInterface/readme#sign) + +*** + +### switchChain()? + +> `optional` **switchChain**: (`provider`, `chainOrId`) => `Promise`\<`void`\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:368 + +#### Parameters + +##### provider + +[`WalletProvider`](../WalletProvider/readme) + +##### chainOrId + +`string` | [`SwitchableChain`](../SwitchableChain/readme) + +#### Returns + +`Promise`\<`void`\> + +#### Inherited from + +[`BaseWalletInterface`](../BaseWalletInterface/readme).[`switchChain`](../BaseWalletInterface/readme#switchchain) diff --git a/generated-docs/sdks/react-wallet-kit/index/EvmChainInfo/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/EvmChainInfo/readme.mdx new file mode 100644 index 000000000..e7e2e7776 --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/EvmChainInfo/readme.mdx @@ -0,0 +1,26 @@ +--- +title: "EvmChainInfo" +mode: wide +--- + +# Type Alias: EvmChainInfo + +> **EvmChainInfo** = `object` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:322 + +## Properties + +### chainId + +> **chainId**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:324 + +*** + +### namespace + +> **namespace**: [`Ethereum`](../Chain/readme#ethereum) + +Defined in: core/dist/\_\_types\_\_/base.d.ts:323 diff --git a/generated-docs/sdks/react-wallet-kit/index/ExportBundle/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/ExportBundle/readme.mdx new file mode 100644 index 000000000..bd0af6ffc --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/ExportBundle/readme.mdx @@ -0,0 +1,10 @@ +--- +title: "ExportBundle" +mode: wide +--- + +# Type Alias: ExportBundle + +> **ExportBundle** = `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:121 diff --git a/generated-docs/sdks/react-wallet-kit/index/FilterType/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/FilterType/readme.mdx new file mode 100644 index 000000000..74c52880e --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/FilterType/readme.mdx @@ -0,0 +1,40 @@ +--- +title: "FilterType" +mode: wide +--- + +# Enumeration: FilterType + +Defined in: core/dist/\_\_types\_\_/base.d.ts:222 + +## Enumeration Members + +### Email + +> **Email**: `"EMAIL"` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:223 + +*** + +### OidcToken + +> **OidcToken**: `"OIDC_TOKEN"` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:225 + +*** + +### PublicKey + +> **PublicKey**: `"PUBLIC_KEY"` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:226 + +*** + +### Sms + +> **Sms**: `"PHONE_NUMBER"` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:224 diff --git a/generated-docs/sdks/react-wallet-kit/index/GrpcStatus/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/GrpcStatus/readme.mdx new file mode 100644 index 000000000..5f0058937 --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/GrpcStatus/readme.mdx @@ -0,0 +1,34 @@ +--- +title: "GrpcStatus" +mode: wide +--- + +# Type Alias: GrpcStatus + +> **GrpcStatus** = `object` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:8 + +## Properties + +### code + +> **code**: `number` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:10 + +*** + +### details + +> **details**: `unknown`[] \| `null` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:11 + +*** + +### message + +> **message**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:9 diff --git a/generated-docs/sdks/react-wallet-kit/index/IframeClientParams/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/IframeClientParams/readme.mdx new file mode 100644 index 000000000..d3a3d9373 --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/IframeClientParams/readme.mdx @@ -0,0 +1,40 @@ +--- +title: "IframeClientParams" +mode: wide +--- + +# Interface: IframeClientParams + +Defined in: core/dist/\_\_types\_\_/base.d.ts:94 + +## Properties + +### dangerouslyOverrideIframeKeyTtl? + +> `optional` **dangerouslyOverrideIframeKeyTtl**: `number` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:98 + +*** + +### iframeContainer + +> **iframeContainer**: `undefined` \| `null` \| `HTMLElement` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:95 + +*** + +### iframeElementId? + +> `optional` **iframeElementId**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:97 + +*** + +### iframeUrl + +> **iframeUrl**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:96 diff --git a/generated-docs/sdks/react-wallet-kit/index/LoginWithBundleParams/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/LoginWithBundleParams/readme.mdx new file mode 100644 index 000000000..2d75e39da --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/LoginWithBundleParams/readme.mdx @@ -0,0 +1,24 @@ +--- +title: "LoginWithBundleParams" +mode: wide +--- + +# Interface: LoginWithBundleParams + +Defined in: core/dist/\_\_types\_\_/base.d.ts:111 + +## Properties + +### bundle + +> **bundle**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:112 + +*** + +### expirationSeconds? + +> `optional` **expirationSeconds**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:113 diff --git a/generated-docs/sdks/react-wallet-kit/index/LoginWithWalletParams/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/LoginWithWalletParams/readme.mdx new file mode 100644 index 000000000..c9c3e2ed4 --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/LoginWithWalletParams/readme.mdx @@ -0,0 +1,32 @@ +--- +title: "LoginWithWalletParams" +mode: wide +--- + +# Interface: LoginWithWalletParams + +Defined in: core/dist/\_\_types\_\_/base.d.ts:115 + +## Properties + +### expirationSeconds? + +> `optional` **expirationSeconds**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:117 + +*** + +### publicKey? + +> `optional` **publicKey**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:118 + +*** + +### sessionType + +> **sessionType**: [`SessionType`](../../../sdk-browser/index/SessionType/readme) + +Defined in: core/dist/\_\_types\_\_/base.d.ts:116 diff --git a/generated-docs/sdks/react-wallet-kit/index/MethodType/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/MethodType/readme.mdx new file mode 100644 index 000000000..c76f69088 --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/MethodType/readme.mdx @@ -0,0 +1,32 @@ +--- +title: "MethodType" +mode: wide +--- + +# Enumeration: MethodType + +Defined in: core/dist/\_\_types\_\_/base.d.ts:13 + +## Enumeration Members + +### Command + +> **Command**: `2` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:16 + +*** + +### Get + +> **Get**: `0` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:14 + +*** + +### List + +> **List**: `1` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:15 diff --git a/generated-docs/sdks/react-wallet-kit/index/OtpType/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/OtpType/readme.mdx new file mode 100644 index 000000000..e77d39371 --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/OtpType/readme.mdx @@ -0,0 +1,24 @@ +--- +title: "OtpType" +mode: wide +--- + +# Enumeration: OtpType + +Defined in: core/dist/\_\_types\_\_/base.d.ts:218 + +## Enumeration Members + +### Email + +> **Email**: `"OTP_TYPE_EMAIL"` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:219 + +*** + +### Sms + +> **Sms**: `"OTP_TYPE_SMS"` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:220 diff --git a/generated-docs/sdks/react-wallet-kit/index/OtpTypeToFilterTypeMap/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/OtpTypeToFilterTypeMap/readme.mdx new file mode 100644 index 000000000..e1599237b --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/OtpTypeToFilterTypeMap/readme.mdx @@ -0,0 +1,20 @@ +--- +title: "OtpTypeToFilterTypeMap" +mode: wide +--- + +# Variable: OtpTypeToFilterTypeMap + +> `const` **OtpTypeToFilterTypeMap**: `object` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:228 + +## Type declaration + +### OTP\_TYPE\_EMAIL + +> **OTP\_TYPE\_EMAIL**: [`FilterType`](../FilterType/readme) + +### OTP\_TYPE\_SMS + +> **OTP\_TYPE\_SMS**: [`FilterType`](../FilterType/readme) diff --git a/generated-docs/sdks/react-wallet-kit/index/Passkey/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/Passkey/readme.mdx new file mode 100644 index 000000000..1c1d7d6f7 --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/Passkey/readme.mdx @@ -0,0 +1,42 @@ +--- +title: "Passkey" +mode: wide +--- + +# Type Alias: Passkey + +> **Passkey** = `object` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:58 + +## Properties + +### attestation + +> **attestation**: `object` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:60 + +#### attestationObject + +> **attestationObject**: `string` + +#### clientDataJson + +> **clientDataJson**: `string` + +#### credentialId + +> **credentialId**: `string` + +#### transports + +> **transports**: (`"AUTHENTICATOR_TRANSPORT_BLE"` \| `"AUTHENTICATOR_TRANSPORT_INTERNAL"` \| `"AUTHENTICATOR_TRANSPORT_NFC"` \| `"AUTHENTICATOR_TRANSPORT_USB"` \| `"AUTHENTICATOR_TRANSPORT_HYBRID"`)[] + +*** + +### encodedChallenge + +> **encodedChallenge**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:59 diff --git a/generated-docs/sdks/react-wallet-kit/index/PasskeyClientParams/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/PasskeyClientParams/readme.mdx new file mode 100644 index 000000000..f1804d3c6 --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/PasskeyClientParams/readme.mdx @@ -0,0 +1,40 @@ +--- +title: "PasskeyClientParams" +mode: wide +--- + +# Interface: PasskeyClientParams + +Defined in: core/dist/\_\_types\_\_/base.d.ts:100 + +## Properties + +### allowCredentials? + +> `optional` **allowCredentials**: `PublicKeyCredentialDescriptor`[] + +Defined in: core/dist/\_\_types\_\_/base.d.ts:104 + +*** + +### rpId? + +> `optional` **rpId**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:101 + +*** + +### timeout? + +> `optional` **timeout**: `number` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:102 + +*** + +### userVerification? + +> `optional` **userVerification**: `UserVerificationRequirement` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:103 diff --git a/generated-docs/sdks/react-wallet-kit/index/Provider/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/Provider/readme.mdx new file mode 100644 index 000000000..1d7d162c9 --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/Provider/readme.mdx @@ -0,0 +1,26 @@ +--- +title: "Provider" +mode: wide +--- + +# Type Alias: Provider + +> **Provider** = `object` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:150 + +## Properties + +### oidcToken + +> **oidcToken**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:152 + +*** + +### providerName + +> **providerName**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:151 diff --git a/generated-docs/sdks/react-wallet-kit/index/README.mdx b/generated-docs/sdks/react-wallet-kit/index/README.mdx new file mode 100644 index 000000000..f5f4e79ad --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/README.mdx @@ -0,0 +1,92 @@ +--- +title: "Index" +mode: wide +--- + +# index + +## Enumerations + +- [AuthClient](AuthClient/readme) +- [Chain](Chain/readme) +- [Curve](Curve/readme) +- [FilterType](FilterType/readme) +- [MethodType](MethodType/readme) +- [OtpType](OtpType/readme) +- [SessionKey](SessionKey/readme) +- [SignIntent](SignIntent/readme) +- [StamperType](StamperType/readme) +- [WalletInterfaceType](WalletInterfaceType/readme) +- [WalletSource](WalletSource/readme) + +## Classes + +- [TurnkeyRequestError](TurnkeyRequestError/readme) + +## Interfaces + +- [ActivityMetadata](ActivityMetadata/readme) +- [ActivityResponse](ActivityResponse/readme) +- [ApiKeyStamperBase](ApiKeyStamperBase/readme) +- [BaseWalletInterface](BaseWalletInterface/readme) +- [ClientContextType](ClientContextType/readme) +- [ConnectedWallet](ConnectedWallet/readme) +- [ConnectedWalletAccount](ConnectedWalletAccount/readme) +- [EmbeddedWallet](EmbeddedWallet/readme) +- [EmbeddedWalletAccount](EmbeddedWalletAccount/readme) +- [EthereumWalletInterface](EthereumWalletInterface/readme) +- [IframeClientParams](IframeClientParams/readme) +- [LoginWithBundleParams](LoginWithBundleParams/readme) +- [LoginWithWalletParams](LoginWithWalletParams/readme) +- [PasskeyClientParams](PasskeyClientParams/readme) +- [RefreshSessionParams](RefreshSessionParams/readme) +- [SolanaWalletInterface](SolanaWalletInterface/readme) +- [StorageBase](StorageBase/readme) +- [SubOrganization](SubOrganization/readme) +- [TStamper](TStamper/readme) +- [TurnkeyHttpClientConfig](TurnkeyHttpClientConfig/readme) +- [TurnkeySDKClientConfig](TurnkeySDKClientConfig/readme) +- [WalletConnectInterface](WalletConnectInterface/readme) +- [WalletConnectProvider](WalletConnectProvider/readme) +- [WalletManagerBase](WalletManagerBase/readme) +- [WalletProvider](WalletProvider/readme) +- [WalletProviderInfo](WalletProviderInfo/readme) + +## Type Aliases + +- [ChainInfo](ChainInfo/readme) +- [commandOverrideParams](commandOverrideParams/readme) +- [CreateSubOrgParams](CreateSubOrgParams/readme) +- [CreateSuborgResponse](CreateSuborgResponse/readme) +- [EmbeddedAPIKey](EmbeddedAPIKey/readme) +- [EvmChainInfo](EvmChainInfo/readme) +- [ExportBundle](ExportBundle/readme) +- [GrpcStatus](GrpcStatus/readme) +- [Passkey](Passkey/readme) +- [Provider](Provider/readme) +- [queryOverrideParams](queryOverrideParams/readme) +- [SignUpBody](SignUpBody/readme) +- [SolanaChainInfo](SolanaChainInfo/readme) +- [SwitchableChain](SwitchableChain/readme) +- [TActivityPollerConfig](TActivityPollerConfig/readme) +- [THttpConfig](THttpConfig/readme) +- [TPasskeyStamperConfig](TPasskeyStamperConfig/readme) +- [TStamp](TStamp/readme) +- [TWalletManagerConfig](TWalletManagerConfig/readme) +- [User](User/readme) +- [Wallet](Wallet/readme) +- [WalletAccount](WalletAccount/readme) +- [WalletAccountParams](WalletAccountParams/readme) +- [WalletInterface](WalletInterface/readme) +- [WalletRpcProvider](WalletRpcProvider/readme) + +## Variables + +- [DEFAULT\_SESSION\_EXPIRATION\_IN\_SECONDS](DEFAULT_SESSION_EXPIRATION_IN_SECONDS/readme) +- [OtpTypeToFilterTypeMap](OtpTypeToFilterTypeMap/readme) + +## Functions + +- [TurnkeyProvider](TurnkeyProvider/readme) +- [useModal](useModal/readme) +- [useTurnkey](useTurnkey/readme) diff --git a/generated-docs/sdks/react-wallet-kit/index/RefreshSessionParams/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/RefreshSessionParams/readme.mdx new file mode 100644 index 000000000..2986297c7 --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/RefreshSessionParams/readme.mdx @@ -0,0 +1,32 @@ +--- +title: "RefreshSessionParams" +mode: wide +--- + +# Interface: RefreshSessionParams + +Defined in: core/dist/\_\_types\_\_/base.d.ts:106 + +## Properties + +### expirationSeconds? + +> `optional` **expirationSeconds**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:108 + +*** + +### publicKey? + +> `optional` **publicKey**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:109 + +*** + +### sessionType + +> **sessionType**: [`SessionType`](../../../sdk-browser/index/SessionType/readme) + +Defined in: core/dist/\_\_types\_\_/base.d.ts:107 diff --git a/generated-docs/sdks/react-wallet-kit/index/SessionKey/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/SessionKey/readme.mdx new file mode 100644 index 000000000..394451fe1 --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/SessionKey/readme.mdx @@ -0,0 +1,16 @@ +--- +title: "SessionKey" +mode: wide +--- + +# Enumeration: SessionKey + +Defined in: core/dist/\_\_types\_\_/base.d.ts:232 + +## Enumeration Members + +### DefaultSessionkey + +> **DefaultSessionkey**: `"@turnkey/session/v3"` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:233 diff --git a/generated-docs/sdks/react-wallet-kit/index/SignIntent/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/SignIntent/readme.mdx new file mode 100644 index 000000000..a790d0e0c --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/SignIntent/readme.mdx @@ -0,0 +1,32 @@ +--- +title: "SignIntent" +mode: wide +--- + +# Enumeration: SignIntent + +Defined in: core/dist/\_\_types\_\_/base.d.ts:345 + +## Enumeration Members + +### SignAndSendTransaction + +> **SignAndSendTransaction**: `"sign_and_send"` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:348 + +*** + +### SignMessage + +> **SignMessage**: `"sign_message"` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:346 + +*** + +### SignTransaction + +> **SignTransaction**: `"sign_transaction"` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:347 diff --git a/generated-docs/sdks/react-wallet-kit/index/SignUpBody/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/SignUpBody/readme.mdx new file mode 100644 index 000000000..3cff58589 --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/SignUpBody/readme.mdx @@ -0,0 +1,126 @@ +--- +title: "SignUpBody" +mode: wide +--- + +# Type Alias: SignUpBody + +> **SignUpBody** = `object` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:181 + +## Properties + +### apiKeys? + +> `optional` **apiKeys**: `object`[] + +Defined in: core/dist/\_\_types\_\_/base.d.ts:193 + +#### apiKeyName + +> **apiKeyName**: `string` + +#### curveType? + +> `optional` **curveType**: [`v1ApiKeyCurve`](../../../_turnkey/sdk-types/v1ApiKeyCurve/readme) + +#### expirationSeconds + +> **expirationSeconds**: `string` + +#### publicKey + +> **publicKey**: `string` + +*** + +### authenticators? + +> `optional` **authenticators**: `object`[] + +Defined in: core/dist/\_\_types\_\_/base.d.ts:186 + +#### attestation + +> **attestation**: [`v1Attestation`](../../../_turnkey/sdk-types/v1Attestation/readme) + +#### authenticatorName + +> **authenticatorName**: `string` + +#### challenge + +> **challenge**: `string` + +*** + +### customWallet? + +> `optional` **customWallet**: `object` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:199 + +#### walletAccounts + +> **walletAccounts**: [`WalletAccountParams`](../WalletAccountParams/readme)[] + +#### walletName + +> **walletName**: `string` + +*** + +### oauthProviders? + +> `optional` **oauthProviders**: [`v1OauthProviderParams`](../../../_turnkey/sdk-types/v1OauthProviderParams/readme)[] + +Defined in: core/dist/\_\_types\_\_/base.d.ts:203 + +*** + +### subOrgName + +> **subOrgName**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:183 + +*** + +### userEmail? + +> `optional` **userEmail**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:184 + +*** + +### userName + +> **userName**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:182 + +*** + +### userPhoneNumber? + +> `optional` **userPhoneNumber**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:191 + +*** + +### userTag? + +> `optional` **userTag**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:185 + +*** + +### verificationToken? + +> `optional` **verificationToken**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:192 diff --git a/generated-docs/sdks/react-wallet-kit/index/SolanaChainInfo/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/SolanaChainInfo/readme.mdx new file mode 100644 index 000000000..6b5a77dbc --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/SolanaChainInfo/readme.mdx @@ -0,0 +1,18 @@ +--- +title: "SolanaChainInfo" +mode: wide +--- + +# Type Alias: SolanaChainInfo + +> **SolanaChainInfo** = `object` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:326 + +## Properties + +### namespace + +> **namespace**: [`Solana`](../Chain/readme#solana) + +Defined in: core/dist/\_\_types\_\_/base.d.ts:327 diff --git a/generated-docs/sdks/react-wallet-kit/index/SolanaWalletInterface/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/SolanaWalletInterface/readme.mdx new file mode 100644 index 000000000..e63366f74 --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/SolanaWalletInterface/readme.mdx @@ -0,0 +1,167 @@ +--- +title: "SolanaWalletInterface" +mode: wide +--- + +# Interface: SolanaWalletInterface + +Defined in: core/dist/\_\_types\_\_/base.d.ts:377 + +Solana wallets can directly access the public key without needing a signed message. + SolanaWalletInterface + +## Extends + +- [`BaseWalletInterface`](../BaseWalletInterface/readme) + +## Properties + +### connectWalletAccount() + +> **connectWalletAccount**: (`provider`) => `Promise`\<`void`\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:366 + +#### Parameters + +##### provider + +[`WalletProvider`](../WalletProvider/readme) + +#### Returns + +`Promise`\<`void`\> + +#### Inherited from + +[`BaseWalletInterface`](../BaseWalletInterface/readme).[`connectWalletAccount`](../BaseWalletInterface/readme#connectwalletaccount) + +*** + +### disconnectWalletAccount() + +> **disconnectWalletAccount**: (`provider`) => `Promise`\<`void`\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:367 + +#### Parameters + +##### provider + +[`WalletProvider`](../WalletProvider/readme) + +#### Returns + +`Promise`\<`void`\> + +#### Inherited from + +[`BaseWalletInterface`](../BaseWalletInterface/readme).[`disconnectWalletAccount`](../BaseWalletInterface/readme#disconnectwalletaccount) + +*** + +### getProviders() + +> **getProviders**: () => `Promise`\<[`WalletProvider`](../WalletProvider/readme)[]\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:365 + +#### Returns + +`Promise`\<[`WalletProvider`](../WalletProvider/readme)[]\> + +#### Inherited from + +[`BaseWalletInterface`](../BaseWalletInterface/readme).[`getProviders`](../BaseWalletInterface/readme#getproviders) + +*** + +### getPublicKey() + +> **getPublicKey**: (`provider`) => `Promise`\<`string`\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:364 + +Returns the public key, which is the ED25519 hex encoded public key from your Solana wallet public key. + +#### Parameters + +##### provider + +[`WalletProvider`](../WalletProvider/readme) + +#### Returns + +`Promise`\<`string`\> + +#### Inherited from + +[`BaseWalletInterface`](../BaseWalletInterface/readme).[`getPublicKey`](../BaseWalletInterface/readme#getpublickey) + +*** + +### interfaceType + +> **interfaceType**: [`Solana`](../WalletInterfaceType/readme#solana) + +Defined in: core/dist/\_\_types\_\_/base.d.ts:378 + +#### Overrides + +[`BaseWalletInterface`](../BaseWalletInterface/readme).[`interfaceType`](../BaseWalletInterface/readme#interfacetype) + +*** + +### sign() + +> **sign**: (`message`, `provider`, `intent`) => `Promise`\<`string`\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:363 + +#### Parameters + +##### message + +`string` + +##### provider + +[`WalletProvider`](../WalletProvider/readme) + +##### intent + +[`SignIntent`](../SignIntent/readme) + +#### Returns + +`Promise`\<`string`\> + +#### Inherited from + +[`BaseWalletInterface`](../BaseWalletInterface/readme).[`sign`](../BaseWalletInterface/readme#sign) + +*** + +### switchChain()? + +> `optional` **switchChain**: (`provider`, `chainOrId`) => `Promise`\<`void`\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:368 + +#### Parameters + +##### provider + +[`WalletProvider`](../WalletProvider/readme) + +##### chainOrId + +`string` | [`SwitchableChain`](../SwitchableChain/readme) + +#### Returns + +`Promise`\<`void`\> + +#### Inherited from + +[`BaseWalletInterface`](../BaseWalletInterface/readme).[`switchChain`](../BaseWalletInterface/readme#switchchain) diff --git a/generated-docs/sdks/react-wallet-kit/index/StamperType/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/StamperType/readme.mdx new file mode 100644 index 000000000..4b5bb2275 --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/StamperType/readme.mdx @@ -0,0 +1,32 @@ +--- +title: "StamperType" +mode: wide +--- + +# Enumeration: StamperType + +Defined in: core/dist/\_\_types\_\_/base.d.ts:213 + +## Enumeration Members + +### ApiKey + +> **ApiKey**: `"api-key"` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:214 + +*** + +### Passkey + +> **Passkey**: `"passkey"` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:215 + +*** + +### Wallet + +> **Wallet**: `"wallet"` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:216 diff --git a/generated-docs/sdks/react-wallet-kit/index/StorageBase/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/StorageBase/readme.mdx new file mode 100644 index 000000000..30bb8977e --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/StorageBase/readme.mdx @@ -0,0 +1,190 @@ +--- +title: "StorageBase" +mode: wide +--- + +# Interface: StorageBase + +Defined in: core/dist/\_\_types\_\_/base.d.ts:235 + +## Methods + +### clearAllSessions() + +> **clearAllSessions**(): `Promise`\<`void`\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:246 + +#### Returns + +`Promise`\<`void`\> + +*** + +### clearSession() + +> **clearSession**(`sessionKey`): `Promise`\<`void`\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:245 + +#### Parameters + +##### sessionKey + +`string` + +#### Returns + +`Promise`\<`void`\> + +*** + +### getActiveSession() + +> **getActiveSession**(): `Promise`\<`undefined` \| [`Session`](../../../sdk-browser/index/Session/readme)\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:243 + +#### Returns + +`Promise`\<`undefined` \| [`Session`](../../../sdk-browser/index/Session/readme)\> + +*** + +### getActiveSessionKey() + +> **getActiveSessionKey**(): `Promise`\<`undefined` \| `string`\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:242 + +#### Returns + +`Promise`\<`undefined` \| `string`\> + +*** + +### getSession() + +> **getSession**(`sessionKey?`): `Promise`\<`undefined` \| [`Session`](../../../sdk-browser/index/Session/readme)\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:241 + +#### Parameters + +##### sessionKey? + +`string` + +#### Returns + +`Promise`\<`undefined` \| [`Session`](../../../sdk-browser/index/Session/readme)\> + +*** + +### getStorageValue() + +> **getStorageValue**(`sessionKey`): `Promise`\<`any`\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:236 + +#### Parameters + +##### sessionKey + +`string` + +#### Returns + +`Promise`\<`any`\> + +*** + +### listSessionKeys() + +> **listSessionKeys**(): `Promise`\<`string`[]\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:244 + +#### Returns + +`Promise`\<`string`[]\> + +*** + +### removeStorageValue() + +> **removeStorageValue**(`sessionKey`): `Promise`\<`void`\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:239 + +#### Parameters + +##### sessionKey + +`string` + +#### Returns + +`Promise`\<`void`\> + +*** + +### setActiveSessionKey() + +> **setActiveSessionKey**(`sessionKey`): `Promise`\<`void`\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:238 + +#### Parameters + +##### sessionKey + +`string` + +#### Returns + +`Promise`\<`void`\> + +*** + +### setStorageValue() + +> **setStorageValue**(`sessionKey`, `storageValue`): `Promise`\<`void`\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:237 + +#### Parameters + +##### sessionKey + +`string` + +##### storageValue + +`any` + +#### Returns + +`Promise`\<`void`\> + +*** + +### storeSession() + +> **storeSession**(`session`, `sessionKey?`): `Promise`\<`void`\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:240 + +#### Parameters + +##### session + +`string` + +##### sessionKey? + +`string` + +#### Returns + +`Promise`\<`void`\> diff --git a/generated-docs/sdks/react-wallet-kit/index/SubOrganization/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/SubOrganization/readme.mdx new file mode 100644 index 000000000..6cc741acb --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/SubOrganization/readme.mdx @@ -0,0 +1,24 @@ +--- +title: "SubOrganization" +mode: wide +--- + +# Interface: SubOrganization + +Defined in: core/dist/\_\_types\_\_/base.d.ts:50 + +## Properties + +### organizationId + +> **organizationId**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:51 + +*** + +### organizationName + +> **organizationName**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:52 diff --git a/generated-docs/sdks/react-wallet-kit/index/SwitchableChain/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/SwitchableChain/readme.mdx new file mode 100644 index 000000000..3f4e7127d --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/SwitchableChain/readme.mdx @@ -0,0 +1,70 @@ +--- +title: "SwitchableChain" +mode: wide +--- + +# Type Alias: SwitchableChain + +> **SwitchableChain** = `object` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:310 + +## Properties + +### blockExplorerUrls? + +> `optional` **blockExplorerUrls**: `string`[] + +Defined in: core/dist/\_\_types\_\_/base.d.ts:314 + +*** + +### iconUrls? + +> `optional` **iconUrls**: `string`[] + +Defined in: core/dist/\_\_types\_\_/base.d.ts:315 + +*** + +### id + +> **id**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:311 + +*** + +### name + +> **name**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:312 + +*** + +### nativeCurrency + +> **nativeCurrency**: `object` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:316 + +#### decimals + +> **decimals**: `number` + +#### name + +> **name**: `string` + +#### symbol + +> **symbol**: `string` + +*** + +### rpcUrls + +> **rpcUrls**: `string`[] + +Defined in: core/dist/\_\_types\_\_/base.d.ts:313 diff --git a/generated-docs/sdks/react-wallet-kit/index/TActivityPollerConfig/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/TActivityPollerConfig/readme.mdx new file mode 100644 index 000000000..b2ef7e81b --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/TActivityPollerConfig/readme.mdx @@ -0,0 +1,26 @@ +--- +title: "TActivityPollerConfig" +mode: wide +--- + +# Type Alias: TActivityPollerConfig + +> **TActivityPollerConfig** = `object` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:46 + +## Properties + +### intervalMs + +> **intervalMs**: `number` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:47 + +*** + +### numRetries + +> **numRetries**: `number` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:48 diff --git a/generated-docs/sdks/react-wallet-kit/index/THttpConfig/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/THttpConfig/readme.mdx new file mode 100644 index 000000000..d3e39623d --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/THttpConfig/readme.mdx @@ -0,0 +1,18 @@ +--- +title: "THttpConfig" +mode: wide +--- + +# Type Alias: THttpConfig + +> **THttpConfig** = `object` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:25 + +## Properties + +### baseUrl + +> **baseUrl**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:26 diff --git a/generated-docs/sdks/react-wallet-kit/index/TPasskeyStamperConfig/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/TPasskeyStamperConfig/readme.mdx new file mode 100644 index 000000000..71aadf545 --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/TPasskeyStamperConfig/readme.mdx @@ -0,0 +1,74 @@ +--- +title: "TPasskeyStamperConfig" +mode: wide +--- + +# Type Alias: TPasskeyStamperConfig + +> **TPasskeyStamperConfig** = `object` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:253 + +## Properties + +### allowCredentials? + +> `optional` **allowCredentials**: `PublicKeyCredentialDescriptor`[] + +Defined in: core/dist/\_\_types\_\_/base.d.ts:257 + +*** + +### extensions? + +> `optional` **extensions**: `Record`\<`string`, `unknown`\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:261 + +*** + +### rpId? + +> `optional` **rpId**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:254 + +*** + +### rpName? + +> `optional` **rpName**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:258 + +*** + +### timeout? + +> `optional` **timeout**: `number` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:255 + +*** + +### userVerification? + +> `optional` **userVerification**: `UserVerificationRequirement` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:256 + +*** + +### withPlatformKey? + +> `optional` **withPlatformKey**: `boolean` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:260 + +*** + +### withSecurityKey? + +> `optional` **withSecurityKey**: `boolean` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:259 diff --git a/generated-docs/sdks/react-wallet-kit/index/TStamp/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/TStamp/readme.mdx new file mode 100644 index 000000000..9cb2951ba --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/TStamp/readme.mdx @@ -0,0 +1,26 @@ +--- +title: "TStamp" +mode: wide +--- + +# Type Alias: TStamp + +> **TStamp** = `object` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:18 + +## Properties + +### stampHeaderName + +> **stampHeaderName**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:19 + +*** + +### stampHeaderValue + +> **stampHeaderValue**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:20 diff --git a/generated-docs/sdks/react-wallet-kit/index/TStamper/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/TStamper/readme.mdx new file mode 100644 index 000000000..6037af0c3 --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/TStamper/readme.mdx @@ -0,0 +1,26 @@ +--- +title: "TStamper" +mode: wide +--- + +# Interface: TStamper + +Defined in: core/dist/\_\_types\_\_/base.d.ts:22 + +## Properties + +### stamp() + +> **stamp**: (`input`) => `Promise`\<[`TStamp`](../TStamp/readme)\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:23 + +#### Parameters + +##### input + +`string` + +#### Returns + +`Promise`\<[`TStamp`](../TStamp/readme)\> diff --git a/generated-docs/sdks/react-wallet-kit/index/TWalletManagerConfig/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/TWalletManagerConfig/readme.mdx new file mode 100644 index 000000000..4f537b1d1 --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/TWalletManagerConfig/readme.mdx @@ -0,0 +1,90 @@ +--- +title: "TWalletManagerConfig" +mode: wide +--- + +# Type Alias: TWalletManagerConfig + +> **TWalletManagerConfig** = `object` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:265 + +## Properties + +### chains + +> **chains**: `object` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:270 + +#### ethereum? + +> `optional` **ethereum**: `object` + +##### ethereum.native? + +> `optional` **native**: `boolean` + +##### ethereum.walletConnectNamespaces? + +> `optional` **walletConnectNamespaces**: `EvmNamespace`[] + +#### solana? + +> `optional` **solana**: `object` + +##### solana.native? + +> `optional` **native**: `boolean` + +##### solana.walletConnectNamespaces? + +> `optional` **walletConnectNamespaces**: `SolNamespace`[] + +*** + +### features? + +> `optional` **features**: `object` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:266 + +#### auth? + +> `optional` **auth**: `boolean` + +#### connecting? + +> `optional` **connecting**: `boolean` + +*** + +### walletConnect? + +> `optional` **walletConnect**: `object` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:280 + +#### appMetadata + +> **appMetadata**: `object` + +##### appMetadata.description + +> **description**: `string` + +##### appMetadata.icons + +> **icons**: `string`[] + +##### appMetadata.name + +> **name**: `string` + +##### appMetadata.url + +> **url**: `string` + +#### projectId + +> **projectId**: `string` diff --git a/generated-docs/sdks/react-wallet-kit/index/TurnkeyHttpClientConfig/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/TurnkeyHttpClientConfig/readme.mdx new file mode 100644 index 000000000..15bdeb2a8 --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/TurnkeyHttpClientConfig/readme.mdx @@ -0,0 +1,88 @@ +--- +title: "TurnkeyHttpClientConfig" +mode: wide +--- + +# Interface: TurnkeyHttpClientConfig + +Defined in: core/dist/\_\_types\_\_/base.d.ts:67 + +## Properties + +### activityPoller? + +> `optional` **activityPoller**: [`TActivityPollerConfig`](../TActivityPollerConfig/readme) + +Defined in: core/dist/\_\_types\_\_/base.d.ts:72 + +*** + +### apiBaseUrl + +> **apiBaseUrl**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:68 + +*** + +### apiKeyStamper? + +> `optional` **apiKeyStamper**: [`TStamper`](../TStamper/readme) + +Defined in: core/dist/\_\_types\_\_/base.d.ts:73 + +*** + +### authProxyConfigId? + +> `optional` **authProxyConfigId**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:71 + +*** + +### authProxyUrl? + +> `optional` **authProxyUrl**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:70 + +*** + +### organizationId + +> **organizationId**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:69 + +*** + +### passkeyStamper? + +> `optional` **passkeyStamper**: [`TStamper`](../TStamper/readme) + +Defined in: core/dist/\_\_types\_\_/base.d.ts:74 + +*** + +### readOnlySession? + +> `optional` **readOnlySession**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:77 + +*** + +### storageManager? + +> `optional` **storageManager**: [`StorageBase`](../StorageBase/readme) + +Defined in: core/dist/\_\_types\_\_/base.d.ts:76 + +*** + +### walletStamper? + +> `optional` **walletStamper**: [`TStamper`](../TStamper/readme) + +Defined in: core/dist/\_\_types\_\_/base.d.ts:75 diff --git a/generated-docs/sdks/react-wallet-kit/index/TurnkeyProvider/README.mdx b/generated-docs/sdks/react-wallet-kit/index/TurnkeyProvider/README.mdx new file mode 100644 index 000000000..00ba7fc87 --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/TurnkeyProvider/README.mdx @@ -0,0 +1,30 @@ +--- +title: "TurnkeyProvider" +mode: wide +--- + +# Function: TurnkeyProvider() + +> **TurnkeyProvider**(`__namedParameters`): `Element` + +Defined in: [react-wallet-kit/src/providers/TurnkeyProvider.tsx:9](https://github.com/tkhq/sdk/blob/main/packages/react-wallet-kit/src/providers/TurnkeyProvider.tsx#L9) + +## Parameters + +### \_\_namedParameters + +#### callbacks? + +`TurnkeyCallbacks` + +#### children + +`ReactNode` + +#### config + +`TurnkeyProviderConfig` + +## Returns + +`Element` diff --git a/generated-docs/sdks/react-wallet-kit/index/TurnkeyRequestError/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/TurnkeyRequestError/readme.mdx new file mode 100644 index 000000000..3884134dd --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/TurnkeyRequestError/readme.mdx @@ -0,0 +1,50 @@ +--- +title: "TurnkeyRequestError" +mode: wide +--- + +# Class: TurnkeyRequestError + +Defined in: core/dist/\_\_types\_\_/base.d.ts:28 + +## Extends + +- `Error` + +## Constructors + +### Constructor + +> **new TurnkeyRequestError**(`input`): `TurnkeyRequestError` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:31 + +#### Parameters + +##### input + +[`GrpcStatus`](../GrpcStatus/readme) + +#### Returns + +`TurnkeyRequestError` + +#### Overrides + +`Error.constructor` + +## Properties + +### code + +> **code**: `number` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:30 + +*** + +### details + +> **details**: `null` \| `any`[] + +Defined in: core/dist/\_\_types\_\_/base.d.ts:29 diff --git a/generated-docs/sdks/react-wallet-kit/index/TurnkeySDKClientConfig/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/TurnkeySDKClientConfig/readme.mdx new file mode 100644 index 000000000..6f2451cac --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/TurnkeySDKClientConfig/readme.mdx @@ -0,0 +1,56 @@ +--- +title: "TurnkeySDKClientConfig" +mode: wide +--- + +# Interface: TurnkeySDKClientConfig + +Defined in: core/dist/\_\_types\_\_/base.d.ts:79 + +## Properties + +### apiBaseUrl? + +> `optional` **apiBaseUrl**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:80 + +*** + +### authProxyConfigId? + +> `optional` **authProxyConfigId**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:82 + +*** + +### authProxyUrl? + +> `optional` **authProxyUrl**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:81 + +*** + +### organizationId + +> **organizationId**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:83 + +*** + +### passkeyConfig? + +> `optional` **passkeyConfig**: [`TPasskeyStamperConfig`](../TPasskeyStamperConfig/readme) + +Defined in: core/dist/\_\_types\_\_/base.d.ts:84 + +*** + +### walletConfig? + +> `optional` **walletConfig**: [`TWalletManagerConfig`](../TWalletManagerConfig/readme) + +Defined in: core/dist/\_\_types\_\_/base.d.ts:85 diff --git a/generated-docs/sdks/react-wallet-kit/index/User/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/User/readme.mdx new file mode 100644 index 000000000..e51f2ee9e --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/User/readme.mdx @@ -0,0 +1,10 @@ +--- +title: "User" +mode: wide +--- + +# Type Alias: User + +> **User** = [`v1User`](../../../_turnkey/sdk-types/v1User/readme) + +Defined in: core/dist/\_\_types\_\_/base.d.ts:120 diff --git a/generated-docs/sdks/react-wallet-kit/index/Wallet/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/Wallet/readme.mdx new file mode 100644 index 000000000..e41d90c11 --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/Wallet/readme.mdx @@ -0,0 +1,10 @@ +--- +title: "Wallet" +mode: wide +--- + +# Type Alias: Wallet + +> **Wallet** = [`EmbeddedWallet`](../EmbeddedWallet/readme) \| [`ConnectedWallet`](../ConnectedWallet/readme) + +Defined in: core/dist/\_\_types\_\_/base.d.ts:148 diff --git a/generated-docs/sdks/react-wallet-kit/index/WalletAccount/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/WalletAccount/readme.mdx new file mode 100644 index 000000000..dbd64f683 --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/WalletAccount/readme.mdx @@ -0,0 +1,10 @@ +--- +title: "WalletAccount" +mode: wide +--- + +# Type Alias: WalletAccount + +> **WalletAccount** = [`EmbeddedWalletAccount`](../EmbeddedWalletAccount/readme) \| [`ConnectedWalletAccount`](../ConnectedWalletAccount/readme) + +Defined in: core/dist/\_\_types\_\_/base.d.ts:139 diff --git a/generated-docs/sdks/react-wallet-kit/index/WalletAccountParams/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/WalletAccountParams/readme.mdx new file mode 100644 index 000000000..c1a5a009d --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/WalletAccountParams/readme.mdx @@ -0,0 +1,10 @@ +--- +title: "WalletAccountParams" +mode: wide +--- + +# Type Alias: WalletAccountParams + +> **WalletAccountParams** = [`v1WalletAccountParams`](../../../_turnkey/sdk-types/v1WalletAccountParams/readme) + +Defined in: core/dist/\_\_types\_\_/base.d.ts:149 diff --git a/generated-docs/sdks/react-wallet-kit/index/WalletConnectInterface/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/WalletConnectInterface/readme.mdx new file mode 100644 index 000000000..09d330db3 --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/WalletConnectInterface/readme.mdx @@ -0,0 +1,191 @@ +--- +title: "WalletConnectInterface" +mode: wide +--- + +# Interface: WalletConnectInterface + +Defined in: core/dist/\_\_types\_\_/base.d.ts:394 + +Base interface for wallet functionalities common across different blockchain chains. + BaseWalletInterface + +## Extends + +- [`BaseWalletInterface`](../BaseWalletInterface/readme) + +## Properties + +### connectWalletAccount() + +> **connectWalletAccount**: (`provider`) => `Promise`\<`void`\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:366 + +#### Parameters + +##### provider + +[`WalletProvider`](../WalletProvider/readme) + +#### Returns + +`Promise`\<`void`\> + +#### Inherited from + +[`BaseWalletInterface`](../BaseWalletInterface/readme).[`connectWalletAccount`](../BaseWalletInterface/readme#connectwalletaccount) + +*** + +### disconnectWalletAccount() + +> **disconnectWalletAccount**: (`provider`) => `Promise`\<`void`\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:367 + +#### Parameters + +##### provider + +[`WalletProvider`](../WalletProvider/readme) + +#### Returns + +`Promise`\<`void`\> + +#### Inherited from + +[`BaseWalletInterface`](../BaseWalletInterface/readme).[`disconnectWalletAccount`](../BaseWalletInterface/readme#disconnectwalletaccount) + +*** + +### getProviders() + +> **getProviders**: () => `Promise`\<[`WalletProvider`](../WalletProvider/readme)[]\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:365 + +#### Returns + +`Promise`\<[`WalletProvider`](../WalletProvider/readme)[]\> + +#### Inherited from + +[`BaseWalletInterface`](../BaseWalletInterface/readme).[`getProviders`](../BaseWalletInterface/readme#getproviders) + +*** + +### getPublicKey() + +> **getPublicKey**: (`provider`) => `Promise`\<`string`\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:364 + +Retrieves the public key as a string. + +#### Parameters + +##### provider + +[`WalletProvider`](../WalletProvider/readme) + +#### Returns + +`Promise`\<`string`\> + +#### Inherited from + +[`BaseWalletInterface`](../BaseWalletInterface/readme).[`getPublicKey`](../BaseWalletInterface/readme#getpublickey) + +*** + +### init() + +> **init**: (`opts`) => `Promise`\<`void`\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:396 + +#### Parameters + +##### opts + +###### ethereumNamespaces + +`string`[] + +###### solanaNamespaces + +`string`[] + +#### Returns + +`Promise`\<`void`\> + +*** + +### interfaceType + +> **interfaceType**: [`WalletConnect`](../WalletInterfaceType/readme#walletconnect) + +Defined in: core/dist/\_\_types\_\_/base.d.ts:395 + +#### Overrides + +[`BaseWalletInterface`](../BaseWalletInterface/readme).[`interfaceType`](../BaseWalletInterface/readme#interfacetype) + +*** + +### sign() + +> **sign**: (`message`, `provider`, `intent`) => `Promise`\<`string`\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:363 + +#### Parameters + +##### message + +`string` + +##### provider + +[`WalletProvider`](../WalletProvider/readme) + +##### intent + +[`SignIntent`](../SignIntent/readme) + +#### Returns + +`Promise`\<`string`\> + +#### Inherited from + +[`BaseWalletInterface`](../BaseWalletInterface/readme).[`sign`](../BaseWalletInterface/readme#sign) + +*** + +### switchChain()? + +> `optional` **switchChain**: (`provider`, `chainOrId`) => `Promise`\<`void`\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:368 + +#### Parameters + +##### provider + +[`WalletProvider`](../WalletProvider/readme) + +##### chainOrId + +`string` | [`SwitchableChain`](../SwitchableChain/readme) + +#### Returns + +`Promise`\<`void`\> + +#### Inherited from + +[`BaseWalletInterface`](../BaseWalletInterface/readme).[`switchChain`](../BaseWalletInterface/readme#switchchain) diff --git a/generated-docs/sdks/react-wallet-kit/index/WalletConnectProvider/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/WalletConnectProvider/readme.mdx new file mode 100644 index 000000000..81809f22c --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/WalletConnectProvider/readme.mdx @@ -0,0 +1,32 @@ +--- +title: "WalletConnectProvider" +mode: wide +--- + +# Interface: WalletConnectProvider + +Defined in: core/dist/\_\_types\_\_/base.d.ts:330 + +## Methods + +### request() + +> **request**(`args`): `Promise`\<`unknown`\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:331 + +#### Parameters + +##### args + +###### method + +`string` + +###### params? + +`any`[] + +#### Returns + +`Promise`\<`unknown`\> diff --git a/generated-docs/sdks/react-wallet-kit/index/WalletInterface/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/WalletInterface/readme.mdx new file mode 100644 index 000000000..3d3a192d4 --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/WalletInterface/readme.mdx @@ -0,0 +1,12 @@ +--- +title: "WalletInterface" +mode: wide +--- + +# Type Alias: WalletInterface + +> **WalletInterface** = [`SolanaWalletInterface`](../SolanaWalletInterface/readme) \| [`EthereumWalletInterface`](../EthereumWalletInterface/readme) \| [`WalletConnectInterface`](../WalletConnectInterface/readme) + +Defined in: core/dist/\_\_types\_\_/base.d.ts:405 + +Union type for wallet interfaces, supporting both Solana and Ethereum wallets. diff --git a/generated-docs/sdks/react-wallet-kit/index/WalletInterfaceType/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/WalletInterfaceType/readme.mdx new file mode 100644 index 000000000..52ceb1073 --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/WalletInterfaceType/readme.mdx @@ -0,0 +1,32 @@ +--- +title: "WalletInterfaceType" +mode: wide +--- + +# Enumeration: WalletInterfaceType + +Defined in: core/dist/\_\_types\_\_/base.d.ts:350 + +## Enumeration Members + +### Ethereum + +> **Ethereum**: `"ethereum"` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:352 + +*** + +### Solana + +> **Solana**: `"solana"` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:351 + +*** + +### WalletConnect + +> **WalletConnect**: `"wallet_connect"` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:353 diff --git a/generated-docs/sdks/react-wallet-kit/index/WalletManagerBase/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/WalletManagerBase/readme.mdx new file mode 100644 index 000000000..5414fd50e --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/WalletManagerBase/readme.mdx @@ -0,0 +1,42 @@ +--- +title: "WalletManagerBase" +mode: wide +--- + +# Interface: WalletManagerBase + +Defined in: core/dist/\_\_types\_\_/base.d.ts:248 + +## Properties + +### connector? + +> `optional` **connector**: `CrossPlatformWalletConnector` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:251 + +*** + +### getProviders() + +> **getProviders**: (`chain?`) => `Promise`\<[`WalletProvider`](../WalletProvider/readme)[]\> + +Defined in: core/dist/\_\_types\_\_/base.d.ts:249 + +#### Parameters + +##### chain? + +[`Chain`](../Chain/readme) + +#### Returns + +`Promise`\<[`WalletProvider`](../WalletProvider/readme)[]\> + +*** + +### stamper? + +> `optional` **stamper**: `CrossPlatformWalletStamper` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:250 diff --git a/generated-docs/sdks/react-wallet-kit/index/WalletProvider/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/WalletProvider/readme.mdx new file mode 100644 index 000000000..86935951d --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/WalletProvider/readme.mdx @@ -0,0 +1,56 @@ +--- +title: "WalletProvider" +mode: wide +--- + +# Interface: WalletProvider + +Defined in: core/dist/\_\_types\_\_/base.d.ts:337 + +## Properties + +### chainInfo + +> **chainInfo**: [`ChainInfo`](../ChainInfo/readme) + +Defined in: core/dist/\_\_types\_\_/base.d.ts:339 + +*** + +### connectedAddresses + +> **connectedAddresses**: `string`[] + +Defined in: core/dist/\_\_types\_\_/base.d.ts:342 + +*** + +### info + +> **info**: [`WalletProviderInfo`](../WalletProviderInfo/readme) + +Defined in: core/dist/\_\_types\_\_/base.d.ts:340 + +*** + +### interfaceType + +> **interfaceType**: [`WalletInterfaceType`](../WalletInterfaceType/readme) + +Defined in: core/dist/\_\_types\_\_/base.d.ts:338 + +*** + +### provider + +> **provider**: [`WalletRpcProvider`](../WalletRpcProvider/readme) + +Defined in: core/dist/\_\_types\_\_/base.d.ts:341 + +*** + +### uri? + +> `optional` **uri**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:343 diff --git a/generated-docs/sdks/react-wallet-kit/index/WalletProviderInfo/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/WalletProviderInfo/readme.mdx new file mode 100644 index 000000000..208825fb7 --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/WalletProviderInfo/readme.mdx @@ -0,0 +1,40 @@ +--- +title: "WalletProviderInfo" +mode: wide +--- + +# Interface: WalletProviderInfo + +Defined in: core/dist/\_\_types\_\_/base.d.ts:300 + +## Properties + +### icon? + +> `optional` **icon**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:303 + +*** + +### name + +> **name**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:301 + +*** + +### rdns? + +> `optional` **rdns**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:304 + +*** + +### uuid? + +> `optional` **uuid**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:302 diff --git a/generated-docs/sdks/react-wallet-kit/index/WalletRpcProvider/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/WalletRpcProvider/readme.mdx new file mode 100644 index 000000000..67f1c6802 --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/WalletRpcProvider/readme.mdx @@ -0,0 +1,10 @@ +--- +title: "WalletRpcProvider" +mode: wide +--- + +# Type Alias: WalletRpcProvider + +> **WalletRpcProvider** = `EthereumProvider` \| `SolanaProvider` \| [`WalletConnectProvider`](../WalletConnectProvider/readme) + +Defined in: core/dist/\_\_types\_\_/base.d.ts:336 diff --git a/generated-docs/sdks/react-wallet-kit/index/WalletSource/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/WalletSource/readme.mdx new file mode 100644 index 000000000..437d3810f --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/WalletSource/readme.mdx @@ -0,0 +1,24 @@ +--- +title: "WalletSource" +mode: wide +--- + +# Enumeration: WalletSource + +Defined in: core/dist/\_\_types\_\_/base.d.ts:126 + +## Enumeration Members + +### Connected + +> **Connected**: `"connected"` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:128 + +*** + +### Embedded + +> **Embedded**: `"embedded"` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:127 diff --git a/generated-docs/sdks/react-wallet-kit/index/commandOverrideParams/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/commandOverrideParams/readme.mdx new file mode 100644 index 000000000..828e46536 --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/commandOverrideParams/readme.mdx @@ -0,0 +1,26 @@ +--- +title: "CommandOverrideParams" +mode: wide +--- + +# Type Alias: commandOverrideParams + +> **commandOverrideParams** = `object` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:90 + +## Properties + +### organizationId? + +> `optional` **organizationId**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:91 + +*** + +### timestampMs? + +> `optional` **timestampMs**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:92 diff --git a/generated-docs/sdks/react-wallet-kit/index/queryOverrideParams/readme.mdx b/generated-docs/sdks/react-wallet-kit/index/queryOverrideParams/readme.mdx new file mode 100644 index 000000000..43fdaa395 --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/queryOverrideParams/readme.mdx @@ -0,0 +1,18 @@ +--- +title: "QueryOverrideParams" +mode: wide +--- + +# Type Alias: queryOverrideParams + +> **queryOverrideParams** = `object` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:87 + +## Properties + +### organizationId? + +> `optional` **organizationId**: `string` + +Defined in: core/dist/\_\_types\_\_/base.d.ts:88 diff --git a/generated-docs/sdks/react-wallet-kit/index/useModal/README.mdx b/generated-docs/sdks/react-wallet-kit/index/useModal/README.mdx new file mode 100644 index 000000000..5c3353b29 --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/useModal/README.mdx @@ -0,0 +1,14 @@ +--- +title: "UseModal" +mode: wide +--- + +# Function: useModal() + +> **useModal**(): `ModalContextType` + +Defined in: [react-wallet-kit/src/providers/modal/Hook.tsx:6](https://github.com/tkhq/sdk/blob/main/packages/react-wallet-kit/src/providers/modal/Hook.tsx#L6) + +## Returns + +`ModalContextType` diff --git a/generated-docs/sdks/react-wallet-kit/index/useTurnkey/README.mdx b/generated-docs/sdks/react-wallet-kit/index/useTurnkey/README.mdx new file mode 100644 index 000000000..0461c8742 --- /dev/null +++ b/generated-docs/sdks/react-wallet-kit/index/useTurnkey/README.mdx @@ -0,0 +1,14 @@ +--- +title: "UseTurnkey" +mode: wide +--- + +# Function: useTurnkey() + +> **useTurnkey**(): [`ClientContextType`](../ClientContextType/readme) + +Defined in: [react-wallet-kit/src/providers/client/Hook.tsx:6](https://github.com/tkhq/sdk/blob/main/packages/react-wallet-kit/src/providers/client/Hook.tsx#L6) + +## Returns + +[`ClientContextType`](../ClientContextType/readme) diff --git a/generated-docs/sdks/sdk-js/README.mdx b/generated-docs/sdks/sdk-js/README.mdx new file mode 100644 index 000000000..97dde2a03 --- /dev/null +++ b/generated-docs/sdks/sdk-js/README.mdx @@ -0,0 +1,15 @@ +[**Documentation**](../README.mdx) + +*** + +[Documentation](../modules.mdx) / sdk-js + +# sdk-js + +## Documents + +- [docs](docs/README.mdx) + +## Modules + +- [index](index/README.mdx) diff --git a/generated-docs/sdks/sdk-js/docs/README.mdx b/generated-docs/sdks/sdk-js/docs/README.mdx new file mode 100644 index 000000000..ee197145d --- /dev/null +++ b/generated-docs/sdks/sdk-js/docs/README.mdx @@ -0,0 +1,5 @@ +[**Documentation**](../../README.mdx) + +*** + +[Documentation](../../modules.mdx) / [sdk-js](../README.mdx) / docs diff --git a/generated-docs/sdks/sdk-js/index/ApiKeyStamper/README.mdx b/generated-docs/sdks/sdk-js/index/ApiKeyStamper/README.mdx new file mode 100644 index 000000000..c1546f6ac --- /dev/null +++ b/generated-docs/sdks/sdk-js/index/ApiKeyStamper/README.mdx @@ -0,0 +1,71 @@ +[**Documentation**](../../../README.mdx) + +*** + +[Documentation](../../../modules.mdx) / [sdk-js](../../README.mdx) / [index](../README.mdx) / ApiKeyStamper + +# Class: ApiKeyStamper + +Defined in: api-key-stamper/dist/index.d.ts:19 + +Stamper to use with `@turnkey/http`'s `TurnkeyClient` + +## Constructors + +### Constructor + +> **new ApiKeyStamper**(`config`): `ApiKeyStamper` + +Defined in: api-key-stamper/dist/index.d.ts:23 + +#### Parameters + +##### config + +[`TApiKeyStamperConfig`](../TApiKeyStamperConfig/README.mdx) + +#### Returns + +`ApiKeyStamper` + +## Properties + +### apiPrivateKey + +> **apiPrivateKey**: `string` + +Defined in: api-key-stamper/dist/index.d.ts:21 + +*** + +### apiPublicKey + +> **apiPublicKey**: `string` + +Defined in: api-key-stamper/dist/index.d.ts:20 + +*** + +### runtimeOverride? + +> `optional` **runtimeOverride**: [`Runtime`](../../../api-key-stamper/index/Runtime/README.mdx) + +Defined in: api-key-stamper/dist/index.d.ts:22 + +## Methods + +### stamp() + +> **stamp**(`payload`): `Promise`\<\{ `stampHeaderName`: `string`; `stampHeaderValue`: `string`; \}\> + +Defined in: api-key-stamper/dist/index.d.ts:24 + +#### Parameters + +##### payload + +`string` + +#### Returns + +`Promise`\<\{ `stampHeaderName`: `string`; `stampHeaderValue`: `string`; \}\> diff --git a/generated-docs/sdks/sdk-js/index/README.mdx b/generated-docs/sdks/sdk-js/index/README.mdx new file mode 100644 index 000000000..816396a3a --- /dev/null +++ b/generated-docs/sdks/sdk-js/index/README.mdx @@ -0,0 +1,27 @@ +[**Documentation**](../../README.mdx) + +*** + +[Documentation](../../modules.mdx) / [sdk-js](../README.mdx) / index + +# index + +## Classes + +- [ApiKeyStamper](ApiKeyStamper/README.mdx) +- [TurnkeyClient](TurnkeyClient/README.mdx) +- [WebauthnStamper](WebauthnStamper/README.mdx) + +## Type Aliases + +- [TApiKeyStamperConfig](TApiKeyStamperConfig/README.mdx) +- [TurnkeyClientMethods](TurnkeyClientMethods/README.mdx) +- [TWebauthnStamperConfig](TWebauthnStamperConfig/README.mdx) + +## Variables + +- [signWithApiKey](signWithApiKey/README.mdx) + +## Functions + +- [generateWalletAccountsFromAddressFormat](generateWalletAccountsFromAddressFormat/README.mdx) diff --git a/generated-docs/sdks/sdk-js/index/TApiKeyStamperConfig/README.mdx b/generated-docs/sdks/sdk-js/index/TApiKeyStamperConfig/README.mdx new file mode 100644 index 000000000..54fb5d4cf --- /dev/null +++ b/generated-docs/sdks/sdk-js/index/TApiKeyStamperConfig/README.mdx @@ -0,0 +1,35 @@ +[**Documentation**](../../../README.mdx) + +*** + +[Documentation](../../../modules.mdx) / [sdk-js](../../README.mdx) / [index](../README.mdx) / TApiKeyStamperConfig + +# Type Alias: TApiKeyStamperConfig + +> **TApiKeyStamperConfig** = `object` + +Defined in: api-key-stamper/dist/index.d.ts:3 + +## Properties + +### apiPrivateKey + +> **apiPrivateKey**: `string` + +Defined in: api-key-stamper/dist/index.d.ts:5 + +*** + +### apiPublicKey + +> **apiPublicKey**: `string` + +Defined in: api-key-stamper/dist/index.d.ts:4 + +*** + +### runtimeOverride? + +> `optional` **runtimeOverride**: [`Runtime`](../../../api-key-stamper/index/Runtime/README.mdx) + +Defined in: api-key-stamper/dist/index.d.ts:6 diff --git a/generated-docs/sdks/sdk-js/index/TWebauthnStamperConfig/README.mdx b/generated-docs/sdks/sdk-js/index/TWebauthnStamperConfig/README.mdx new file mode 100644 index 000000000..fb937e186 --- /dev/null +++ b/generated-docs/sdks/sdk-js/index/TWebauthnStamperConfig/README.mdx @@ -0,0 +1,43 @@ +[**Documentation**](../../../README.mdx) + +*** + +[Documentation](../../../modules.mdx) / [sdk-js](../../README.mdx) / [index](../README.mdx) / TWebauthnStamperConfig + +# Type Alias: TWebauthnStamperConfig + +> **TWebauthnStamperConfig** = `object` + +Defined in: webauthn-stamper/dist/index.d.ts:2 + +## Properties + +### allowCredentials? + +> `optional` **allowCredentials**: `PublicKeyCredentialDescriptor`[] + +Defined in: webauthn-stamper/dist/index.d.ts:6 + +*** + +### rpId + +> **rpId**: `string` + +Defined in: webauthn-stamper/dist/index.d.ts:3 + +*** + +### timeout? + +> `optional` **timeout**: `number` + +Defined in: webauthn-stamper/dist/index.d.ts:4 + +*** + +### userVerification? + +> `optional` **userVerification**: `UserVerificationRequirement` + +Defined in: webauthn-stamper/dist/index.d.ts:5 diff --git a/generated-docs/sdks/sdk-js/index/TurnkeyClient/README.mdx b/generated-docs/sdks/sdk-js/index/TurnkeyClient/README.mdx new file mode 100644 index 000000000..b54f960b8 --- /dev/null +++ b/generated-docs/sdks/sdk-js/index/TurnkeyClient/README.mdx @@ -0,0 +1,2221 @@ +[**Documentation**](../../../README.mdx) + +*** + +[Documentation](../../../modules.mdx) / [sdk-js](../../README.mdx) / [index](../README.mdx) / TurnkeyClient + +# Class: TurnkeyClient + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:86](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L86) + +## Constructors + +### Constructor + +> **new TurnkeyClient**(`config`, `apiKeyStamper`?, `passkeyStamper`?, `walletManager`?): `TurnkeyClient` + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:95](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L95) + +#### Parameters + +##### config + +`TurnkeySDKClientConfig` + +##### apiKeyStamper? + +`CrossPlatformApiKeyStamper` + +##### passkeyStamper? + +`CrossPlatformPasskeyStamper` + +##### walletManager? + +`WalletManagerBase` + +#### Returns + +`TurnkeyClient` + +## Properties + +### config + +> **config**: `TurnkeySDKClientConfig` + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:87](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L87) + +*** + +### httpClient + +> **httpClient**: `TurnkeySDKClientBase` + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:88](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L88) + +## Methods + +### addOAuthProvider() + +> **addOAuthProvider**(`params`): `Promise`\<`string`[]\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:2142](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L2142) + +Adds an OAuth provider to the user. + +- This function adds an OAuth provider (e.g., Google, Apple) to the user account. +- If a userId is provided, it adds the provider for that specific user; otherwise, it uses the current session's userId. +- Automatically checks if an account already exists for the provided OIDC token and prevents duplicate associations. +- If the user's email is not set or not verified, attempts to update and verify the email using the email from the OIDC token. +- Handles session management and error reporting for the add provider flow. +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Parameters + +##### params + +###### oidcToken + +`string` + +The OIDC token for the OAuth provider. + +###### providerName + +`string` + +The name of the OAuth provider to add (e.g., "Google", "Apple"). + +###### stampWith? + +`StamperType` + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### userId? + +`string` + +user ID to add the provider for a specific user (defaults to current session's userId). + +#### Returns + +`Promise`\<`string`[]\> + +A promise that resolves to an array of provider IDs associated with the user. + +#### Throws + +If there is no active session, if the account already exists, or if there is an error adding the OAuth provider. + +*** + +### addPasskey() + +> **addPasskey**(`params`?): `Promise`\<`string`[]\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:2297](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L2297) + +Adds a new passkey authenticator for the user. + +- This function prompts the user to create a new passkey (WebAuthn/FIDO2) and adds it as an authenticator for the user. +- Handles both web and React Native environments, automatically selecting the appropriate passkey creation flow. +- If a userId is provided, the passkey is added for that specific user; otherwise, it uses the current session's userId. +- The passkey's name and display name can be customized; if not provided, defaults are generated. +- The resulting passkey attestation and challenge are registered with Turnkey as a new authenticator. +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Parameters + +##### params? + +###### displayName? + +`string` + +The display name of the passkey (defaults to the value of `name`). + +###### name? + +`string` + +The name of the passkey (defaults to "Turnkey Passkey-`timestamp`"). + +###### stampWith? + +`StamperType` + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### userId? + +`string` + +user ID to add the passkey for a specific user (defaults to the current session's userId). + +#### Returns + +`Promise`\<`string`[]\> + +A promise that resolves to an array of authenticator IDs for the newly added passkey(s). + +#### Throws + +If there is no active session, if passkey creation fails, or if there is an error adding the passkey. + +*** + +### clearAllSessions() + +> **clearAllSessions**(): `Promise`\<`void`\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:2806](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L2806) + +Clears all sessions and resets the active session state. + +- This function removes all session data from the client and persistent storage, including all associated key pairs. +- Iterates through all stored session keys, clearing each session and deleting its corresponding API key pair. +- After clearing, there will be no active session, and all session-related data will be removed from local storage. +- Throws an error if no sessions exist or if there is an error during the clearing process. + +#### Returns + +`Promise`\<`void`\> + +A promise that resolves when all sessions are successfully cleared. + +#### Throws + +If no sessions exist or if there is an error clearing all sessions. + +*** + +### clearSession() + +> **clearSession**(`params`?): `Promise`\<`void`\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:2772](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L2772) + +Clears the session associated with the specified session key, or the active session by default. + +- This function deletes the session and its associated key pair from storage. +- If a sessionKey is provided, it will clear the session under that key; otherwise, it will clear the default (active) session. +- Removes the session data from local storage and deletes the corresponding API key pair from the key store. +- Throws an error if the session does not exist or if there is an error during the clearing process. + +#### Parameters + +##### params? + +###### sessionKey? + +`string` + +session key to clear the session under (defaults to the default session key). + +#### Returns + +`Promise`\<`void`\> + +A promise that resolves when the session is successfully cleared. + +#### Throws + +If the session does not exist or if there is an error clearing the session. + +*** + +### clearUnusedKeyPairs() + +> **clearUnusedKeyPairs**(): `Promise`\<`void`\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:3027](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L3027) + +Clears any unused API key pairs from persistent storage. + +- This function scans all API key pairs stored in indexedDB and removes any key pairs that are not associated with a session in persistent storage. +- Ensures that only key pairs referenced by existing sessions are retained, preventing orphaned or stale key pairs from accumulating. +- Iterates through all stored session keys and builds a map of in-use public keys, then deletes any key pairs not present in this map. +- Intended to be called after session changes (e.g., login, logout, session replacement) to keep key storage clean and secure. + +#### Returns + +`Promise`\<`void`\> + +A promise that resolves when all unused key pairs are successfully cleared. + +#### Throws + +If there is an error listing, checking, or deleting unused key pairs. + +*** + +### completeOauth() + +> **completeOauth**(`params`): `Promise`\<`string`\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:1230](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L1230) + +Completes the OAuth authentication flow by either signing up or logging in the user, depending on whether a sub-organization already exists for the provided OIDC token. + +- This function first checks if there is an existing sub-organization associated with the OIDC token. +- If a sub-organization exists, it proceeds with the OAuth login flow. +- If no sub-organization exists, it creates a new sub-organization and completes the sign-up flow. +- Optionally accepts a custom OAuth provider name, session key, and additional sub-organization creation parameters. +- Handles session storage and management, and supports invalidating existing sessions if specified. + +#### Parameters + +##### params + +###### createSubOrgParams? + +`CreateSubOrgParams` + +parameters for sub-organization creation (e.g., authenticators, user metadata). + +###### invalidateExisting? + +`boolean` + +flag to invalidate existing sessions for the user. + +###### oidcToken + +`string` + +The OIDC token received after successful authentication with the OAuth provider. + +###### providerName? + +`string` + +name of the OAuth provider (defaults to a generated name with a timestamp). + +###### publicKey + +`string` + +The public key to use for authentication. Must be generated prior to calling this function. + +###### sessionKey? + +`string` + +session key to use for session creation (defaults to the default session key). + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to a signed JWT session token for the user. + +#### Throws + +If there is an error during the OAuth completion process, such as account lookup, sign-up, or login. + +*** + +### completeOtp() + +> **completeOtp**(`params`): `Promise`\<`string`\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:1147](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L1147) + +Completes the OTP authentication flow by verifying the OTP code and then either signing up or logging in the user. + +- This function first verifies the OTP code for the provided contact and OTP type. +- If the contact is not associated with an existing sub-organization, it will automatically create a new sub-organization and complete the sign-up flow. +- If the contact is already associated with a sub-organization, it will complete the login flow. +- Supports passing a custom public key for authentication, invalidating existing session, specifying a session key, and providing additional sub-organization creation parameters. +- Handles both email and SMS OTP types. + +#### Parameters + +##### params + +###### contact + +`string` + +The contact information for the user (e.g., email address or phone number). + +###### createSubOrgParams? + +`CreateSubOrgParams` + +parameters for sub-organization creation (e.g., authenticators, user metadata). + +###### invalidateExisting? + +`boolean` + +flag to invalidate existing sessions for the user. + +###### otpCode + +`string` + +The OTP code entered by the user. + +###### otpId + +`string` + +The ID of the OTP to complete (returned from `initOtp`). + +###### otpType + +`OtpType` + +The type of OTP being completed (OtpType.Email or OtpType.Sms). + +###### publicKey? + +`string` + +public key to use for authentication. If not provided, a new key pair may be generated. + +###### sessionKey? + +`string` + +session key to use for session creation (defaults to the default session key). + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to a signed JWT session token for the user. + +#### Throws + +If there is an error during OTP verification, sign-up, or login. + +*** + +### connectWalletAccount() + +> **connectWalletAccount**(`walletProvider`): `Promise`\<`void`\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:494](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L494) + +#### Parameters + +##### walletProvider + +`WalletProvider` + +#### Returns + +`Promise`\<`void`\> + +*** + +### createApiKeyPair() + +> **createApiKeyPair**(`params`?): `Promise`\<`string`\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:3080](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L3080) + +Creates a new API key pair and returns the public key. + +- This function generates a new API key pair and stores it in the underlying key store (IndexedDB). +- If an external key pair is provided, it will use that key pair for creation instead of generating a new one. +- If `storeOverride` is set to true, the generated or provided public key will be set as the override key in the API key stamper, making it the active key for subsequent signing operations. +- Ensures the API key stamper is initialized before proceeding. +- Handles both native CryptoKeyPair objects and raw key material. + +#### Parameters + +##### params? + +###### externalKeyPair? + +`CryptoKeyPair` \| \{ `privateKey`: `string`; `publicKey`: `string`; \} + +An externally generated key pair (either a CryptoKeyPair or an object with publicKey/privateKey strings) to use instead of generating a new one. + +###### storeOverride? + +`boolean` + +If true, sets the generated or provided public key as the override key in the API key stamper (defaults to false). +@returnparams.s A promise that resolves to the public key of the created or provided API key pair as a string. + +#### Returns + +`Promise`\<`string`\> + +#### Throws + +If the API key stamper is not initialized or if there is an error during key pair creation or storage. + +*** + +### createPasskey() + +> **createPasskey**(`params`?): `Promise`\<\{ `attestation`: `v1Attestation`; `encodedChallenge`: `string`; \}\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:168](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L168) + +Creates a new passkey authenticator for the user. + +- This function generates a new passkey attestation and challenge, suitable for registration with the user's device. +- Handles both web and React Native environments, automatically selecting the appropriate passkey creation flow. +- The resulting attestation and challenge can be used to register the passkey with Turnkey. + +#### Parameters + +##### params? + +###### displayName? + +`string` + +The display name for the passkey. If not provided, defaults to "A Passkey". + +###### name? + +`string` + +The name of the passkey. If not provided, defaults to "A Passkey". + +###### stampWith? + +`StamperType` + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Returns + +`Promise`\<\{ `attestation`: `v1Attestation`; `encodedChallenge`: `string`; \}\> + +A promise that resolves to an object containing: + - attestation: The attestation object returned from the passkey creation process. + - encodedChallenge: The encoded challenge string used for passkey registration. + +#### Throws + +If there is an error during passkey creation, or if the platform is unsupported. + +*** + +### createWallet() + +> **createWallet**(`params`): `Promise`\<`string`\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:2421](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L2421) + +Creates a new wallet for sub-organization. + +- This function creates a new wallet for the current sub-organization. +- If an organizationId is provided, the wallet will be created under that specific sub-organization; otherwise, it uses the current session's organizationId. +- If a list of address formats is provided, accounts will be created in the wallet based on those formats (starting from path index 0). +- If a list of account parameters is provided, those accounts will be created in the wallet. +- If no accounts or address formats are provided, default Ethereum and Solana accounts will be created. +- Optionally allows specifying the mnemonic length for the wallet seed phrase (defaults to 12). +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Parameters + +##### params + +###### accounts? + +`v1WalletAccountParams`[] \| `v1AddressFormat`[] + +array of account parameters or address formats to create in the wallet. + +###### mnemonicLength? + +`number` + +mnemonic length for the wallet seed phrase (defaults to 12). + +###### organizationId? + +`string` + +organization ID to create the wallet under a specific sub-organization (defaults to the current session's organizationId). + +###### stampWith? + +`StamperType` + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### walletName + +`string` + +The name of the wallet to create. + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to the ID of the newly created wallet. + +#### Throws + +If there is no active session or if there is an error creating the wallet. + +*** + +### createWalletAccounts() + +> **createWalletAccounts**(`params`): `Promise`\<`string`[]\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:2495](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L2495) + +Creates new accounts in the specified wallet. + +- This function creates new wallet accounts based on the provided account parameters or address formats. +- If a walletId is provided, it creates the accounts in that specific wallet; otherwise, it uses the current session's wallet. +- If a list of address formats is provided, it will create accounts in the wallet based on those formats, automatically determining the next available path indexes to avoid duplicates with existing accounts. +- If account parameters are provided, they are used directly for account creation. +- Automatically queries existing wallet accounts to prevent duplicate account creation for the same address format and path. +- Supports stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Parameters + +##### params + +###### accounts + +`v1WalletAccountParams`[] \| `v1AddressFormat`[] + +An array of account parameters or address formats to create in the wallet. + +###### organizationId? + +`string` + +organization ID to create the accounts under a specific organization (walletId must be associated with the sub-organization). + +###### stampWith? + +`StamperType` + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### walletId + +`string` + +The ID of the wallet to create accounts in. + +#### Returns + +`Promise`\<`string`[]\> + +A promise that resolves to an array of addresses for the newly created accounts. + +#### Throws + +If there is no active session, if the wallet does not exist, or if there is an error creating the wallet accounts. + +*** + +### deleteSubOrganization() + +> **deleteSubOrganization**(`params`?): `Promise`\<`TDeleteSubOrganizationResponse`\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:2694](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L2694) + +Deletes the current sub-organization (sub-org) for the active session. + +- This function deletes the sub-organization associated with the current active session. +- By default, the deletion will fail if any wallets associated with the sub-organization have not been exported. +- If `deleteWithoutExport` is set to true, the sub-organization will be deleted even if its wallets have not been exported (potentially resulting in loss of access to those wallets). +- Requires an active session; otherwise, an error is thrown. +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Parameters + +##### params? + +###### deleteWithoutExport? + +`boolean` + +flag to delete the sub-organization without requiring all wallets to be exported first (defaults to false). + +###### stampWith? + +`StamperType` + +parameter to stamp the request with a specific stamper. + +#### Returns + +`Promise`\<`TDeleteSubOrganizationResponse`\> + +A promise that resolves to a `TDeleteSubOrganizationResponse` object containing the result of the deletion. + +#### Throws + +If there is no active session or if there is an error deleting the sub-organization. + +*** + +### disconnectWalletAccount() + +> **disconnectWalletAccount**(`walletProvider`): `Promise`\<`void`\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:507](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L507) + +#### Parameters + +##### walletProvider + +`WalletProvider` + +#### Returns + +`Promise`\<`void`\> + +*** + +### exportWallet() + +> **exportWallet**(`params`): `Promise`\<`string`\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:2572](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L2572) + +Exports a wallet as an encrypted bundle. + +- This function exports the specified wallet and its accounts as an encrypted bundle, suitable for backup or transfer. +- The exported bundle contains the wallet's seed phrase, encrypted to the provided target public key. +- If a targetPublicKey is provided, the bundle will be encrypted to that public key; otherwise, an error will be thrown. +- If an organizationId is provided, the wallet will be exported under that sub-organization; otherwise, the current session's organizationId is used. +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). +- The exported bundle can later be imported using the `importWallet` method. + +#### Parameters + +##### params + +###### organizationId? + +`string` + +organization ID to export the wallet under a specific sub-organization (walletId must be associated with the sub-organization). + +###### stampWith? + +`StamperType` + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### targetPublicKey + +`string` + +The public key to encrypt the bundle to (required). + +###### walletId + +`string` + +The ID of the wallet to export. + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to an `ExportBundle` object containing the encrypted wallet seed phrase and metadata. + +#### Throws + +If there is no active session, if the targetPublicKey is missing, or if there is an error exporting the wallet. + +*** + +### fetchUser() + +> **fetchUser**(`params`?): `Promise`\<`v1User`\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:1816](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L1816) + +Fetches the user details for the current session or a specified user. + +- Retrieves user details from the Turnkey API using the provided userId and organizationId, or defaults to those from the active session. +- If no userId is provided, the userId from the current session is used. +- If no organizationId is provided, the organizationId from the current session is used. +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). +- Ensures that an active session exists before making the request. + +#### Parameters + +##### params? + +###### organizationId? + +`string` + +organization ID to specify the sub-organization (defaults to the current session's organizationId). + +###### stampWith? + +`StamperType` + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### userId? + +`string` + +user ID to fetch specific user details (defaults to the current session's userId). + +#### Returns + +`Promise`\<`v1User`\> + +A promise that resolves to a `v1User` object containing the user details. + +#### Throws + +If there is no active session, if there is no userId, or if there is an error fetching user details. + +*** + +### fetchWalletAccounts() + +> **fetchWalletAccounts**(`params`): `Promise`\<`WalletAccount`[]\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:1561](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L1561) + +Fetches all accounts for a specific wallet, including both embedded and connected wallet accounts. + +- For embedded wallets, retrieves accounts from the Turnkey API, supporting pagination (defaults to the first page with a limit of 100 accounts). +- For connected wallets (e.g., browser extensions or external providers), constructs account objects for each connected address from the provided or discovered wallet providers. +- Automatically determines the account type and populates relevant fields such as address, curve, and signing capability. +- Optionally allows filtering by a specific set of wallet providers and supports custom pagination options. +- Supports stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Parameters + +##### params + +###### paginationOptions? + +`v1Pagination` + +pagination options for embedded wallets. + +###### stampWith? + +`StamperType` + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### wallet + +`Wallet` + +The wallet for which to fetch accounts. + +###### walletProviders? + +`WalletProvider`[] + +list of wallet providers to filter by (used for connected wallets). + +#### Returns + +`Promise`\<`WalletAccount`[]\> + +A promise that resolves to an array of `v1WalletAccount` objects. + +#### Throws + +If no active session is found or if there is an error fetching wallet accounts. + +*** + +### fetchWallets() + +> **fetchWallets**(`params`?): `Promise`\<`Wallet`[]\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:1446](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L1446) + +Fetches all wallets for the current user, including both embedded and connected wallets. + +- Retrieves all wallets associated with the organizationId from the current active session. +- For each embedded wallet, automatically fetches and attaches all associated wallet accounts. +- For connected wallets (e.g., browser extensions or external providers), groups providers by wallet name and attaches all connected accounts. +- Returns both embedded and connected wallets in a single array, each with their respective accounts populated. +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Parameters + +##### params? + +###### stampWith? + +`StamperType` + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Returns + +`Promise`\<`Wallet`[]\> + +A promise that resolves to an array of `Wallet` objects. + +#### Throws + +If no active session is found or if there is an error fetching wallets. + +*** + +### getActiveSessionKey() + +> **getActiveSessionKey**(): `Promise`\<`undefined` \| `string`\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:3003](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L3003) + +Retrieves the active session key currently set in persistent storage. + +- This function fetches the session key that is currently marked as active in the client's persistent storage. +- The active session key determines which session is used for all session-dependent operations. +- If no active session key is set, returns `undefined`. +- Useful for determining which session is currently in use, especially when managing multiple sessions. + +#### Returns + +`Promise`\<`undefined` \| `string`\> + +A promise that resolves to the active session key as a string, or `undefined` if no active session is set. + +#### Throws + +If there is an error retrieving the active session key from storage. + +*** + +### getAllSessions() + +> **getAllSessions**(): `Promise`\<`undefined` \| `Record`\<`string`, [`Session`](../../../sdk-browser/index/Session/README.mdx)\>\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:2942](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L2942) + +Retrieves all sessions stored in persistent storage. + +- This function fetches all session objects currently stored by the client, including those that are not active. +- Returns a record mapping each session key to its corresponding `Session` object. +- Useful for session management, auditing, or displaying all available sessions to the user. +- Automatically skips any session keys that do not have a valid session object. + +#### Returns + +`Promise`\<`undefined` \| `Record`\<`string`, [`Session`](../../../sdk-browser/index/Session/README.mdx)\>\> + +A promise that resolves to a record of session keys and their corresponding `Session` objects, or `undefined` if no sessions exist. + +#### Throws + +If there is an error retrieving sessions from storage. + +*** + +### getProxyAuthConfig() + +> **getProxyAuthConfig**(): `Promise`\<`ProxyTGetWalletKitConfigResponse`\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:3124](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L3124) + +Fetches the WalletKit proxy authentication configuration from the auth proxy. + +- This function makes a request to the Turnkey auth proxy to retrieve the current WalletKit configuration, + including supported authentication methods, OAuth providers, and any custom proxy settings. +- Useful for dynamically configuring the client UI or authentication flows based on the proxy's capabilities. +- Ensures that the client is aware of the latest proxy-side configuration, which may affect available login/signup options. + +#### Returns + +`Promise`\<`ProxyTGetWalletKitConfigResponse`\> + +A promise that resolves to a `ProxyTGetWalletKitConfigResponse` object containing the proxy authentication configuration. + +#### Throws + +If there is an error retrieving the proxy authentication configuration from the auth proxy. + +*** + +### getSession() + +> **getSession**(`params`?): `Promise`\<`undefined` \| [`Session`](../../../sdk-browser/index/Session/README.mdx)\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:2914](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L2914) + +Retrieves the session associated with the specified session key, or the active session by default. + +- This function retrieves the session object from storage, using the provided session key or, if not specified, the current active session key. +- If no session key is provided and there is no active session, it returns undefined. +- Returns the session details, including public key, organization ID, user ID, and expiration. + +#### Parameters + +##### params? + +###### sessionKey? + +`string` + +session key to retrieve a specific session (defaults to the current active session key). + +#### Returns + +`Promise`\<`undefined` \| [`Session`](../../../sdk-browser/index/Session/README.mdx)\> + +A promise that resolves to a `Session` object containing the session details, or undefined if not found. + +#### Throws + +If there is an error retrieving the session from storage. + +*** + +### getWalletProviders() + +> **getWalletProviders**(`chain`?): `Promise`\<`WalletProvider`[]\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:481](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L481) + +#### Parameters + +##### chain? + +`WalletType` + +#### Returns + +`Promise`\<`WalletProvider`[]\> + +*** + +### importWallet() + +> **importWallet**(`params`): `Promise`\<`string`\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:2631](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L2631) + +Imports a wallet from an encrypted bundle. + +- This function imports a wallet using the provided encrypted bundle and creates accounts based on the provided parameters. +- If a userId is provided, the wallet will be imported for that specific user; otherwise, it uses the current session's userId. +- If an accounts array is provided, those accounts will be created in the imported wallet; otherwise, default Ethereum and Solana accounts will be created. +- The encrypted bunlde MUST be encrypted to +- Automatically ensures an active session exists before making the request. +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Parameters + +##### params + +###### accounts? + +`v1WalletAccountParams`[] + +array of account parameters to create in the imported wallet (defaults to standard Ethereum and Solana accounts). + +###### encryptedBundle + +`string` + +The encrypted bundle containing the wallet seed phrase and metadata. + +###### stampWith? + +`StamperType` + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### userId? + +`string` + +user ID to import the wallet for a specific user (defaults to the current session's userId). + +###### walletName + +`string` + +The name of the wallet to create upon import. + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to the ID of the imported wallet. + +#### Throws + +If there is no active session, if the encrypted bundle is invalid, or if there is an error importing the wallet. + +*** + +### init() + +> **init**(): `Promise`\<`void`\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:113](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L113) + +#### Returns + +`Promise`\<`void`\> + +*** + +### initOtp() + +> **initOtp**(`params`): `Promise`\<`string`\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:870](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L870) + +Initializes the OTP process by sending an OTP code to the provided contact. + +- This function initiates the OTP flow by sending a one-time password (OTP) code to the user's contact information (email address or phone number) via the auth proxy. +- Supports both email and SMS OTP types. +- Returns an OTP ID that is required for subsequent OTP verification. + +#### Parameters + +##### params + +###### contact + +`string` + +The contact information for the user (e.g., email address or phone number). + +###### otpType + +`OtpType` + +The type of OTP to initialize (OtpType.Email or OtpType.Sms). + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to the OTP ID required for verification. + +#### Throws + +If there is an error during the OTP initialization process or if the maximum number of OTPs has been reached. + +*** + +### loginOrSignupWithWallet() + +> **loginOrSignupWithWallet**(`params`): `Promise`\<`string`\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:690](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L690) + +#### Parameters + +##### params + +###### createSubOrgParams? + +`CreateSubOrgParams` + +###### expirationSeconds? + +`string` + +###### sessionKey? + +`string` + +###### walletProvider + +`WalletProvider` + +#### Returns + +`Promise`\<`string`\> + +*** + +### loginWithOauth() + +> **loginWithOauth**(`params`): `Promise`\<`string`\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:1303](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L1303) + +Logs in a user using OAuth authentication. + +- This function logs in a user using the provided OIDC token and public key. +- Optionally invalidates any existing sessions for the user if `invalidateExisting` is set to true. +- Stores the resulting session token under the specified session key, or the default session key if not provided. +- Handles cleanup of unused key pairs if login fails. + +#### Parameters + +##### params + +###### invalidateExisting? + +`boolean` + +flag to invalidate existing sessions for the user. + +###### oidcToken + +`string` + +The OIDC token received after successful authentication with the OAuth provider. + +###### publicKey + +`string` + +The public key to use for authentication. Must be generated prior to calling this function. + +###### sessionKey? + +`string` + +session key to use for session creation (defaults to the default session key). + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to a signed JWT session token. + +#### Throws + +If there is an error during the OAuth login process or if key pair cleanup fails. + +*** + +### loginWithOtp() + +> **loginWithOtp**(`params`): `Promise`\<`string`\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:992](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L992) + +Logs in a user using an OTP verification token. + +- This function logs in a user using the verification token received after OTP verification (from email or SMS). +- If a public key is not provided, a new API key pair will be generated for authentication. +- Optionally invalidates any existing sessions for the user if `invalidateExisting` is set to true. +- Stores the resulting session token under the specified session key, or the default session key if not provided. +- Handles cleanup of unused key pairs if login fails. + +#### Parameters + +##### params + +###### invalidateExisting? + +`boolean` + +flag to invalidate existing session for the user. + +###### publicKey? + +`string` + +public key to use for authentication. If not provided, a new key pair will be generated. + +###### sessionKey? + +`string` + +session key to use for session creation (defaults to the default session key). + +###### verificationToken + +`string` + +The verification token received after OTP verification. + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to a signed JWT session token. + +#### Throws + +If there is an error during the OTP login process or if key pair cleanup fails. + +*** + +### loginWithPasskey() + +> **loginWithPasskey**(`params`?): `Promise`\<`string`\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:292](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L292) + +Logs in a user using a passkey, optionally specifying the public key, session key, and session expiration. + +- This function initiates the login process with a passkey and handles session creation and storage. +- If a public key is not provided, a new key pair will be generated for authentication. +- If a session key is not provided, the default session key will be used. +- The session expiration can be customized via the expirationSeconds parameter. +- Handles cleanup of unused key pairs if login fails. + +#### Parameters + +##### params? + +###### expirationSeconds? + +`string` + +session expiration time in seconds (defaults to the configured default). + +###### publicKey? + +`string` + +public key to use for authentication. If not provided, a new key pair will be generated. + +###### sessionKey? + +`string` + +session key to use for session creation (defaults to the default session key). + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to a signed JWT session token. + +#### Throws + +If there is an error during the passkey login process or if the user cancels the passkey prompt. + +*** + +### loginWithWallet() + +> **loginWithWallet**(`params`): `Promise`\<`string`\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:522](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L522) + +#### Parameters + +##### params + +###### expirationSeconds? + +`string` + +###### publicKey? + +`string` + +###### sessionKey? + +`string` + +###### walletProvider + +`WalletProvider` + +#### Returns + +`Promise`\<`string`\> + +*** + +### logout() + +> **logout**(`params`?): `Promise`\<`void`\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:248](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L248) + +Logs out the current client session. + +- This function clears the specified session and removes any associated key pairs from storage. +- If a sessionKey is provided, it logs out from that session; otherwise, it logs out from the active session. +- Cleans up any api keys associated with the session. + +#### Parameters + +##### params? + +###### sessionKey? + +`string` + +session key to specify which session to log out from (defaults to the active session). + +#### Returns + +`Promise`\<`void`\> + +A promise that resolves when the logout process is complete. + +#### Throws + +If there is no active session or if there is an error during the logout process. + +*** + +### refreshSession() + +> **refreshSession**(`params`?): `Promise`\<`undefined` \| `TStampLoginResponse`\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:2846](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L2846) + +Refreshes the session associated with the specified session key, or the active session by default. + +- This function refreshes the session and updates the session token and key pair associated with the given session key. +- If a sessionKey is provided, it will refresh the session under that key; otherwise, it will use the current active session key. +- Optionally allows specifying a new expiration time for the session, a custom public key, and whether to invalidate the existing session after refreshing. +- Makes a request to the Turnkey API to stamp a new login and stores the refreshed session token. +- Automatically manages key pair cleanup and session storage to ensure consistency. +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Parameters + +##### params? + +###### expirationSeconds? + +`string` + +expiration time in seconds for the refreshed session (defaults to the configured default). + +###### invalidateExisitng? + +`boolean` + +flag to invalidate the existing session before refreshing (defaults to false). + +###### publicKey? + +`string` + +public key to use for the refreshed session (if not provided, a new key pair will be generated). + +###### sessionKey? + +`string` + +session key to refresh the session under (defaults to the active session key). + +###### stampWith? + +`StamperType` + +parameter to stamp the request with a specific stamper. + +#### Returns + +`Promise`\<`undefined` \| `TStampLoginResponse`\> + +A promise that resolves to a `TStampLoginResponse` object containing the refreshed session details. + +#### Throws + +If the session key does not exist, if there is no active session, or if there is an error refreshing the session. + +*** + +### removeOAuthProviders() + +> **removeOAuthProviders**(`params`): `Promise`\<`string`[]\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:2250](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L2250) + +Removes a list of OAuth providers from the user. + +- This function removes OAuth providers (e.g., Google, Apple) from the user's account. +- If a userId is provided, it removes the providers for that specific user; otherwise, it uses the current session's userId. +- Automatically ensures an active session exists before making the request. +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). +- Returns an array of remaining provider IDs associated with the user after removal. + +#### Parameters + +##### params + +###### providerIds + +`string`[] + +The IDs of the OAuth providers to remove. + +###### stampWith? + +`StamperType` + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### userId? + +`string` + +user ID to remove the provider for a specific user (defaults to the current session's userId). + +#### Returns + +`Promise`\<`string`[]\> + +A promise that resolves to an array of provider IDs that were removed. + +#### Throws + +If there is no active session, if the userId is missing, or if there is an error removing the OAuth provider. + +*** + +### removePasskeys() + +> **removePasskeys**(`params`): `Promise`\<`string`[]\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:2371](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L2371) + +Removes passkeys (authenticator) from the user. + +- This function removes passkeys (WebAuthn/FIDO2 authenticators) from the user's account. +- If a userId is provided, it removes the passkeys for that specific user; otherwise, it uses the current session's userId. +- Automatically ensures an active session exists before making the request. +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). +- Returns an array of remaining authenticator IDs for the user after removal. + +#### Parameters + +##### params + +###### authenticatorIds + +`string`[] + +The IDs of the authenticators (passkeys) to remove. + +###### stampWith? + +`StamperType` + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### userId? + +`string` + +user ID to remove the passkeys for a specific user (defaults to the current session's userId). + +#### Returns + +`Promise`\<`string`[]\> + +A promise that resolves to an array of authenticator IDs that were removed. + +#### Throws + +If there is no active session, if the userId is missing, or if there is an error removing the passkeys. + +*** + +### removeUserEmail() + +> **removeUserEmail**(`params`?): `Promise`\<`string`\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:1937](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L1937) + +Removes the user's email address. + +- This function removes the user's email address by setting it to an empty string. +- If a userId is provided, it removes the email for that specific user; otherwise, it uses the current session's userId. +- Automatically ensures an active session exists before making the request. +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Parameters + +##### params? + +###### stampWith? + +`StamperType` + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### userId? + +`string` + +user ID to remove a specific user's email address (defaults to the current session's userId). + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to the userId of the user whose email was removed. + +#### Throws + +If there is no active session, if the userId is missing, or if there is an error removing the user email. + +*** + +### removeUserPhoneNumber() + +> **removeUserPhoneNumber**(`params`?): `Promise`\<`string`\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:2039](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L2039) + +Removes the user's phone number. + +- This function removes the user's phone number by setting it to an empty string. +- If a userId is provided, it removes the phone number for that specific user; otherwise, it uses the current session's userId. +- Automatically ensures an active session exists before making the request. +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Parameters + +##### params? + +###### stampWith? + +`StamperType` + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### userId? + +`string` + +user ID to remove a specific user's phone number (defaults to the current session's userId). + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to the userId of the user whose phone number was removed. + +#### Throws + +If there is no active session, if the userId is missing, or if there is an error removing the user phone number. + +*** + +### setActiveSession() + +> **setActiveSession**(`params`): `Promise`\<`void`\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:2978](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L2978) + +Sets the active session to the specified session key. + +- This function updates the `activeSessionKey` in persistent storage to the specified session key. +- Ensures that subsequent operations use the session associated with this key as the active session. +- Does not validate whether the session key exists or is valid; it simply updates the pointer. +- Useful for switching between multiple stored sessions or restoring a previous session context. + +#### Parameters + +##### params + +###### sessionKey + +`string` + +The session key to set as the active session. + +#### Returns + +`Promise`\<`void`\> + +A promise that resolves when the active session key is successfully set. + +#### Throws + +If the client is not initialized or if there is an error setting the active session key. + +*** + +### signMessage() + +> **signMessage**(`params`): `Promise`\<`v1SignRawPayloadResult`\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:1674](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L1674) + +Signs a message using the specified wallet account. + +- Supports both embedded and connected wallets. +- For **connected wallets**: + - Delegates signing to the wallet provider’s native signing method. + - **Important:** For Ethereum wallets (e.g., MetaMask), signatures follow [EIP-191](https://eips.ethereum.org/EIPS/eip-191). + The message is automatically prefixed with `"\x19Ethereum Signed Message:\n" + message length` + before signing. As a result, this signature **cannot be used as a raw transaction signature** + or broadcast on-chain. +- For **embedded wallets**, uses the Turnkey API to sign the message directly. +- Automatically handles message encoding and hashing based on the wallet account’s address format, + unless explicitly overridden. + +#### Parameters + +##### params + +###### encoding? + +`v1PayloadEncoding` + +override for the payload encoding (defaults to the encoding appropriate for the address type). + +###### hashFunction? + +`v1HashFunction` + +override for the hash function (defaults to the hash function appropriate for the address type). + +###### message + +`string` + +The message to sign. + +###### stampWith? + +`StamperType` + +stamper to tag the signing request (e.g., Passkey, ApiKey, or Wallet). + +###### walletAccount + +`WalletAccount` + +The wallet account to use for signing. + +#### Returns + +`Promise`\<`v1SignRawPayloadResult`\> + +A promise resolving to a `v1SignRawPayloadResult` containing the signature and metadata. + +#### Throws + +If signing fails, if the wallet account does not support signing, or if the response is invalid. + +*** + +### signTransaction() + +> **signTransaction**(`params`): `Promise`\<`string`\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:1747](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L1747) + +Signs a transaction using the specified wallet account. + +- This function signs a blockchain transaction using the provided wallet address and transaction data. +- Supports all Turnkey-supported blockchain networks (e.g., Ethereum, Solana, Tron). +- Automatically determines the appropriate signing method based on the transaction type. +- Delegates signing to the Turnkey API, which returns the signed transaction and related metadata. +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +#### Parameters + +##### params + +###### stampWith? + +`StamperType` + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### transactionType + +`v1TransactionType` + +The type of transaction (e.g., "TRANSACTION_TYPE_ETHEREUM", "TRANSACTION_TYPE_SOLANA", "TRANSACTION_TYPE_TRON"). + +###### unsignedTransaction + +`string` + +The unsigned transaction data (serialized as a string) to be signed. + +###### walletAccount + +`WalletAccount` + +The wallet account to use for signing the transaction. + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to a `TSignTransactionResponse` object containing the signed transaction and any additional signing metadata. + +#### Throws + +If there is an error signing the transaction or if the response is invalid. + +*** + +### signUpWithOauth() + +> **signUpWithOauth**(`params`): `Promise`\<`string`\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:1388](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L1388) + +Signs up a user using OAuth authentication. + +- This function creates a new sub-organization for the user using the provided OIDC token, public key, and provider name. +- Handles the full OAuth sign-up flow, including sub-organization creation and session management. +- Optionally accepts additional sub-organization creation parameters and a custom session key. +- After successful sign-up, automatically logs in the user and returns a signed JWT session token. + +#### Parameters + +##### params + +###### createSubOrgParams? + +`CreateSubOrgParams` + +parameters for sub-organization creation (e.g., authenticators, user metadata). + +###### oidcToken + +`string` + +The OIDC token received after successful authentication with the OAuth provider. + +###### providerName + +`string` + +The name of the OAuth provider (e.g., "Google", "Apple"). + +###### publicKey + +`string` + +The public key to associate with the new sub-organization. + +###### sessionKey? + +`string` + +session key to use for session creation (defaults to the default session key). + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to a signed JWT session token for the new sub-organization. + +#### Throws + +If there is an error during the OAuth sign-up or login process. + +*** + +### signUpWithOtp() + +> **signUpWithOtp**(`params`): `Promise`\<`string`\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:1073](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L1073) + +Signs up a user using an OTP verification token. + +- This function signs up a user using the verification token received after OTP verification (from email or SMS). +- Creates a new sub-organization for the user with the provided parameters and associates the contact (email or phone) with the sub-organization. +- Automatically generates a new API key pair for authentication and session management. +- Stores the resulting session token under the specified session key, or the default session key if not provided. +- Handles both email and SMS OTP types, and supports additional sub-organization creation parameters. + +#### Parameters + +##### params + +###### contact + +`string` + +The contact information for the user (e.g., email address or phone number). + +###### createSubOrgParams? + +`CreateSubOrgParams` + +parameters for creating a sub-organization (e.g., authenticators, user metadata). + +###### invalidateExisting? + +`boolean` + +flag to invalidate existing session for the user. + +###### otpType + +`OtpType` + +The type of OTP being used (OtpType.Email or OtpType.Sms). + +###### sessionKey? + +`string` + +session key to use for session creation (defaults to the default session key). + +###### verificationToken + +`string` + +The verification token received after OTP verification. + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to a signed JWT session token for the new sub-organization. + +#### Throws + +If there is an error during the OTP sign-up process or session storage. + +*** + +### signUpWithPasskey() + +> **signUpWithPasskey**(`params`?): `Promise`\<`string`\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:374](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L374) + +Signs up a user using a passkey, creating a new sub-organization and session. + +- This function creates a new passkey authenticator and uses it to register a new sub-organization for the user. +- Handles both passkey creation and sub-organization creation in a single flow. +- Optionally accepts additional sub-organization parameters, a custom session key, a custom passkey display name, and a custom session expiration. +- Automatically generates a new API key pair for authentication and session management. +- Stores the resulting session token and manages cleanup of unused key pairs. + +#### Parameters + +##### params? + +###### createSubOrgParams? + +`CreateSubOrgParams` + +parameters for creating a sub-organization (e.g., authenticators, user metadata). + +###### expirationSeconds? + +`string` + +session expiration time in seconds (defaults to the configured default). + +###### passkeyDisplayName? + +`string` + +display name for the passkey (defaults to a generated name based on the current timestamp). + +###### sessionKey? + +`string` + +session key to use for storing the session (defaults to the default session key). + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to a signed JWT session token for the new sub-organization. + +#### Throws + +If there is an error during passkey creation, sub-organization creation, or session storage. + +*** + +### signUpWithWallet() + +> **signUpWithWallet**(`params`): `Promise`\<`string`\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:579](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L579) + +#### Parameters + +##### params + +###### createSubOrgParams? + +`CreateSubOrgParams` + +###### expirationSeconds? + +`string` + +###### sessionKey? + +`string` + +###### walletProvider + +`WalletProvider` + +#### Returns + +`Promise`\<`string`\> + +*** + +### storeSession() + +> **storeSession**(`params`): `Promise`\<`void`\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:2736](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L2736) + +Stores a session token and updates the session associated with the specified session key, or by default the active session. + +- This function parses and stores a signed JWT session token in local storage, associating it with the given session key. +- If a sessionKey is provided, the session will be stored under that key; otherwise, it will use the default session key. +- If a session already exists for the session key, its associated key pair will be deleted before storing the new session. +- After storing the session, any unused key pairs are automatically cleared from storage. +- Ensures that session management is consistent and prevents orphaned key pairs. + +#### Parameters + +##### params + +###### sessionKey? + +`string` + +session key to store the session under (defaults to the default session key). + +###### sessionToken + +`string` + +The JWT session token to store. + +#### Returns + +`Promise`\<`void`\> + +A promise that resolves when the session is successfully stored. + +#### Throws + +If there is an error storing the session or cleaning up key pairs. + +*** + +### updateUserEmail() + +> **updateUserEmail**(`params`): `Promise`\<`string`\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:1880](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L1880) + +Updates the user's email address. + +- This function updates the user's email address and, if provided, verifies it using a verification token (typically from an OTP flow). +- If a userId is provided, it updates the email for that specific user; otherwise, it uses the current session's userId. +- If a verificationToken is not provided, the email will be updated but will not be marked as verified. +- Automatically ensures an active session exists before making the request. +- Handles session management and error reporting for both update and verification flows. + +#### Parameters + +##### params + +###### email + +`string` + +The new email address to set for the user. + +###### stampWith? + +`StamperType` + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### userId? + +`string` + +user ID to update a specific user's email (defaults to the current session's userId). + +###### verificationToken? + +`string` + +verification token from OTP email verification (required if verifying the email). + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to the userId of the updated user. + +#### Throws + +If there is no active session, if the userId is missing, or if there is an error updating or verifying the user email. + +*** + +### updateUserName() + +> **updateUserName**(`params`): `Promise`\<`string`\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:2083](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L2083) + +Updates the user's name. + +- This function updates the user's display name. +- If a userId is provided, it updates the name for that specific user; otherwise, it uses the current session's userId. +- Automatically ensures an active session exists before making the request. +- Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). +- Handles session management and error reporting for the update flow. + +#### Parameters + +##### params + +###### stampWith? + +`StamperType` + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### userId? + +`string` + +user ID to update a specific user's name (defaults to the current session's userId). + +###### userName + +`string` + +The new name to set for the user. + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to the userId of the updated user. + +#### Throws + +If there is no active session, if the userId is missing, or if there is an error updating the user name. + +*** + +### updateUserPhoneNumber() + +> **updateUserPhoneNumber**(`params`): `Promise`\<`string`\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:1982](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L1982) + +Updates the user's phone number. + +- This function updates the user's phone number and, if provided, verifies it using a verification token (from an OTP flow). +- If a userId is provided, it updates the phone number for that specific user; otherwise, it uses the current session's userId. +- If a verificationToken is not provided, the phone number will be updated but will not be marked as verified. +- Automatically ensures an active session exists before making the request. +- Handles session management and error reporting for both update and verification flows. + +#### Parameters + +##### params + +###### phoneNumber + +`string` + +The new phone number to set for the user. + +###### stampWith? + +`StamperType` + +parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + +###### userId? + +`string` + +user ID to update a specific user's phone number (defaults to the current session's userId). + +###### verificationToken? + +`string` + +verification token from OTP phone verification (required if verifying the phone number). + +#### Returns + +`Promise`\<`string`\> + +A promise that resolves to the userId of the updated user. + +#### Throws + +If there is no active session, if the userId is missing, or if there is an error updating or verifying the user phone number. + +*** + +### verifyOtp() + +> **verifyOtp**(`params`): `Promise`\<\{ `subOrganizationId`: `string`; `verificationToken`: `string`; \}\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:920](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L920) + +Verifies the OTP code sent to the user. + +- This function verifies the OTP code entered by the user against the OTP sent to their contact information (email or phone) using the auth proxy. +- If verification is successful, it returns the sub-organization ID associated with the contact (if it exists) and a verification token. +- The verification token can be used for subsequent login or sign-up flows. +- Handles both email and SMS OTP types. + +#### Parameters + +##### params + +###### contact + +`string` + +The contact information for the user (e.g., email address or phone number). + +###### otpCode + +`string` + +The OTP code entered by the user. + +###### otpId + +`string` + +The ID of the OTP to verify (returned from `initOtp`). + +###### otpType + +`OtpType` + +The type of OTP being verified (OtpType.Email or OtpType.Sms). + +#### Returns + +`Promise`\<\{ `subOrganizationId`: `string`; `verificationToken`: `string`; \}\> + +A promise that resolves to an object containing: + - subOrganizationId: The sub-organization ID if the contact is already associated with a sub-organization, or an empty string if not. + - verificationToken: The verification token to be used for login or sign-up. + +#### Throws + +If there is an error during the OTP verification process, such as an invalid code or network failure. diff --git a/generated-docs/sdks/sdk-js/index/TurnkeyClientMethods/README.mdx b/generated-docs/sdks/sdk-js/index/TurnkeyClientMethods/README.mdx new file mode 100644 index 000000000..f0be46ca1 --- /dev/null +++ b/generated-docs/sdks/sdk-js/index/TurnkeyClientMethods/README.mdx @@ -0,0 +1,11 @@ +[**Documentation**](../../../README.mdx) + +*** + +[Documentation](../../../modules.mdx) / [sdk-js](../../README.mdx) / [index](../README.mdx) / TurnkeyClientMethods + +# Type Alias: TurnkeyClientMethods + +> **TurnkeyClientMethods** = `PublicMethods`\<[`TurnkeyClient`](../TurnkeyClient/README.mdx)\> + +Defined in: [sdk-js/src/\_\_clients\_\_/core.ts:84](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/__clients__/core.ts#L84) diff --git a/generated-docs/sdks/sdk-js/index/WebauthnStamper/README.mdx b/generated-docs/sdks/sdk-js/index/WebauthnStamper/README.mdx new file mode 100644 index 000000000..a36241841 --- /dev/null +++ b/generated-docs/sdks/sdk-js/index/WebauthnStamper/README.mdx @@ -0,0 +1,79 @@ +[**Documentation**](../../../README.mdx) + +*** + +[Documentation](../../../modules.mdx) / [sdk-js](../../README.mdx) / [index](../README.mdx) / WebauthnStamper + +# Class: WebauthnStamper + +Defined in: webauthn-stamper/dist/index.d.ts:11 + +Stamper to use with `@turnkey/http`'s `TurnkeyClient` + +## Constructors + +### Constructor + +> **new WebauthnStamper**(`config`): `WebauthnStamper` + +Defined in: webauthn-stamper/dist/index.d.ts:16 + +#### Parameters + +##### config + +[`TWebauthnStamperConfig`](../TWebauthnStamperConfig/README.mdx) + +#### Returns + +`WebauthnStamper` + +## Properties + +### allowCredentials + +> **allowCredentials**: `PublicKeyCredentialDescriptor`[] + +Defined in: webauthn-stamper/dist/index.d.ts:15 + +*** + +### rpId + +> **rpId**: `string` + +Defined in: webauthn-stamper/dist/index.d.ts:12 + +*** + +### timeout + +> **timeout**: `number` + +Defined in: webauthn-stamper/dist/index.d.ts:13 + +*** + +### userVerification + +> **userVerification**: `UserVerificationRequirement` + +Defined in: webauthn-stamper/dist/index.d.ts:14 + +## Methods + +### stamp() + +> **stamp**(`payload`): `Promise`\<\{ `stampHeaderName`: `string`; `stampHeaderValue`: `string`; \}\> + +Defined in: webauthn-stamper/dist/index.d.ts:17 + +#### Parameters + +##### payload + +`string` + +#### Returns + +`Promise`\<\{ `stampHeaderName`: `string`; `stampHeaderValue`: `string`; \}\> diff --git a/generated-docs/sdks/sdk-js/index/generateWalletAccountsFromAddressFormat/README.mdx b/generated-docs/sdks/sdk-js/index/generateWalletAccountsFromAddressFormat/README.mdx new file mode 100644 index 000000000..60a0fc121 --- /dev/null +++ b/generated-docs/sdks/sdk-js/index/generateWalletAccountsFromAddressFormat/README.mdx @@ -0,0 +1,27 @@ +[**Documentation**](../../../README.mdx) + +*** + +[Documentation](../../../modules.mdx) / [sdk-js](../../README.mdx) / [index](../README.mdx) / generateWalletAccountsFromAddressFormat + +# Function: generateWalletAccountsFromAddressFormat() + +> **generateWalletAccountsFromAddressFormat**(`params`): `v1WalletAccountParams`[] + +Defined in: [sdk-js/src/utils.ts:526](https://github.com/tkhq/sdk/blob/main/packages/sdk-js/src/utils.ts#L526) + +## Parameters + +### params + +#### addresses + +`v1AddressFormat`[] + +#### existingWalletAccounts? + +`v1WalletAccount`[] + +## Returns + +`v1WalletAccountParams`[] diff --git a/generated-docs/sdks/sdk-js/index/signWithApiKey/README.mdx b/generated-docs/sdks/sdk-js/index/signWithApiKey/README.mdx new file mode 100644 index 000000000..941251438 --- /dev/null +++ b/generated-docs/sdks/sdk-js/index/signWithApiKey/README.mdx @@ -0,0 +1,37 @@ +[**Documentation**](../../../README.mdx) + +*** + +[Documentation](../../../modules.mdx) / [sdk-js](../../README.mdx) / [index](../README.mdx) / signWithApiKey + +# Variable: signWithApiKey() + +> `const` **signWithApiKey**: (`input`, `runtimeOverride`?) => `Promise`\<`string`\> + +Defined in: api-key-stamper/dist/index.d.ts:11 + +Signature function abstracting the differences between NodeJS and web environments for signing with API keys. + +## Parameters + +### input + +#### content + +`string` + +#### privateKey + +`string` + +#### publicKey + +`string` + +### runtimeOverride? + +[`Runtime`](../../../api-key-stamper/index/Runtime/README.mdx) + +## Returns + +`Promise`\<`string`\> diff --git a/packages/api-key-stamper/CHANGELOG.md b/packages/api-key-stamper/CHANGELOG.md index 83a12ce95..30b93103d 100644 --- a/packages/api-key-stamper/CHANGELOG.md +++ b/packages/api-key-stamper/CHANGELOG.md @@ -1,5 +1,40 @@ # @turnkey/api-key-stamper +## 0.4.8-beta.4 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/encoding@0.6.0-beta.4 + +## 0.4.8-beta.3 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/encoding@0.6.0-beta.3 + +## 0.4.8-beta.2 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/encoding@0.6.0-beta.2 + +## 0.4.8-beta.1 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/encoding@0.6.0-beta.1 + +## 0.4.8-beta.0 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/encoding@0.6.0-beta.0 + ## 0.4.7 ### Patch Changes diff --git a/packages/api-key-stamper/package.json b/packages/api-key-stamper/package.json index b972fb392..7de699a51 100644 --- a/packages/api-key-stamper/package.json +++ b/packages/api-key-stamper/package.json @@ -1,6 +1,6 @@ { "name": "@turnkey/api-key-stamper", - "version": "0.4.7", + "version": "0.4.8-beta.4", "main": "./dist/index.js", "module": "./dist/index.mjs", "exports": { diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md new file mode 100644 index 000000000..125216f29 --- /dev/null +++ b/packages/core/CHANGELOG.md @@ -0,0 +1,113 @@ +# @turnkey/core + +## 1.0.0-beta.4 + +### Minor Changes + +- @turnkey/react-wallet-kit and @turnkey/core beta-3 release + +### Patch Changes + +- Updated dependencies []: + - @turnkey/sdk-types@0.4.0-beta.4 + - @turnkey/encoding@0.6.0-beta.4 + - @turnkey/http@3.10.0-beta.1 + - @turnkey/api-key-stamper@0.4.8-beta.4 + - @turnkey/crypto@2.5.1-beta.4 + - @turnkey/react-native-passkey-stamper@1.1.2-beta.4 + +## 1.0.0-beta.3 + +### Minor Changes + +- @turnkey/react-wallet-kit and @turnkey/core beta-3 release + +### Patch Changes + +- Updated dependencies []: + - @turnkey/sdk-types@0.4.0-beta.3 + - @turnkey/encoding@0.6.0-beta.3 + - @turnkey/http@3.10.0-beta.0 + - @turnkey/api-key-stamper@0.4.8-beta.3 + - @turnkey/crypto@2.5.1-beta.3 + - @turnkey/react-native-passkey-stamper@1.1.2-beta.3 + +## 1.0.0-beta.2 + +### Minor Changes + +- updating package versions + +### Patch Changes + +- Updated dependencies []: + - @turnkey/sdk-types@0.4.0-beta.2 + - @turnkey/encoding@0.6.0-beta.2 + - @turnkey/api-key-stamper@0.4.8-beta.2 + - @turnkey/crypto@2.5.1-beta.2 + - @turnkey/http@3.8.1-beta.2 + - @turnkey/react-native-passkey-stamper@1.1.2-beta.2 + +## 1.0.0-beta.1 + +### Minor Changes + +- test build + +### Patch Changes + +- Updated dependencies []: + - @turnkey/sdk-types@0.4.0-beta.1 + - @turnkey/encoding@0.6.0-beta.1 + - @turnkey/api-key-stamper@0.4.8-beta.1 + - @turnkey/crypto@2.5.1-beta.1 + - @turnkey/http@3.8.1-beta.1 + - @turnkey/react-native-passkey-stamper@1.1.2-beta.1 + +## 1.0.0-beta.0 + +### Major Changes + +- beta for @turnkey/react-wallet-kit and @turnkey/core + +### Patch Changes + +- Updated dependencies []: + - @turnkey/sdk-types@0.4.0-beta.0 + - @turnkey/encoding@0.6.0-beta.0 + - @turnkey/api-key-stamper@0.4.8-beta.0 + - @turnkey/crypto@2.5.1-beta.0 + - @turnkey/http@3.8.1-beta.0 + - @turnkey/react-native-passkey-stamper@1.1.2-beta.0 + +## 1.0.0 + +### Major Changes + +- Initial beta release for react wallet kit + +### Patch Changes + +- Updated dependencies []: + - @turnkey/sdk-types@0.4.0 + - @turnkey/encoding@0.6.0 + - @turnkey/api-key-stamper@0.4.8 + - @turnkey/crypto@2.5.1 + - @turnkey/http@3.8.1 + - @turnkey/react-native-passkey-stamper@1.1.2 + +## 1.0.0 + +### Major Changes + +- Initial beta release for @turnkey/react-wallet-kit and @turnkey/core + +### Patch Changes + +- Updated dependencies []: + - @turnkey/sdk-types@0.4.0 + - @turnkey/encoding@0.6.0 + - @turnkey/api-key-stamper@0.4.8 + - @turnkey/crypto@2.5.1 + - @turnkey/http@3.8.1 + - @turnkey/react-native-passkey-stamper@1.1.2 diff --git a/packages/core/README.MD b/packages/core/README.MD new file mode 100644 index 000000000..3cf41509a --- /dev/null +++ b/packages/core/README.MD @@ -0,0 +1,5 @@ +# @turnkey/core + +A core JavaScript web and React Native package for interfacing with Turnkey's infrastructure. + +If you're using React, please use `@turnkey/react-wallet-kit` instead diff --git a/packages/core/package.json b/packages/core/package.json new file mode 100644 index 000000000..825ee9ebc --- /dev/null +++ b/packages/core/package.json @@ -0,0 +1,68 @@ +{ + "name": "@turnkey/core", + "version": "1.0.0-beta.4", + "description": "A core JavaScript web and React Native package for interfacing with Turnkey's infrastructure.", + "main": "./dist/index.js", + "module": "./dist/index.mjs", + "types": "dist/index.d.ts", + "files": [ + "dist", + "README.md" + ], + "scripts": { + "version": "node -p \"'export const VERSION = ' + JSON.stringify(require('./package.json').name + '@' + require('./package.json').version) + ';'\" > src/__generated__/version.ts", + "build": "rollup -c", + "clean": "rimraf ./dist ./.cache", + "typecheck": "tsc -p tsconfig.typecheck.json", + "prepublishOnly": "pnpm run clean && pnpm run build" + }, + "keywords": [ + "turnkey" + ], + "license": "MIT", + "dependencies": { + "@turnkey/api-key-stamper": "workspace:*", + "@turnkey/crypto": "workspace:*", + "@turnkey/encoding": "workspace:*", + "@turnkey/http": "workspace:*", + "@turnkey/sdk-types": "workspace:*", + "@turnkey/webauthn-stamper": "workspace:*", + "@wallet-standard/app": "^1.1.0", + "@wallet-standard/base": "^1.1.0", + "@walletconnect/sign-client": "^2.21.8", + "@walletconnect/types": "^2.21.8", + "bs58": "^6.0.0", + "cross-fetch": "^3.1.5", + "ethers": "^6.10.0", + "jwt-decode": "4.0.0", + "uuid": "^11.1.0", + "viem": "^2.33.1" + }, + "devDependencies": { + "glob": "^8.0.3", + "typescript": "5.4.3" + }, + "peerDependencies": { + "@react-native-async-storage/async-storage": "^2.2.0", + "@turnkey/react-native-passkey-stamper": "workspace:*", + "react-native-keychain": "^8.1.0 || ^9.2.2 || ^10.0.0" + }, + "peerDependenciesMeta": { + "react-native-keychain": { + "optional": true + }, + "@react-native-async-storage/async-storage": { + "optional": true + }, + "@turnkey/react-native-passkey-stamper": { + "optional": true + } + }, + "engines": { + "node": ">=18.0.0" + }, + "publishConfig": { + "access": "public", + "tag": "beta" + } +} diff --git a/packages/core/rollup.config.mjs b/packages/core/rollup.config.mjs new file mode 100644 index 000000000..23fa423e6 --- /dev/null +++ b/packages/core/rollup.config.mjs @@ -0,0 +1,3 @@ +import rollup from "../../rollup.config.base.mjs"; + +export default (options) => rollup(); diff --git a/packages/core/scripts/codegen.js b/packages/core/scripts/codegen.js new file mode 100644 index 000000000..39fc64a3c --- /dev/null +++ b/packages/core/scripts/codegen.js @@ -0,0 +1,520 @@ +const fs = require("fs"); +const path = require("path"); + +const SOURCE_DIRECTORY = path.resolve(__dirname, "../src"); +const PUBLIC_API_SWAGGER_PATH = path.resolve( + `${SOURCE_DIRECTORY}/__inputs__`, + "public_api.swagger.json", +); +const AUTH_PROXY_SWAGGER_PATH = path.resolve( + `${SOURCE_DIRECTORY}/__inputs__`, + "auth_proxy.swagger.json", +); +const TARGET_SDK_CLIENT_PATH = path.resolve( + `${SOURCE_DIRECTORY}/__generated__`, + "sdk-client-base.ts", +); + +const COMMENT_HEADER = "/* @generated by codegen. DO NOT EDIT BY HAND */"; + +const VERSIONED_ACTIVITY_TYPES = { + ACTIVITY_TYPE_CREATE_AUTHENTICATORS: "ACTIVITY_TYPE_CREATE_AUTHENTICATORS_V2", + ACTIVITY_TYPE_CREATE_API_KEYS: "ACTIVITY_TYPE_CREATE_API_KEYS_V2", + ACTIVITY_TYPE_CREATE_POLICY: "ACTIVITY_TYPE_CREATE_POLICY_V3", + ACTIVITY_TYPE_CREATE_PRIVATE_KEYS: "ACTIVITY_TYPE_CREATE_PRIVATE_KEYS_V2", + ACTIVITY_TYPE_CREATE_SUB_ORGANIZATION: + "ACTIVITY_TYPE_CREATE_SUB_ORGANIZATION_V7", + ACTIVITY_TYPE_CREATE_USERS: "ACTIVITY_TYPE_CREATE_USERS_V3", + ACTIVITY_TYPE_SIGN_RAW_PAYLOAD: "ACTIVITY_TYPE_SIGN_RAW_PAYLOAD_V2", + ACTIVITY_TYPE_SIGN_TRANSACTION: "ACTIVITY_TYPE_SIGN_TRANSACTION_V2", + ACTIVITY_TYPE_EMAIL_AUTH: "ACTIVITY_TYPE_EMAIL_AUTH_V2", + ACTIVITY_TYPE_CREATE_READ_WRITE_SESSION: + "ACTIVITY_TYPE_CREATE_READ_WRITE_SESSION_V2", + ACTIVITY_TYPE_UPDATE_POLICY: "ACTIVITY_TYPE_UPDATE_POLICY_V2", + ACTIVITY_TYPE_INIT_OTP_AUTH: "ACTIVITY_TYPE_INIT_OTP_AUTH_V2", +}; + +const METHODS_WITH_ONLY_OPTIONAL_PARAMETERS = [ + "getActivities", + "getApiKeys", + "getOrganization", + "getPolicies", + "getPrivateKeys", + "getSubOrgIds", + "getUsers", + "getWallets", + "getWhoami", + "listPrivateKeys", + "listUserTags", +]; + +/** + * @param {string} methodName + * @returns {string} + */ +function methodTypeFromMethodName(methodName) { + if (["approveActivity", "rejectActivity"].includes(methodName)) { + return "activityDecision"; + } + if (methodName.startsWith("nOOP")) { + return "noop"; + } + // TODO: filter out unnecessary client methods, whether here or from the source + if ( + methodName.startsWith("get") || + methodName.startsWith("list") || + methodName.startsWith("test") + ) { + return "query"; + } + return "activity"; +} + +// Helper that takes in swagger definitions and returns a map containing the latest version of a field. +// The intent is to consolidate a field with multiple versions (e.g. v1CreateSubOrganizationResult, v1CreateSubOrganizationResultV2...) +// in order to get just the latest (v1CreateSubOrganizationResultV4). +function extractLatestVersions(definitions) { + const latestVersions = {}; + + // Regex to separate the version prefix, base activity details, and (optional) activity version + const keyVersionRegex = /^(v\d+)([A-Z][a-z]+(?:[A-Z][a-z]+)*)(V\d+)?$/; + + Object.keys(definitions).forEach((key) => { + const match = key.match(keyVersionRegex); + if (match) { + const fullName = match[0]; + const baseName = match[2]; // Field without any version-related prefixes or suffixes + const versionSuffix = match[3]; // Version (optional) + const formattedKeyName = + baseName.charAt(0).toLowerCase() + + baseName.slice(1) + + (versionSuffix || ""); // Reconstruct the original key with version + + // Determine if this version is newer or if no version was previously stored + if ( + !latestVersions[baseName] || + versionSuffix > (latestVersions[baseName].versionSuffix || "") + ) { + latestVersions[baseName] = { + fullName, + formattedKeyName, + versionSuffix, + }; + } + } + }); + + return latestVersions; +} + +const generateSDKClientFromSwagger = async ( + swaggerSpec, + authProxySwaggerSpec, + targetPath, +) => { + const namespace = swaggerSpec.tags?.find((item) => item.name != null)?.name; + const authProxyNamespace = authProxySwaggerSpec.tags?.find( + (item) => item.name != null, + )?.name; + + /** @type {Array} */ + const codeBuffer = []; + + /** @type {Array} */ + const imports = []; + + imports.push( + 'import { TERMINAL_ACTIVITY_STATUSES, TActivityResponse, TActivityStatus, TSignedRequest } from "@turnkey/http";', + ); + + imports.push( + 'import { GrpcStatus, TStamper, TurnkeyRequestError, TurnkeyHttpClientConfig, StorageBase } from "../__types__/base";', + ); + + imports.push('import { VERSION } from "../__generated__/version";'); + + imports.push('import type * as SdkTypes from "@turnkey/sdk-types";'); + imports.push( + 'import { TurnkeyError, TurnkeyErrorCodes } from "@turnkey/sdk-types";', + ); + + imports.push('import { StamperType } from "../__types__/base";'); + + codeBuffer.push(` + export class TurnkeySDKClientBase { + config: TurnkeyHttpClientConfig; + + // Store stampers + private apiKeyStamper?: TStamper | undefined; + private passkeyStamper?: TStamper | undefined; + private walletStamper?: TStamper | undefined; + + + // Storage manager + private storageManager?: StorageBase | undefined; + + constructor(config: TurnkeyHttpClientConfig) { + this.config = config; + + if (config.apiKeyStamper) { + this.apiKeyStamper = config.apiKeyStamper; + } + if (config.passkeyStamper) { + this.passkeyStamper = config.passkeyStamper; + } + if (config.walletStamper) { + this.walletStamper = config.walletStamper; + } + if (config.storageManager) { + this.storageManager = config.storageManager; + } + } + + private getStamper(stampWith?: StamperType): TStamper | undefined { + if (!stampWith) return this.apiKeyStamper || this.passkeyStamper || this.walletStamper; + + switch (stampWith) { + case StamperType.ApiKey: + return this.apiKeyStamper; + case StamperType.Passkey: + return this.passkeyStamper; + case StamperType.Wallet: + return this.walletStamper; + default: + return this.apiKeyStamper; + } + } + + async request( + url: string, + body: TBodyType, + stampWith?: StamperType + ): Promise { + const fullUrl = this.config.apiBaseUrl + url; + const stringifiedBody = JSON.stringify(body); + var headers: Record = { + "X-Client-Version": VERSION + } + + // Use the specified stamper for this request + const activeStamper = this.getStamper(stampWith); + + if (activeStamper) { + const stamp = await activeStamper.stamp(stringifiedBody); + headers[stamp.stampHeaderName] = stamp.stampHeaderValue + } + + if (this.config.readOnlySession){ + headers["X-Session"] = this.config.readOnlySession + } + + const response = await fetch(fullUrl, { + method: "POST", + headers: headers, + body: stringifiedBody, + redirect: "follow" + }); + + if (!response.ok) { + let res: GrpcStatus; + try { + res = await response.json(); + } catch (_) { + throw new Error(\`\${response.status} \${response.statusText}\`); + } + + throw new TurnkeyRequestError(res); + } + + const data = await response.json(); + return data as TResponseType; + } + + async activity( + url: string, + body: TBodyType, + resultKey: string, + stampWith?: StamperType + ): Promise { + const pollingDuration = this.config.activityPoller?.intervalMs ?? 1000; + const maxRetries = this.config.activityPoller?.numRetries ?? 3; + + const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)); + + const handleResponse = (activityData: TActivityResponse): TResponseType => { + const { result, status } = activityData.activity; + + if (status === "ACTIVITY_STATUS_COMPLETED") { + return { + ...result[\`\${resultKey}\` as keyof SdkTypes.v1Result], + ...activityData + } as TResponseType; + } + + return activityData as TResponseType; + }; + + let attempts = 0; + + const pollStatus = async (activityId: string): Promise => { + const pollBody = { activityId }; + // Pass the stampWith parameter to getActivity + const pollData = await this.getActivity(pollBody, stampWith) as TActivityResponse; + + if (attempts > maxRetries) { + return handleResponse(pollData); + } + + attempts += 1; + + if (!TERMINAL_ACTIVITY_STATUSES.includes(pollData.activity.status as TActivityStatus)) { + await sleep(pollingDuration); + return pollStatus(activityId); + } + + return handleResponse(pollData); + }; + + // Use the specified stamper for the initial request + const responseData = await this.request(url, body, stampWith) as TActivityResponse; + + if (!TERMINAL_ACTIVITY_STATUSES.includes(responseData.activity.status as TActivityStatus)) { + return pollStatus(responseData.activity.id); + } + + return handleResponse(responseData); + } + + async activityDecision( + url: string, + body: TBodyType, + stampWith?: StamperType + ): Promise { + // Use the specified stamper for this request + const activityData = await this.request(url, body, stampWith) as TActivityResponse; + + return { + ...activityData["activity"]["result"], + ...activityData + } as TResponseType; + } + + async authProxyRequest( + url: string, + body: TBodyType, + ): Promise { + if (!this.config.authProxyUrl || !this.config.authProxyConfigId) { + throw new TurnkeyError("Auth Proxy URL or ID is not configured.", TurnkeyErrorCodes.INVALID_CONFIGURATION); + } + const fullUrl = this.config.authProxyUrl + url; + const stringifiedBody = JSON.stringify(body); + var headers: Record = { + "Content-Type": "application/json", + "X-Auth-Proxy-Config-ID": this.config.authProxyConfigId, + } + + const response = await fetch(fullUrl, { + method: "POST", + headers: headers, + body: stringifiedBody, + }); + + if (!response.ok) { + let res: GrpcStatus; + try { + res = await response.json(); + } catch (_) { + throw new Error(\`\${response.status} \${response.statusText}\`); + } + + throw new TurnkeyRequestError(res); + } + + const data = await response.json(); + return data as TResponseType; + }`); + const latestVersions = extractLatestVersions(swaggerSpec.definitions); + + for (const endpointPath in swaggerSpec.paths) { + const methodMap = swaggerSpec.paths[endpointPath]; + const operation = methodMap.post; + const operationId = operation.operationId; + + const operationNameWithoutNamespace = operationId.replace( + new RegExp(`${namespace}_`), + "", + ); + + if (operationNameWithoutNamespace === "NOOPCodegenAnchor") { + continue; + } + + const methodName = `${ + operationNameWithoutNamespace.charAt(0).toLowerCase() + + operationNameWithoutNamespace.slice(1) + }`; + + const methodType = methodTypeFromMethodName(methodName); + const inputType = `T${operationNameWithoutNamespace}Body`; + const responseType = `T${operationNameWithoutNamespace}Response`; + + // For query methods + if (methodType === "query") { + codeBuffer.push( + `\n\t${methodName} = async (input: SdkTypes.${inputType}${ + METHODS_WITH_ONLY_OPTIONAL_PARAMETERS.includes(methodName) + ? " = {}" + : "" + }, stampWith?: StamperType): Promise => { + const session = await this.storageManager?.getActiveSession(); + return this.request("${endpointPath}", { + ...input, + organizationId: input.organizationId ?? session?.organizationId ?? this.config.organizationId + }, stampWith); + }`, + ); + } else if (methodType === "activity") { + // For activity methods + const unversionedActivityType = `ACTIVITY_TYPE_${operationNameWithoutNamespace + .replace(/([a-z])([A-Z])/g, "$1_$2") + .toUpperCase()}`; + const versionedActivityType = + VERSIONED_ACTIVITY_TYPES[unversionedActivityType]; + + const resultKey = operationNameWithoutNamespace + "Result"; + const versionedMethodName = latestVersions[resultKey].formattedKeyName; + + codeBuffer.push( + `\n\t${methodName} = async (input: SdkTypes.${inputType}, stampWith?: StamperType): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity("${endpointPath}", { + parameters: rest, + organizationId: organizationId ?? (session?.organizationId ?? this.config.organizationId), + timestampMs: timestampMs ?? String(Date.now()), + type: "${versionedActivityType ?? unversionedActivityType}" + }, "${versionedMethodName}", stampWith); + }`, + ); + } else if (methodType === "activityDecision") { + // For activityDecision methods + codeBuffer.push( + `\n\t${methodName} = async (input: SdkTypes.${inputType}, stampWith?: StamperType): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + return this.activityDecision("${endpointPath}", + { + parameters: rest, + organizationId: organizationId ?? (session?.organizationId ?? this.config.organizationId), + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_${operationNameWithoutNamespace + .replace(/([a-z])([A-Z])/g, "$1_$2") + .toUpperCase()}" + }, stampWith); + }`, + ); + } + + const unversionedActivityType = `ACTIVITY_TYPE_${operationNameWithoutNamespace + .replace(/([a-z])([A-Z])/g, "$1_$2") + .toUpperCase()}`; + const versionedActivityType = + VERSIONED_ACTIVITY_TYPES[unversionedActivityType]; + + // generate a stamping method for each method + codeBuffer.push( + `\n\tstamp${operationNameWithoutNamespace} = async (input: SdkTypes.${inputType}, stampWith?: StamperType): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId${methodType === "activity" || methodType === "activityDecision" ? ", timestampMs" : ""}, ...parameters } = input; + + const fullUrl = this.config.apiBaseUrl + "${endpointPath}"; + const bodyWithType = { + parameters, + organizationId,${ + methodType === "activity" || methodType === "activityDecision" + ? "\n timestampMs: timestampMs ?? String(Date.now())," + : "" + } + type: "${versionedActivityType ?? unversionedActivityType}" + }; + + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }`, + ); + } + + for (const endpointPath in authProxySwaggerSpec.paths) { + const methodMap = authProxySwaggerSpec.paths[endpointPath]; + const operation = methodMap.post; + const operationId = operation.operationId; + + const operationNameWithoutNamespace = operationId.replace( + new RegExp(`${authProxyNamespace}_`), + "", + ); + + const methodName = `proxy${ + operationNameWithoutNamespace.charAt(0).toUpperCase() + + operationNameWithoutNamespace.slice(1) + }`; + + const inputType = `ProxyT${operationNameWithoutNamespace}Body`; + const responseType = `ProxyT${operationNameWithoutNamespace}Response`; + + codeBuffer.push( + `\n\t${methodName} = async (input: SdkTypes.${inputType}${ + METHODS_WITH_ONLY_OPTIONAL_PARAMETERS.includes(methodName) + ? " = {}" + : "" + }): Promise => { + return this.authProxyRequest("${endpointPath}", input); + }`, + ); + } + + // End of the TurnkeySDKClient Class Definition + codeBuffer.push(`}`); + + await fs.promises.writeFile( + targetPath, + [COMMENT_HEADER].concat(imports).concat(codeBuffer).join("\n\n"), + ); +}; + +// Main Runner +main().catch((error) => { + console.error(error); + process.exit(1); +}); + +async function main() { + const swaggerSpecFile = await fs.promises.readFile( + PUBLIC_API_SWAGGER_PATH, + "utf-8", + ); + const authProxySwaggerSpecFile = await fs.promises.readFile( + AUTH_PROXY_SWAGGER_PATH, + "utf-8", + ); + + const swaggerSpec = JSON.parse(swaggerSpecFile); + const authProxySwaggerSpec = JSON.parse(authProxySwaggerSpecFile); + + await generateSDKClientFromSwagger( + swaggerSpec, + authProxySwaggerSpec, + TARGET_SDK_CLIENT_PATH, + ); +} diff --git a/packages/core/src/__clients__/core.ts b/packages/core/src/__clients__/core.ts new file mode 100644 index 000000000..d65134326 --- /dev/null +++ b/packages/core/src/__clients__/core.ts @@ -0,0 +1,3749 @@ +import { TurnkeySDKClientBase } from "../__generated__/sdk-client-base"; +import { + TDeleteSubOrganizationResponse, + Session, + TStampLoginResponse, + v1AddressFormat, + v1Attestation, + v1Pagination, + v1SignRawPayloadResult, + v1TransactionType, + v1User, + TurnkeyError, + TurnkeyErrorCodes, + TurnkeyNetworkError, + ProxyTGetWalletKitConfigResponse, + v1WalletAccountParams, + v1PayloadEncoding, + v1HashFunction, + v1Curve, +} from "@turnkey/sdk-types"; +import { + DEFAULT_SESSION_EXPIRATION_IN_SECONDS, + ExportBundle, + StamperType, + User, + TurnkeySDKClientConfig, + WalletAccount, + Wallet, + OtpType, + OtpTypeToFilterTypeMap, + CreateSubOrgParams, + Chain, + FilterType, + EmbeddedWallet, + WalletSource, + ConnectedWallet, + Curve, + StorageBase, + SessionKey, + EmbeddedWalletAccount, + ConnectedWalletAccount, + WalletManagerBase, + WalletProvider, + SwitchableChain, +} from "../__types__/base"; // TODO (Amir): How many of these should we keep in sdk-types +import { + buildSignUpBody, + generateWalletAccountsFromAddressFormat, + getEncodedMessage, + getHashFunction, + getEncodingType, + isReactNative, + isWalletAccountArray, + isWeb, + toExternalTimestamp, + splitSignature, + getWalletAccountMethods, + getPublicKeyFromStampHeader, + isEthereumWallet, + isSolanaWallet, + broadcastTransaction, + googleISS, + withTurnkeyErrorHandling, +} from "@utils"; +import { createStorageManager } from "../__storage__/base"; +import { CrossPlatformApiKeyStamper } from "../__stampers__/api/base"; +import { CrossPlatformPasskeyStamper } from "../__stampers__/passkey/base"; +import { + DEFAULT_ETHEREUM_ACCOUNTS, + DEFAULT_SOLANA_ACCOUNTS, +} from "../turnkey-helpers"; +import { jwtDecode } from "jwt-decode"; +import { createWalletManager } from "../__wallet__/base"; +import { toUtf8Bytes } from "ethers"; + +// Gathers all public methods exposed in our core client and turns it into a type that +// can be used to extend clients created for other packages built off core +// +// Should be used to keep any packages that extend this core package in sync with each +// other, meaning any new additions to core should also be reflected in those packages +type PublicMethods = { + [K in keyof T as K extends string | number | symbol + ? K extends + | "init" + | "constructor" + | "config" + | "httpClient" + | "user" + | "wallets" + ? never + : K + : never]: T[K] extends (...args: any[]) => any ? T[K] : never; +}; +export type TurnkeyClientMethods = PublicMethods; + +export class TurnkeyClient { + config: TurnkeySDKClientConfig; + httpClient!: TurnkeySDKClientBase; + + private apiKeyStamper?: CrossPlatformApiKeyStamper | undefined; + private passkeyStamper?: CrossPlatformPasskeyStamper | undefined; + private walletManager?: WalletManagerBase | undefined; + private storageManager!: StorageBase; + + constructor( + config: TurnkeySDKClientConfig, + + // Users can pass in their own stampers, or we will create them. Should we remove this? + apiKeyStamper?: CrossPlatformApiKeyStamper, + passkeyStamper?: CrossPlatformPasskeyStamper, + walletManager?: WalletManagerBase, + ) { + this.config = config; + + // Just store any explicitly provided stampers + this.apiKeyStamper = apiKeyStamper; + this.passkeyStamper = passkeyStamper; + this.walletManager = walletManager; + + // Actual initialization will happen in init() + } + + async init() { + // Initialize storage manager + // TODO (Amir): StorageManager should be a class that extends StorageBase and has an init method + this.storageManager = await createStorageManager(); + + // Initialize the API key stamper + this.apiKeyStamper = new CrossPlatformApiKeyStamper(this.storageManager); + await this.apiKeyStamper.init(); + + if (this.config.passkeyConfig) { + this.passkeyStamper = new CrossPlatformPasskeyStamper( + this.config.passkeyConfig, + ); + await this.passkeyStamper.init(); + } + + if ( + this.config.walletConfig?.features?.auth || + this.config.walletConfig?.features?.connecting + ) { + this.walletManager = await createWalletManager(this.config.walletConfig); + } + + // We can comfortably default to the prod urls here + const apiBaseUrl = this.config.apiBaseUrl || "https://api.turnkey.com"; + const authProxyUrl = + this.config.authProxyUrl || "https://authproxy.turnkey.com"; + + // Initialize the HTTP client with the appropriate stampers + this.httpClient = new TurnkeySDKClientBase({ + ...this.config, + apiBaseUrl, + authProxyUrl, + apiKeyStamper: this.apiKeyStamper, + passkeyStamper: this.passkeyStamper, + walletStamper: this.walletManager?.stamper, + storageManager: this.storageManager, + }); + } + + /** + * Creates a new passkey authenticator for the user. + * + * - This function generates a new passkey attestation and challenge, suitable for registration with the user's device. + * - Handles both web and React Native environments, automatically selecting the appropriate passkey creation flow. + * - The resulting attestation and challenge can be used to register the passkey with Turnkey. + * + * @param params.name - name of the passkey. If not provided, defaults to "A Passkey". + * @param params.displayName - display name for the passkey. If not provided, defaults to "A Passkey". + * @param params.stampWith - parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + * @returns A promise that resolves to an object containing: + * - attestation: attestation object returned from the passkey creation process. + * - encodedChallenge: encoded challenge string used for passkey registration. + * @throws {TurnkeyError} If there is an error during passkey creation, or if the platform is unsupported. + */ + createPasskey = async (params?: { + name?: string; + displayName?: string; + stampWith?: StamperType | undefined; + }): Promise<{ attestation: v1Attestation; encodedChallenge: string }> => { + return withTurnkeyErrorHandling( + async () => { + const name = params?.name || "A Passkey"; + const displayName = params?.displayName || "A Passkey"; + let passkey: { encodedChallenge: string; attestation: v1Attestation }; + if (isWeb()) { + const res = await this.passkeyStamper?.createWebPasskey({ + publicKey: { + user: { + name, + displayName, + }, + }, + }); + if (!res) { + throw new TurnkeyError( + "Failed to create React Native passkey", + TurnkeyErrorCodes.INTERNAL_ERROR, + ); + } + passkey = { + encodedChallenge: res?.encodedChallenge, + attestation: res?.attestation, + }; + } else if (isReactNative()) { + const res = await this.passkeyStamper?.createReactNativePasskey({ + name, + displayName, + }); + if (!res) { + throw new TurnkeyError( + "Failed to create React Native passkey", + TurnkeyErrorCodes.INTERNAL_ERROR, + ); + } + passkey = { + encodedChallenge: res?.challenge, + attestation: res?.attestation, + }; + } else { + throw new TurnkeyError( + "Unsupported platform for passkey creation", + TurnkeyErrorCodes.INVALID_REQUEST, + ); + } + + return passkey; + }, + { + errorMessage: "Failed to create passkey", + errorCode: TurnkeyErrorCodes.CREATE_PASSKEY_ERROR, + customMessageByMessages: { + "timed out or was not allowed": { + message: "Passkey creation was cancelled by the user.", + code: TurnkeyErrorCodes.SELECT_PASSKEY_CANCELLED, + }, + }, + }, + ); + }; + + /** + * Logs out the current client session. + * + * - This function clears the specified session and removes any associated key pairs from storage. + * - If a sessionKey is provided, it logs out from that session; otherwise, it logs out from the active session. + * - Cleans up any api keys associated with the session. + * + * @param params.sessionKey - session key to specify which session to log out from (defaults to the active session). + * @returns A promise that resolves when the logout process is complete. + * @throws {TurnkeyError} If there is no active session or if there is an error during the logout process. + */ + logout = async (params?: { sessionKey?: string }): Promise => { + withTurnkeyErrorHandling( + async () => { + if (params?.sessionKey) { + const session = await this.storageManager.getSession( + params.sessionKey, + ); + this.storageManager.clearSession(params.sessionKey); + this.apiKeyStamper?.deleteKeyPair(session?.publicKey!); + } else { + const sessionKey = await this.storageManager.getActiveSessionKey(); + const session = await this.storageManager.getActiveSession(); + if (sessionKey) { + this.storageManager.clearSession(sessionKey); + this.apiKeyStamper?.deleteKeyPair(session?.publicKey!); + } else { + throw new TurnkeyError( + "No active session found to log out from.", + TurnkeyErrorCodes.NO_SESSION_FOUND, + ); + } + } + }, + { + errorMessage: "Failed to log out", + errorCode: TurnkeyErrorCodes.LOGOUT_ERROR, + }, + ); + }; + + /** + * Logs in a user using a passkey, optionally specifying the public key, session key, and session expiration. + * + * - This function initiates the login process with a passkey and handles session creation and storage. + * - If a public key is not provided, a new key pair will be generated for authentication. + * - If a session key is not provided, the default session key will be used. + * - The session expiration can be customized via the expirationSeconds parameter. + * - Handles cleanup of unused key pairs if login fails. + * + * @param params.publicKey - public key to use for authentication. If not provided, a new key pair will be generated. + * @param params.sessionKey - session key to use for session creation (defaults to the default session key). + * @param params.expirationSeconds - session expiration time in seconds (defaults to the configured default). + * @returns A promise that resolves to a signed JWT session token. + * @throws {TurnkeyError} If there is an error during the passkey login process or if the user cancels the passkey prompt. + */ + loginWithPasskey = async (params?: { + publicKey?: string; + sessionKey?: string; + expirationSeconds?: string; + }): Promise => { + let generatedKeyPair: string | undefined = undefined; + return await withTurnkeyErrorHandling( + async () => { + generatedKeyPair = + params?.publicKey || (await this.apiKeyStamper?.createKeyPair()); + const sessionKey = params?.sessionKey || SessionKey.DefaultSessionkey; + + const expirationSeconds = + params?.expirationSeconds || DEFAULT_SESSION_EXPIRATION_IN_SECONDS; + + if (!generatedKeyPair) { + throw new TurnkeyError( + "A publickey could not be found or generated.", + TurnkeyErrorCodes.INTERNAL_ERROR, + ); + } + const sessionResponse = await this.httpClient.stampLogin( + { + publicKey: generatedKeyPair, + organizationId: this.config.organizationId, + expirationSeconds, + }, + StamperType.Passkey, + ); + + await this.storeSession({ + sessionToken: sessionResponse.session, + sessionKey, + }); + + generatedKeyPair = undefined; // Key pair was successfully used, set to null to prevent cleanup + + return sessionResponse.session; + }, + { + errorMessage: "Unable to log in with the provided passkey", + errorCode: TurnkeyErrorCodes.PASSKEY_LOGIN_AUTH_ERROR, + customMessageByMessages: { + "timed out or was not allowed": { + message: "Passkey login was cancelled by the user.", + code: TurnkeyErrorCodes.SELECT_PASSKEY_CANCELLED, + }, + }, + }, + { + finallyFn: async () => { + if (generatedKeyPair) { + try { + await this.apiKeyStamper?.deleteKeyPair(generatedKeyPair); + } catch (cleanupError) { + throw new TurnkeyError( + `Failed to clean up generated key pair`, + TurnkeyErrorCodes.KEY_PAIR_CLEANUP_ERROR, + cleanupError, + ); + } + } + }, + }, + ); + }; + + /** + * Signs up a user using a passkey, creating a new sub-organization and session. + * + * - This function creates a new passkey authenticator and uses it to register a new sub-organization for the user. + * - Handles both passkey creation and sub-organization creation in a single flow. + * - Optionally accepts additional sub-organization parameters, a custom session key, a custom passkey display name, and a custom session expiration. + * - Automatically generates a new API key pair for authentication and session management. + * - Stores the resulting session token and manages cleanup of unused key pairs. + * + * @param params.createSubOrgParams - parameters for creating a sub-organization (e.g., authenticators, user metadata). + * @param params.sessionKey - session key to use for storing the session (defaults to the default session key). + * @param params.passkeyDisplayName - display name for the passkey (defaults to a generated name based on the current timestamp). + * @param params.expirationSeconds - session expiration time in seconds (defaults to the configured default). + * @returns A promise that resolves to a signed JWT session token for the new sub-organization. + * @throws {TurnkeyError} If there is an error during passkey creation, sub-organization creation, or session storage. + */ + signUpWithPasskey = async (params?: { + createSubOrgParams?: CreateSubOrgParams; + sessionKey?: string; + passkeyDisplayName?: string; + expirationSeconds?: string; + }): Promise => { + const { + createSubOrgParams, + passkeyDisplayName, + sessionKey = SessionKey.DefaultSessionkey, + expirationSeconds = DEFAULT_SESSION_EXPIRATION_IN_SECONDS, + } = params || {}; + + let generatedKeyPair: string | undefined = undefined; + return withTurnkeyErrorHandling( + async () => { + generatedKeyPair = await this.apiKeyStamper?.createKeyPair(); + const passkeyName = passkeyDisplayName || `passkey-${Date.now()}`; + + // A passkey will be created automatically when you call this function. The name is passed in + const passkey = await this.createPasskey({ + name: passkeyName, + displayName: passkeyName, + }); + + if (!passkey) { + throw new TurnkeyError( + "Failed to create passkey: encoded challenge or attestation is missing", + TurnkeyErrorCodes.INTERNAL_ERROR, + ); + } + + const signUpBody = buildSignUpBody({ + createSubOrgParams: { + ...createSubOrgParams, + authenticators: [ + ...(createSubOrgParams?.authenticators ?? []), // Any extra authenticators can be passed into createSubOrgParams + { + // Add our passkey that we made earlier. + authenticatorName: passkeyName, // Ensure the name in orgData is the same name as the created passkey + challenge: passkey.encodedChallenge, + attestation: passkey.attestation, + }, + ], + apiKeys: [ + { + apiKeyName: `passkey-auth-${generatedKeyPair}`, + publicKey: generatedKeyPair!, + curveType: "API_KEY_CURVE_P256", + expirationSeconds: "60", + }, + ], + }, + }); + + const res = await this.httpClient.proxySignup(signUpBody); + + if (!res) { + throw new TurnkeyError( + `Sign up failed`, + TurnkeyErrorCodes.PASSKEY_SIGNUP_AUTH_ERROR, + ); + } + + const newGeneratedKeyPair = await this.apiKeyStamper?.createKeyPair(); + this.apiKeyStamper?.setPublicKeyOverride(generatedKeyPair!); + + const sessionResponse = await this.httpClient.stampLogin({ + publicKey: newGeneratedKeyPair!, + organizationId: this.config.organizationId, + expirationSeconds, + }); + + await this.apiKeyStamper?.deleteKeyPair(generatedKeyPair!); + + await this.storeSession({ + sessionToken: sessionResponse.session, + sessionKey, + }); + + generatedKeyPair = undefined; // Key pair was successfully used, set to null to prevent cleanup + + return sessionResponse.session; + }, + { + errorCode: TurnkeyErrorCodes.PASSKEY_SIGNUP_AUTH_ERROR, + errorMessage: "Failed to sign up with passkey", + }, + { + finallyFn: async () => { + this.apiKeyStamper?.clearPublicKeyOverride(); + if (generatedKeyPair) { + try { + await this.apiKeyStamper?.deleteKeyPair(generatedKeyPair); + } catch (cleanupError) { + throw new TurnkeyError( + `Failed to clean up generated key pair`, + TurnkeyErrorCodes.KEY_PAIR_CLEANUP_ERROR, + cleanupError, + ); + } + } + }, + }, + ); + }; + + /** + * Retrieves wallet providers from the initialized wallet manager. + * + * - Optionally filters providers by the specified blockchain chain. + * - Throws an error if the wallet manager is not initialized. + * + * @param chain - optional blockchain chain to filter the returned providers. + * @returns A promise that resolves to an array of wallet providers. + * @throws {TurnkeyError} If the wallet manager is uninitialized or provider retrieval fails. + */ + getWalletProviders = async (chain?: Chain): Promise => { + return withTurnkeyErrorHandling( + async () => { + if (!this.walletManager) { + throw new TurnkeyError( + "Wallet manager is not initialized", + TurnkeyErrorCodes.WALLET_MANAGER_COMPONENT_NOT_INITIALIZED, + ); + } + + return await this.walletManager.getProviders(chain); + }, + { + errorMessage: "Unable to get wallet providers", + errorCode: TurnkeyErrorCodes.FETCH_WALLETS_ERROR, + }, + ); + }; + + /** + * Connects the specified wallet account. + * + * - Requires the wallet manager and its connector to be initialized. + * + * @param walletProvider - wallet provider to connect. + * @returns A promise that resolves once the wallet account is connected. + * @throws {TurnkeyError} If the wallet manager is uninitialized or the connection fails. + */ + connectWalletAccount = async (walletProvider: WalletProvider) => { + return withTurnkeyErrorHandling( + async () => { + if (!this.walletManager?.connector) { + throw new TurnkeyError( + "Wallet connector is not initialized", + TurnkeyErrorCodes.WALLET_MANAGER_COMPONENT_NOT_INITIALIZED, + ); + } + await this.walletManager.connector.connectWalletAccount(walletProvider); + }, + { + errorMessage: "Unable to connect wallet account", + errorCode: TurnkeyErrorCodes.CONNECT_WALLET_ACCOUNT_ERROR, + }, + ); + }; + + /** + * Disconnects the specified wallet account. + * + * - Requires the wallet manager and its connector to be initialized. + * + * @param walletProvider - wallet provider to disconnect. + * @returns A promise that resolves once the wallet account is disconnected. + * @throws {TurnkeyError} If the wallet manager is uninitialized or the disconnection fails. + */ + disconnectWalletAccount = async (walletProvider: WalletProvider) => { + return withTurnkeyErrorHandling( + async () => { + if (!this.walletManager?.connector) { + throw new TurnkeyError( + "Wallet connector is not initialized", + TurnkeyErrorCodes.WALLET_MANAGER_COMPONENT_NOT_INITIALIZED, + ); + } + + await this.walletManager.connector.disconnectWalletAccount( + walletProvider, + ); + }, + { + errorMessage: "Unable to disconnect wallet account", + errorCode: TurnkeyErrorCodes.DISCONNECT_WALLET_ACCOUNT_ERROR, + }, + ); + }; + + /** + * Switches the specified wallet provider to a different blockchain chain. + * + * - Requires the wallet manager and its connector to be initialized. + * - The wallet provider must have at least one connected address. + * - Does nothing if the wallet provider is already on the desired chain. + * + * @param walletProvider - wallet provider to switch. + * @param chainOrId - target chain as a chain ID string or SwitchableChain object. + * @returns A promise that resolves once the chain switch is complete. + * @throws {TurnkeyError} If the wallet manager is uninitialized, the provider is not connected, or the switch fails. + */ + switchWalletProviderChain = async ( + walletProvider: WalletProvider, + chainOrId: string | SwitchableChain, + ): Promise => { + return withTurnkeyErrorHandling( + async () => { + if (!this.walletManager?.connector) { + throw new TurnkeyError( + "Wallet connector is not initialized", + TurnkeyErrorCodes.WALLET_MANAGER_COMPONENT_NOT_INITIALIZED, + ); + } + + if (walletProvider.connectedAddresses.length === 0) { + throw new TurnkeyError( + "You can not switch chains for a provider that is not connected", + TurnkeyErrorCodes.INVALID_REQUEST, + ); + } + + // if the wallet provider is already on the desired chain, do nothing + if (walletProvider.chainInfo.namespace === chainOrId) { + return; + } + + await this.walletManager.connector.switchChain( + walletProvider, + chainOrId, + ); + }, + { + errorMessage: "Unable to switch wallet account chain", + errorCode: TurnkeyErrorCodes.SWITCH_WALLET_CHAIN_ERROR, + }, + ); + }; + + /** + * Logs in a user using the specified wallet provider. + * + * - This function logs in a user by authenticating with the provided wallet provider via a wallet-based signature. + * - If a public key is not provided, a new one will be generated for authentication. + * - Optionally accepts a custom session key and session expiration time. + * - Stores the resulting session token under the specified session key, or the default session key if not provided. + * - Throws an error if a public key cannot be found or generated, or if the login process fails. + * + * @param params.walletProvider - wallet provider to use for authentication. + * @param params.publicKey - optional public key to associate with the session (generated if not provided). + * @param params.sessionKey - optional key to store the session under (defaults to the default session key). + * @param params.expirationSeconds - optional session expiration time in seconds (defaults to the configured default). + * @returns A promise that resolves to the created session token. + * @throws {TurnkeyError} If the wallet stamper is uninitialized, a public key cannot be found or generated, or login fails. + */ + loginWithWallet = async (params: { + walletProvider: WalletProvider; + publicKey?: string; + sessionKey?: string; + expirationSeconds?: string; + }): Promise => { + let publicKey = + params.publicKey || (await this.apiKeyStamper?.createKeyPair()); + return withTurnkeyErrorHandling( + async () => { + if (!this.walletManager?.stamper) { + throw new TurnkeyError( + "Wallet stamper is not initialized", + TurnkeyErrorCodes.WALLET_MANAGER_COMPONENT_NOT_INITIALIZED, + ); + } + const sessionKey = params.sessionKey || SessionKey.DefaultSessionkey; + const walletProvider = params.walletProvider; + + const expirationSeconds = + params?.expirationSeconds || DEFAULT_SESSION_EXPIRATION_IN_SECONDS; + + if (!publicKey) { + throw new TurnkeyError( + "A publickey could not be found or generated.", + TurnkeyErrorCodes.INTERNAL_ERROR, + ); + } + + this.walletManager.stamper.setProvider( + walletProvider.interfaceType, + walletProvider, + ); + + const sessionResponse = await this.httpClient.stampLogin( + { + publicKey, + organizationId: this.config.organizationId, + expirationSeconds, + }, + StamperType.Wallet, + ); + + await this.storeSession({ + sessionToken: sessionResponse.session, + sessionKey, + }); + + return sessionResponse.session; + }, + { + errorMessage: "Unable to log in with the provided wallet", + errorCode: TurnkeyErrorCodes.WALLET_LOGIN_AUTH_ERROR, + }, + { + finallyFn: async () => { + // Clean up the generated key pair if it wasn't successfully used + this.apiKeyStamper?.clearPublicKeyOverride(); + if (publicKey) { + try { + await this.apiKeyStamper?.deleteKeyPair(publicKey); + } catch (cleanupError) { + throw new TurnkeyError( + "Failed to clean up generated key pair", + TurnkeyErrorCodes.KEY_PAIR_CLEANUP_ERROR, + cleanupError, + ); + } + } + }, + }, + ); + }; + + /** + * Signs up a user using a wallet, creating a new sub-organization and session. + * + * - This function creates a new wallet authenticator and uses it to register a new sub-organization for the user. + * - Handles both wallet authentication and sub-organization creation in a single flow. + * - Optionally accepts additional sub-organization parameters, a custom session key, and a custom session expiration. + * - Automatically generates additional API key pairs for authentication and session management. + * - Stores the resulting session token under the specified session key, or the default session key if not provided, and manages cleanup of unused key pairs. + * + * @param params.walletProvider - wallet provider to use for authentication. + * @param params.createSubOrgParams - parameters for creating a sub-organization (e.g., authenticators, user metadata). + * @param params.sessionKey - session key to use for storing the session (defaults to the default session key). + * @param params.expirationSeconds - session expiration time in seconds (defaults to the configured default). + * @returns A promise that resolves to a signed JWT session token for the new sub-organization. + * @throws {TurnkeyError} If there is an error during wallet authentication, sub-organization creation, session storage, or cleanup. + */ + signUpWithWallet = async (params: { + walletProvider: WalletProvider; + createSubOrgParams?: CreateSubOrgParams; + sessionKey?: string; + expirationSeconds?: string; + }): Promise => { + const { + walletProvider, + createSubOrgParams, + sessionKey = SessionKey.DefaultSessionkey, + expirationSeconds = DEFAULT_SESSION_EXPIRATION_IN_SECONDS, + } = params; + + let generatedKeyPair: string | undefined = undefined; + return withTurnkeyErrorHandling( + async () => { + if (!this.walletManager?.stamper) { + throw new TurnkeyError( + "Wallet stamper is not initialized", + TurnkeyErrorCodes.WALLET_MANAGER_COMPONENT_NOT_INITIALIZED, + ); + } + + generatedKeyPair = await this.apiKeyStamper?.createKeyPair(); + + this.walletManager.stamper.setProvider( + walletProvider.interfaceType, + walletProvider, + ); + + const publicKey = await this.walletManager.stamper.getPublicKey( + walletProvider.interfaceType, + walletProvider, + ); + + if (!publicKey) { + throw new TurnkeyError( + "Failed to get public key from wallet", + TurnkeyErrorCodes.WALLET_SIGNUP_AUTH_ERROR, + ); + } + + const signUpBody = buildSignUpBody({ + createSubOrgParams: { + ...createSubOrgParams, + apiKeys: [ + { + apiKeyName: `wallet-auth:${publicKey}`, + publicKey: publicKey, + curveType: isEthereumWallet(walletProvider) + ? ("API_KEY_CURVE_SECP256K1" as const) + : ("API_KEY_CURVE_ED25519" as const), + }, + { + apiKeyName: `wallet-auth-${generatedKeyPair}`, + publicKey: generatedKeyPair!, + curveType: "API_KEY_CURVE_P256", + expirationSeconds: "60", + }, + ], + }, + }); + + const res = await this.httpClient.proxySignup(signUpBody); + + if (!res) { + throw new TurnkeyError( + `Sign up failed`, + TurnkeyErrorCodes.WALLET_SIGNUP_AUTH_ERROR, + ); + } + + const newGeneratedKeyPair = await this.apiKeyStamper?.createKeyPair(); + this.apiKeyStamper?.setPublicKeyOverride(generatedKeyPair!); + + const sessionResponse = await this.httpClient.stampLogin({ + publicKey: newGeneratedKeyPair!, + organizationId: this.config.organizationId, + expirationSeconds, + }); + + await this.apiKeyStamper?.deleteKeyPair(generatedKeyPair!); + + await this.storeSession({ + sessionToken: sessionResponse.session, + sessionKey, + }); + + generatedKeyPair = undefined; // Key pair was successfully used, set to null to prevent cleanup + + return sessionResponse.session; + }, + { + errorMessage: "Failed to sign up with wallet", + errorCode: TurnkeyErrorCodes.WALLET_SIGNUP_AUTH_ERROR, + }, + { + finallyFn: async () => { + // Clean up the generated key pair if it wasn't successfully used + this.apiKeyStamper?.clearPublicKeyOverride(); + if (generatedKeyPair) { + try { + await this.apiKeyStamper?.deleteKeyPair(generatedKeyPair); + } catch (cleanupError) { + throw new TurnkeyError( + "Failed to clean up generated key pair", + TurnkeyErrorCodes.KEY_PAIR_CLEANUP_ERROR, + cleanupError, + ); + } + } + }, + }, + ); + }; + + /** + * Logs in an existing user or signs up a new user using a wallet, creating a new sub-organization if needed. + * + * - This function attempts to log in the user by stamping a login request with the provided wallet. + * - If the wallet’s public key is not associated with an existing sub-organization, a new one is created. + * - Handles both wallet authentication and sub-organization creation in a single flow. + * - For Ethereum wallets, derives the public key from the signed request header; for Solana wallets, retrieves it directly from the wallet. + * - Optionally accepts additional sub-organization parameters, a custom session key, and a custom session expiration. + * - Stores the resulting session token under the specified session key, or the default session key if not provided. + * + * @param params.walletProvider - wallet provider to use for authentication. + * @param params.createSubOrgParams - optional parameters for creating a sub-organization (e.g., authenticators, user metadata). + * @param params.sessionKey - session key to use for storing the session (defaults to the default session key). + * @param params.expirationSeconds - session expiration time in seconds (defaults to the configured default). + * @returns A promise that resolves to a signed JWT session token for the sub-organization (new or existing). + * @throws {TurnkeyError} If there is an error during wallet authentication, sub-organization creation, or session storage. + */ + loginOrSignupWithWallet = async (params: { + walletProvider: WalletProvider; + createSubOrgParams?: CreateSubOrgParams; + sessionKey?: string; + expirationSeconds?: string; + }): Promise => { + const createSubOrgParams = params.createSubOrgParams; + const sessionKey = params.sessionKey || SessionKey.DefaultSessionkey; + const walletProvider = params.walletProvider; + const expirationSeconds = + params.expirationSeconds || DEFAULT_SESSION_EXPIRATION_IN_SECONDS; + + let generatedKeyPair: string | undefined = undefined; + return withTurnkeyErrorHandling( + async () => { + if (!this.walletManager?.stamper) { + throw new TurnkeyError( + "Wallet stamper is not initialized", + TurnkeyErrorCodes.WALLET_MANAGER_COMPONENT_NOT_INITIALIZED, + ); + } + generatedKeyPair = await this.apiKeyStamper?.createKeyPair(); + + this.walletManager.stamper.setProvider( + walletProvider.interfaceType, + walletProvider, + ); + + // here we sign the request with the wallet, but we don't send it to the Turnkey yet + // this is because we need to check if the subOrg exists first, and create one if it doesn't + // once we have the subOrg for the publicKey, we then can send the request to the Turnkey + const signedRequest = await withTurnkeyErrorHandling( + async () => { + return this.httpClient.stampStampLogin( + { + publicKey: generatedKeyPair!, + organizationId: this.config.organizationId, + expirationSeconds, + }, + StamperType.Wallet, + ); + }, + { + errorMessage: "Failed to create stamped request for wallet login", + errorCode: TurnkeyErrorCodes.WALLET_LOGIN_OR_SIGNUP_ERROR, + customMessageByMessages: { + "Failed to sign the message": { + message: "Wallet auth was cancelled by the user.", + code: TurnkeyErrorCodes.CONNECT_WALLET_CANCELLED, + }, + }, + }, + ); + + if (!signedRequest) { + throw new TurnkeyError( + "Failed to create stamped request for wallet login", + TurnkeyErrorCodes.BAD_RESPONSE, + ); + } + + let publicKey: string | undefined; + switch (walletProvider.chainInfo.namespace) { + case Chain.Ethereum: { + // for Ethereum, there is no way to get the public key from the wallet address + // so we derive it from the signed request + publicKey = getPublicKeyFromStampHeader( + signedRequest.stamp.stampHeaderValue, + ); + + break; + } + + case Chain.Solana: { + // for Solana, we can get the public key from the wallet address + // since the wallet address is the public key + // this doesn't require any action from the user as long as the wallet is connected + // which it has to be since they just called stampStampLogin() + publicKey = await this.walletManager.stamper.getPublicKey( + walletProvider.interfaceType, + walletProvider, + ); + break; + } + + default: + throw new TurnkeyError( + `Unsupported interface type: ${walletProvider.interfaceType}`, + TurnkeyErrorCodes.INVALID_REQUEST, + ); + } + + // here we check if the subOrg exists and create one + // then we send off the stamped request to the Turnkey + + const accountRes = await this.httpClient.proxyGetAccount({ + filterType: FilterType.PublicKey, + filterValue: publicKey, + }); + + if (!accountRes) { + throw new TurnkeyError( + `Account fetch failed`, + TurnkeyErrorCodes.ACCOUNT_FETCH_ERROR, + ); + } + + const subOrganizationId = accountRes.organizationId; + + // if there is no subOrganizationId, we create one + if (!subOrganizationId) { + const signUpBody = buildSignUpBody({ + createSubOrgParams: { + ...createSubOrgParams, + apiKeys: [ + { + apiKeyName: `wallet-auth:${publicKey}`, + publicKey: publicKey, + curveType: isEthereumWallet(walletProvider) + ? ("API_KEY_CURVE_SECP256K1" as const) + : ("API_KEY_CURVE_ED25519" as const), + }, + ], + }, + }); + + const res = await this.httpClient.proxySignup(signUpBody); + + if (!res) { + throw new TurnkeyError( + `Sign up failed`, + TurnkeyErrorCodes.WALLET_SIGNUP_AUTH_ERROR, + ); + } + } + + // now we can send the stamped request to the Turnkey + const headers: Record = { + "Content-Type": "application/json", + [signedRequest.stamp.stampHeaderName]: + signedRequest.stamp.stampHeaderValue, + }; + + const res = await fetch(signedRequest.url, { + method: "POST", + headers, + body: signedRequest.body, + }); + + if (!res.ok) { + const errorText = await res.text(); + throw new TurnkeyNetworkError( + `Stamped request failed`, + res.status, + TurnkeyErrorCodes.WALLET_LOGIN_AUTH_ERROR, + errorText, + ); + } + + const sessionResponse = await res.json(); + const sessionToken = + sessionResponse.activity.result.stampLoginResult?.session; + if (!sessionToken) { + throw new TurnkeyError( + "Session token not found in the response", + TurnkeyErrorCodes.BAD_RESPONSE, + ); + } + + await this.storeSession({ + sessionToken: sessionToken, + sessionKey, + }); + + return sessionToken; + }, + { + errorCode: TurnkeyErrorCodes.WALLET_LOGIN_OR_SIGNUP_ERROR, + errorMessage: "Failed to log in or sign up with wallet", + catchFn: async () => { + if (generatedKeyPair) { + try { + await this.apiKeyStamper?.deleteKeyPair(generatedKeyPair); + } catch (cleanupError) { + throw new TurnkeyError( + `Failed to clean up generated key pair`, + TurnkeyErrorCodes.KEY_PAIR_CLEANUP_ERROR, + cleanupError, + ); + } + } + }, + }, + ); + }; + + /** + * Initializes the OTP process by sending an OTP code to the provided contact. + * + * - This function initiates the OTP flow by sending a one-time password (OTP) code to the user's contact information (email address or phone number) via the auth proxy. + * - Supports both email and SMS OTP types. + * - Returns an OTP ID that is required for subsequent OTP verification. + * + * @param params.otpType - type of OTP to initialize (OtpType.Email or OtpType.Sms). + * @param params.contact - contact information for the user (e.g., email address or phone number). + * @returns A promise that resolves to the OTP ID required for verification. + * @throws {TurnkeyError} If there is an error during the OTP initialization process or if the maximum number of OTPs has been reached. + */ + initOtp = async (params: { + otpType: OtpType; + contact: string; + }): Promise => { + return withTurnkeyErrorHandling( + async () => { + const initOtpRes = await this.httpClient.proxyInitOtp(params); + + if (!initOtpRes || !initOtpRes.otpId) { + throw new TurnkeyError( + "Failed to initialize OTP: otpId is missing", + TurnkeyErrorCodes.INIT_OTP_ERROR, + ); + } + + return initOtpRes.otpId; + }, + { + errorMessage: "Failed to initialize OTP", + errorCode: TurnkeyErrorCodes.INIT_OTP_ERROR, + customMessageByMessages: { + "Max number of OTPs have been initiated": { + message: + "Maximum number of OTPs has been reached for this contact.", + code: TurnkeyErrorCodes.MAX_OTP_INITIATED_ERROR, + }, + }, + }, + ); + }; + + /** + * Verifies the OTP code sent to the user. + * + * - This function verifies the OTP code entered by the user against the OTP sent to their contact information (email or phone) using the auth proxy. + * - If verification is successful, it returns the sub-organization ID associated with the contact (if it exists) and a verification token. + * - The verification token can be used for subsequent login or sign-up flows. + * - Handles both email and SMS OTP types. + * + * @param params.otpId - ID of the OTP to verify (returned from `initOtp`). + * @param params.otpCode - OTP code entered by the user. + * @param params.contact - contact information for the user (e.g., email address or phone number). + * @param params.otpType - type of OTP being verified (OtpType.Email or OtpType.Sms). + * @returns A promise that resolves to an object containing: + * - subOrganizationId: sub-organization ID if the contact is already associated with a sub-organization, or an empty string if not. + * - verificationToken: verification token to be used for login or sign-up. + * @throws {TurnkeyError} If there is an error during the OTP verification process, such as an invalid code or network failure. + */ + verifyOtp = async (params: { + otpId: string; + otpCode: string; + contact: string; + otpType: OtpType; + }): Promise<{ subOrganizationId: string; verificationToken: string }> => { + const { otpId, otpCode, contact, otpType } = params; + + return withTurnkeyErrorHandling( + async () => { + const verifyOtpRes = await this.httpClient.proxyVerifyOtp({ + otpId: otpId, + otpCode: otpCode, + }); + + if (!verifyOtpRes) { + throw new TurnkeyError( + `OTP verification failed`, + TurnkeyErrorCodes.INTERNAL_ERROR, + ); + } + const accountRes = await this.httpClient.proxyGetAccount({ + filterType: OtpTypeToFilterTypeMap[otpType], + filterValue: contact, + }); + + if (!accountRes) { + throw new TurnkeyError( + `Account fetch failed`, + TurnkeyErrorCodes.ACCOUNT_FETCH_ERROR, + ); + } + + const subOrganizationId = accountRes.organizationId; + return { + subOrganizationId: subOrganizationId, + verificationToken: verifyOtpRes.verificationToken, + }; + }, + { + errorMessage: "Failed to verify OTP", + errorCode: TurnkeyErrorCodes.VERIFY_OTP_ERROR, + customMessageByMessages: { + "Invalid OTP code": { + message: "The provided OTP code is invalid.", + code: TurnkeyErrorCodes.INVALID_OTP_CODE, + }, + }, + }, + ); + }; + + /** + * Logs in a user using an OTP verification token. + * + * - This function logs in a user using the verification token received after OTP verification (from email or SMS). + * - If a public key is not provided, a new API key pair will be generated for authentication. + * - Optionally invalidates any existing sessions for the user if `invalidateExisting` is set to true. + * - Stores the resulting session token under the specified session key, or the default session key if not provided. + * - Handles cleanup of unused key pairs if login fails. + * + * @param params.verificationToken - verification token received after OTP verification. + * @param params.publicKey - public key to use for authentication. If not provided, a new key pair will be generated. + * @param params.invalidateExisting - flag to invalidate existing session for the user. + * @param params.sessionKey - session key to use for session creation (defaults to the default session key). + * @returns A promise that resolves to a signed JWT session token. + * @throws {TurnkeyError} If there is an error during the OTP login process or if key pair cleanup fails. + */ + loginWithOtp = async (params: { + verificationToken: string; + publicKey?: string; + invalidateExisting?: boolean; + sessionKey?: string; + }): Promise => { + const { + verificationToken, + invalidateExisting = false, + publicKey = await this.apiKeyStamper?.createKeyPair(), + sessionKey = SessionKey.DefaultSessionkey, + } = params; + + return withTurnkeyErrorHandling( + async () => { + const res = await this.httpClient.proxyOtpLogin({ + verificationToken, + publicKey: publicKey!, + invalidateExisting, + }); + + if (!res) { + throw new TurnkeyError( + `Auth proxy OTP login failed`, + TurnkeyErrorCodes.OTP_LOGIN_ERROR, + ); + } + + const loginRes = await res; + if (!loginRes.session) { + throw new TurnkeyError( + "No session returned from OTP login", + TurnkeyErrorCodes.OTP_LOGIN_ERROR, + ); + } + + await this.storeSession({ + sessionToken: loginRes.session, + sessionKey, + }); + + return loginRes.session; + }, + { + errorMessage: "Failed to log in with OTP", + errorCode: TurnkeyErrorCodes.OTP_LOGIN_ERROR, + catchFn: async () => { + // Clean up the generated key pair if it wasn't successfully used + if (publicKey) { + try { + await this.apiKeyStamper?.deleteKeyPair(publicKey); + } catch (cleanupError) { + throw new TurnkeyError( + `Failed to clean up generated key pair`, + TurnkeyErrorCodes.KEY_PAIR_CLEANUP_ERROR, + cleanupError, + ); + } + } + }, + }, + ); + }; + + /** + * Signs up a user using an OTP verification token. + * + * - This function signs up a user using the verification token received after OTP verification (from email or SMS). + * - Creates a new sub-organization for the user with the provided parameters and associates the contact (email or phone) with the sub-organization. + * - Automatically generates a new API key pair for authentication and session management. + * - Stores the resulting session token under the specified session key, or the default session key if not provided. + * - Handles both email and SMS OTP types, and supports additional sub-organization creation parameters. + * + * @param params.verificationToken - verification token received after OTP verification. + * @param params.contact - contact information for the user (e.g., email address or phone number). + * @param params.otpType - type of OTP being used (OtpType.Email or OtpType.Sms). + * @param params.createSubOrgParams - parameters for creating a sub-organization (e.g., authenticators, user metadata). + * @param params.invalidateExisting - flag to invalidate existing session for the user. + * @param params.sessionKey - session key to use for session creation (defaults to the default session key). + * @returns A promise that resolves to a signed JWT session token for the new sub-organization. + * @throws {TurnkeyError} If there is an error during the OTP sign-up process or session storage. + */ + signUpWithOtp = async (params: { + verificationToken: string; + contact: string; + otpType: OtpType; + createSubOrgParams?: CreateSubOrgParams; + invalidateExisting?: boolean; + sessionKey?: string; + }): Promise => { + const { + verificationToken, + contact, + otpType, + createSubOrgParams, + invalidateExisting, + sessionKey, + } = params; + + const signUpBody = buildSignUpBody({ + createSubOrgParams: { + ...createSubOrgParams, + ...(otpType === OtpType.Email + ? { userEmail: contact } + : { userPhoneNumber: contact }), + verificationToken, + }, + }); + + return withTurnkeyErrorHandling( + async () => { + const generatedKeyPair = await this.apiKeyStamper?.createKeyPair(); + const res = await this.httpClient.proxySignup(signUpBody); + + if (!res) { + throw new TurnkeyError( + `Auth proxy OTP sign up failed`, + TurnkeyErrorCodes.OTP_SIGNUP_ERROR, + ); + } + + return await this.loginWithOtp({ + verificationToken, + publicKey: generatedKeyPair!, + ...(invalidateExisting && { invalidateExisting }), + ...(sessionKey && { sessionKey }), + }); + }, + { + errorCode: TurnkeyErrorCodes.OTP_SIGNUP_ERROR, + errorMessage: "Failed to sign up with OTP", + }, + ); + }; + + /** + * Completes the OTP authentication flow by verifying the OTP code and then either signing up or logging in the user. + * + * - This function first verifies the OTP code for the provided contact and OTP type. + * - If the contact is not associated with an existing sub-organization, it will automatically create a new sub-organization and complete the sign-up flow. + * - If the contact is already associated with a sub-organization, it will complete the login flow. + * - Supports passing a custom public key for authentication, invalidating existing session, specifying a session key, and providing additional sub-organization creation parameters. + * - Handles both email and SMS OTP types. + * + * @param params.otpId - ID of the OTP to complete (returned from `initOtp`). + * @param params.otpCode - OTP code entered by the user. + * @param params.contact - contact information for the user (e.g., email address or phone number). + * @param params.otpType - type of OTP being completed (OtpType.Email or OtpType.Sms). + * @param params.publicKey - public key to use for authentication. If not provided, a new key pair may be generated. + * @param params.invalidateExisting - flag to invalidate existing sessions for the user. + * @param params.sessionKey - session key to use for session creation (defaults to the default session key). + * @param params.createSubOrgParams - parameters for sub-organization creation (e.g., authenticators, user metadata). + * @returns A promise that resolves to a signed JWT session token for the user. + * @throws {TurnkeyError} If there is an error during OTP verification, sign-up, or login. + */ + completeOtp = async (params: { + otpId: string; + otpCode: string; + contact: string; + otpType: OtpType; + publicKey?: string; + invalidateExisting?: boolean; + sessionKey?: string; + createSubOrgParams?: CreateSubOrgParams; + }): Promise => { + const { + otpId, + otpCode, + contact, + otpType, + publicKey, + invalidateExisting = false, + sessionKey, + createSubOrgParams, + } = params; + + return withTurnkeyErrorHandling( + async () => { + const { subOrganizationId, verificationToken } = await this.verifyOtp({ + otpId: otpId, + otpCode: otpCode, + contact: contact, + otpType: otpType, + }); + + if (!verificationToken) { + throw new TurnkeyError( + "No verification token returned from OTP verification", + TurnkeyErrorCodes.VERIFY_OTP_ERROR, + ); + } + + if (!subOrganizationId) { + return await this.signUpWithOtp({ + verificationToken, + contact: contact, + otpType: otpType, + ...(createSubOrgParams && { + createSubOrgParams, + }), + ...(invalidateExisting && { invalidateExisting }), + ...(sessionKey && { sessionKey }), + }); + } else { + return await this.loginWithOtp({ + verificationToken, + ...(publicKey && { publicKey }), + ...(invalidateExisting && { invalidateExisting }), + ...(sessionKey && { sessionKey }), + }); + } + }, + { + errorMessage: "Failed to complete OTP process", + errorCode: TurnkeyErrorCodes.OTP_COMPLETION_ERROR, + }, + ); + }; + + /** + * Completes the OAuth authentication flow by either signing up or logging in the user, depending on whether a sub-organization already exists for the provided OIDC token. + * + * - This function first checks if there is an existing sub-organization associated with the OIDC token. + * - If a sub-organization exists, it proceeds with the OAuth login flow. + * - If no sub-organization exists, it creates a new sub-organization and completes the sign-up flow. + * - Optionally accepts a custom OAuth provider name, session key, and additional sub-organization creation parameters. + * - Handles session storage and management, and supports invalidating existing sessions if specified. + * + * @param params.oidcToken - OIDC token received after successful authentication with the OAuth provider. + * @param params.publicKey - public key to use for authentication. Must be generated prior to calling this function. + * @param params.providerName - name of the OAuth provider (defaults to a generated name with a timestamp). + * @param params.sessionKey - session key to use for session creation (defaults to the default session key). + * @param params.invalidateExisting - flag to invalidate existing sessions for the user. + * @param params.createSubOrgParams - parameters for sub-organization creation (e.g., authenticators, user metadata). + * @returns A promise that resolves to a signed JWT session token for the user. + * @throws {TurnkeyError} If there is an error during the OAuth completion process, such as account lookup, sign-up, or login. + */ + completeOauth = async (params: { + oidcToken: string; + publicKey: string; + providerName?: string; + sessionKey?: string; + invalidateExisting?: boolean; + createSubOrgParams?: CreateSubOrgParams; + }): Promise => { + const { + oidcToken, + publicKey, + createSubOrgParams, + providerName = "OpenID Connect Provider" + Date.now(), + sessionKey = SessionKey.DefaultSessionkey, + invalidateExisting = false, + } = params; + + return withTurnkeyErrorHandling( + async () => { + const accountRes = await this.httpClient.proxyGetAccount({ + filterType: "OIDC_TOKEN", + filterValue: oidcToken, + }); + + if (!accountRes) { + throw new TurnkeyError( + `Account fetch failed`, + TurnkeyErrorCodes.ACCOUNT_FETCH_ERROR, + ); + } + const subOrganizationId = accountRes.organizationId; + + if (subOrganizationId) { + return this.loginWithOauth({ + oidcToken, + publicKey, + invalidateExisting, + sessionKey, + }); + } else { + return this.signUpWithOauth({ + oidcToken, + publicKey, + providerName, + ...(createSubOrgParams && { + createSubOrgParams, + }), + }); + } + }, + { + errorMessage: "Failed to complete OAuth process", + errorCode: TurnkeyErrorCodes.OAUTH_LOGIN_ERROR, + }, + ); + }; + + /** + * Logs in a user using OAuth authentication. + * + * - This function logs in a user using the provided OIDC token and public key. + * - Optionally invalidates any existing sessions for the user if `invalidateExisting` is set to true. + * - Stores the resulting session token under the specified session key, or the default session key if not provided. + * - Handles cleanup of unused key pairs if login fails. + * + * @param params.oidcToken - OIDC token received after successful authentication with the OAuth provider. + * @param params.publicKey - public key to use for authentication. Must be generated prior to calling this function. + * @param params.invalidateExisting - flag to invalidate existing sessions for the user. + * @param params.sessionKey - session key to use for session creation (defaults to the default session key). + * @returns A promise that resolves to a signed JWT session token. + * @throws {TurnkeyError} If there is an error during the OAuth login process or if key pair cleanup fails. + */ + loginWithOauth = async (params: { + oidcToken: string; + publicKey: string; + invalidateExisting?: boolean; + sessionKey?: string; + }): Promise => { + const { + oidcToken, + invalidateExisting = false, + publicKey, + sessionKey = SessionKey.DefaultSessionkey, + } = params; + + return withTurnkeyErrorHandling( + async () => { + if (!publicKey) { + throw new TurnkeyError( + "Public key must be provided to log in with OAuth. Please create a key pair first.", + TurnkeyErrorCodes.MISSING_PARAMS, + ); + } + + const loginRes = await this.httpClient.proxyOAuthLogin({ + oidcToken, + publicKey, + invalidateExisting, + }); + + if (!loginRes) { + throw new TurnkeyError( + `Auth proxy OAuth login failed`, + TurnkeyErrorCodes.OAUTH_LOGIN_ERROR, + ); + } + + if (!loginRes.session) { + throw new TurnkeyError( + "No session returned from oauth login", + TurnkeyErrorCodes.OAUTH_LOGIN_ERROR, + ); + } + + await this.storeSession({ + sessionToken: loginRes.session, + sessionKey, + }); + + return loginRes.session; + }, + { + errorMessage: "Failed to complete OAuth login", + errorCode: TurnkeyErrorCodes.OAUTH_LOGIN_ERROR, + customMessageByMessages: { + "OAUTH disallowed": { + message: + "OAuth is disabled on the dashboard for this organization.", + code: TurnkeyErrorCodes.AUTH_METHOD_NOT_ENABLED, + }, + }, + catchFn: async () => { + // Clean up the generated key pair if it wasn't successfully used + if (publicKey) { + try { + await this.apiKeyStamper?.deleteKeyPair(publicKey); + } catch (cleanupError) { + throw new TurnkeyError( + `Failed to clean up generated key pair`, + TurnkeyErrorCodes.KEY_PAIR_CLEANUP_ERROR, + cleanupError, + ); + } + } + }, + }, + ); + }; + + /** + * Signs up a user using OAuth authentication. + * + * - This function creates a new sub-organization for the user using the provided OIDC token, public key, and provider name. + * - Handles the full OAuth sign-up flow, including sub-organization creation and session management. + * - Optionally accepts additional sub-organization creation parameters and a custom session key. + * - After successful sign-up, automatically logs in the user and returns a signed JWT session token. + * + * @param params.oidcToken - OIDC token received after successful authentication with the OAuth provider. + * @param params.publicKey - public key to associate with the new sub-organization. + * @param params.providerName - name of the OAuth provider (e.g., "Google", "Apple"). + * @param params.createSubOrgParams - parameters for sub-organization creation (e.g., authenticators, user metadata). + * @param params.sessionKey - session key to use for session creation (defaults to the default session key). + * @returns A promise that resolves to a signed JWT session token for the new sub-organization. + * @throws {TurnkeyError} If there is an error during the OAuth sign-up or login process. + */ + signUpWithOauth = async (params: { + oidcToken: string; + publicKey: string; + providerName: string; + createSubOrgParams?: CreateSubOrgParams; + sessionKey?: string; + }): Promise => { + const { oidcToken, publicKey, providerName, createSubOrgParams } = params; + + return withTurnkeyErrorHandling( + async () => { + const signUpBody = buildSignUpBody({ + createSubOrgParams: { + ...createSubOrgParams, + oauthProviders: [ + { + providerName, + oidcToken, + }, + ], + }, + }); + + const res = await this.httpClient.proxySignup(signUpBody); + + if (!res) { + throw new TurnkeyError( + `Auth proxy OAuth signup failed`, + TurnkeyErrorCodes.OAUTH_SIGNUP_ERROR, + ); + } + + return await this.loginWithOauth({ + oidcToken, + publicKey: publicKey!, + }); + }, + { + errorMessage: "Failed to sign up with OAuth", + errorCode: TurnkeyErrorCodes.OAUTH_SIGNUP_ERROR, + }, + ); + }; + + /** + * Fetches all wallets for the current user, including both embedded and connected wallets. + * + * - Retrieves all wallets associated with the organizationId from the current active session. + * - For each embedded wallet, automatically fetches and attaches all associated wallet accounts. + * - For connected wallets (e.g., browser extensions or external providers), groups providers by wallet name and attaches all connected accounts. + * - Returns both embedded and connected wallets in a single array, each with their respective accounts populated. + * - Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + * + * @param params.stampWith - parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + * @returns A promise that resolves to an array of `Wallet` objects. + * @throws {TurnkeyError} If no active session is found or if there is an error fetching wallets. + */ + fetchWallets = async (params?: { + stampWith?: StamperType | undefined; + }): Promise => { + const { stampWith } = params || {}; + const session = await this.storageManager.getActiveSession(); + + if (!session) { + throw new TurnkeyError( + "No active session found. Please log in first.", + TurnkeyErrorCodes.NO_SESSION_FOUND, + ); + } + + return withTurnkeyErrorHandling( + async () => { + const res = await this.httpClient.getWallets( + { organizationId: session.organizationId }, + stampWith, + ); + + if (!res || !res.wallets) { + throw new TurnkeyError( + "No wallets found in the response", + TurnkeyErrorCodes.BAD_RESPONSE, + ); + } + + const embedded: EmbeddedWallet[] = await Promise.all( + res.wallets.map(async (wallet) => { + const embeddedWallet: Wallet = { + ...wallet, + source: WalletSource.Embedded, + accounts: [], + }; + + const accounts = await this.fetchWalletAccounts({ + wallet: embeddedWallet, + ...(stampWith !== undefined && { stampWith }), + }); + + embeddedWallet.accounts = accounts; + return embeddedWallet; + }), + ); + + // if wallet connecting is disabled we return only embedded wallets + if (!this.walletManager?.connector) return embedded; + + const providers = await this.getWalletProviders(); + + const groupedProviders = new Map(); + for (const provider of providers) { + const walletId = + provider.info?.name?.toLowerCase().replace(/\s+/g, "-") || + "unknown"; + const group = groupedProviders.get(walletId) || []; + group.push(provider); + groupedProviders.set(walletId, group); + } + + const connected: ConnectedWallet[] = ( + await Promise.all( + Array.from(groupedProviders.entries()).map( + async ([walletId, grouped]) => { + const timestamp = toExternalTimestamp(); + + const wallet: Wallet = { + source: WalletSource.Connected, + walletId, + walletName: grouped[0]?.info?.name ?? "Unknown", + createdAt: timestamp, + updatedAt: timestamp, + exported: false, + imported: false, + accounts: [], + }; + + const accounts = await this.fetchWalletAccounts({ + wallet, + walletProviders: grouped, + ...(stampWith !== undefined && { stampWith }), + }); + + wallet.accounts = accounts; + return wallet; + }, + ), + ) + ).filter((wallet) => wallet.accounts.length > 0); + + return [...embedded, ...connected]; + }, + { + errorMessage: "Failed to fetch wallets", + errorCode: TurnkeyErrorCodes.FETCH_WALLETS_ERROR, + }, + ); + }; + + /** + * Fetches all accounts for a specific wallet, including both embedded and connected wallet accounts. + * + * - For embedded wallets, retrieves accounts from the Turnkey API, supporting pagination (defaults to the first page with a limit of 100 accounts). + * - For connected wallets (e.g., browser extensions or external providers), constructs account objects for each connected address from the provided or discovered wallet providers. + * - Automatically determines the account type and populates relevant fields such as address, curve, and signing capability. + * - Optionally allows filtering by a specific set of wallet providers and supports custom pagination options. + * - Supports stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + * + * @param params.wallet - wallet for which to fetch accounts. + * @param params.walletProviders - list of wallet providers to filter by (used for connected wallets). + * @param params.paginationOptions - pagination options for embedded wallets. + * @param params.stampWith - parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + * @returns A promise that resolves to an array of `v1WalletAccount` objects. + * @throws {TurnkeyError} If no active session is found or if there is an error fetching wallet accounts. + */ + fetchWalletAccounts = async (params: { + wallet: Wallet; + walletProviders?: WalletProvider[]; + paginationOptions?: v1Pagination; + stampWith?: StamperType | undefined; + }): Promise => { + const { wallet, stampWith, walletProviders, paginationOptions } = params; + const session = await this.storageManager.getActiveSession(); + + if (!session) { + throw new TurnkeyError( + "No active session found. Please log in first.", + TurnkeyErrorCodes.NO_SESSION_FOUND, + ); + } + + return withTurnkeyErrorHandling( + async () => { + // this is an embedded wallet so we fetch accounts from Turnkey + if (wallet.source === WalletSource.Embedded) { + const embedded: EmbeddedWalletAccount[] = []; + + const res = await this.httpClient.getWalletAccounts( + { + walletId: wallet.walletId, + organizationId: session.organizationId, + paginationOptions: paginationOptions || { limit: "100" }, + }, + stampWith, + ); + + if (!res || !res.accounts) { + throw new TurnkeyError( + "No wallet accounts found in the response", + TurnkeyErrorCodes.BAD_RESPONSE, + ); + } + + for (const account of res.accounts) { + embedded.push({ + ...account, + source: WalletSource.Embedded, + }); + } + + return embedded; + } + + // this is an external wallet so we fetch accounts from the connected wallet provider + + // if wallet connecting is disabled we return only embedded wallets + // we should never reach this point if wallet connecting is disabled + if (!this.walletManager?.connector) return []; + + const connected: ConnectedWalletAccount[] = []; + + const providers = walletProviders ?? (await this.getWalletProviders()); + const matching = providers.filter( + (p) => + p.info?.name?.toLowerCase().replace(/\s+/g, "-") === + wallet.walletId && p.connectedAddresses.length > 0, + ); + + for (const provider of matching) { + const timestamp = toExternalTimestamp(); + + for (const address of provider.connectedAddresses) { + const account: ConnectedWalletAccount = { + walletAccountId: `${wallet.walletId}-${provider.interfaceType}-${address}`, + organizationId: session.organizationId, + walletId: wallet.walletId, + curve: isEthereumWallet(provider) + ? Curve.SECP256K1 + : Curve.ED25519, + pathFormat: "PATH_FORMAT_BIP32", + path: WalletSource.Connected, + source: WalletSource.Connected, + addressFormat: isEthereumWallet(provider) + ? "ADDRESS_FORMAT_ETHEREUM" + : "ADDRESS_FORMAT_SOLANA", + address, + createdAt: timestamp, + updatedAt: timestamp, + ...getWalletAccountMethods( + this.walletManager!.connector!.sign.bind( + this.walletManager!.connector, + ), + provider, + ), + ...(isSolanaWallet(provider) && { publicKey: address }), + }; + + connected.push(account); + } + } + + return connected; + }, + { + errorMessage: "Failed to fetch wallet accounts", + errorCode: TurnkeyErrorCodes.FETCH_WALLET_ACCOUNTS_ERROR, + }, + ); + }; + + /** + * Signs a message using the specified wallet account. + * + * - Supports both embedded and connected wallets. + * - For **connected wallets**: + * - Delegates signing to the wallet provider’s native signing method. + * - **Important:** For Ethereum wallets (e.g., MetaMask), signatures follow [EIP-191](https://eips.ethereum.org/EIPS/eip-191). + * The message is automatically prefixed with `"\x19Ethereum Signed Message:\n" + message length` + * before signing. As a result, this signature **cannot be used as a raw transaction signature** + * or broadcast on-chain. + * - For **embedded wallets**, uses the Turnkey API to sign the message directly. + * - Automatically handles message encoding and hashing based on the wallet account’s address format, + * unless explicitly overridden. + * + * @param params.message - message to sign. + * @param params.walletAccount - wallet account to use for signing. + * @param params.encoding - override for the payload encoding (defaults to the encoding appropriate for the address type). + * @param params.hashFunction - override for the hash function (defaults to the hash function appropriate for the address type). + * @param params.stampWith - stamper to tag the signing request (e.g., Passkey, ApiKey, or Wallet). + * @param params.addEthereumPrefix - whether to prefix the message with Ethereum's `"\x19Ethereum Signed Message:\n"` string. + * - If `true` (default for Ethereum), the message is prefixed before signing. + * - If `false`: + * - Connected wallets will throw an error because they always prefix automatically. + * - Embedded wallets will sign the raw message without any prefix. + * + * @returns A promise resolving to a `v1SignRawPayloadResult` containing the signature and metadata. + * @throws {TurnkeyError} If signing fails, if the wallet account does not support signing, or if the response is invalid. + */ + signMessage = async (params: { + message: string; + walletAccount: WalletAccount; + encoding?: v1PayloadEncoding; + hashFunction?: v1HashFunction; + stampWith?: StamperType | undefined; + addEthereumPrefix?: boolean; + }): Promise => { + const { message, walletAccount, stampWith, addEthereumPrefix } = params; + + const hashFunction = + params.hashFunction || getHashFunction(walletAccount.addressFormat); + const payloadEncoding = + params.encoding || getEncodingType(walletAccount.addressFormat); + + return withTurnkeyErrorHandling( + async () => { + const isEthereum = + walletAccount.addressFormat === "ADDRESS_FORMAT_ETHEREUM"; + + if (walletAccount.source === WalletSource.Connected) { + // this is a connected wallet + + if (!addEthereumPrefix && isEthereum) { + throw new TurnkeyError( + "Connected Ethereum wallets automatically prefix messages. Use `addEthereumPrefix: true`.", + TurnkeyErrorCodes.SIGN_MESSAGE_ERROR, + ); + } + + let encodedMessage = message; + if (isEthereum) { + encodedMessage = getEncodedMessage( + walletAccount.addressFormat, + message, + ); + } + + const sigHex = await walletAccount.signMessage(encodedMessage); + return splitSignature(sigHex, walletAccount.addressFormat); + } + + // this is an embedded wallet + let messageToEncode = message; + + if (addEthereumPrefix && isEthereum) { + const prefix = `\x19Ethereum Signed Message:\n${toUtf8Bytes(message).length}`; + messageToEncode = prefix + message; + } + + const encodedMessage = getEncodedMessage( + walletAccount.addressFormat, + messageToEncode, + ); + + const response = await this.httpClient.signRawPayload( + { + signWith: walletAccount.address, + payload: encodedMessage, + encoding: payloadEncoding, + hashFunction, + }, + stampWith, + ); + + if (response.activity.failure) { + throw new TurnkeyError( + "Failed to sign message, no signed payload returned", + TurnkeyErrorCodes.SIGN_MESSAGE_ERROR, + ); + } + + return response.activity.result + .signRawPayloadResult as v1SignRawPayloadResult; + }, + { + errorMessage: "Failed to sign message", + errorCode: TurnkeyErrorCodes.SIGN_MESSAGE_ERROR, + }, + ); + }; + + /** + * Signs a transaction using the specified wallet account. + * + * - This function signs a blockchain transaction using the provided wallet address and transaction data. + * - Supports all Turnkey-supported blockchain networks (e.g., Ethereum, Solana, Tron). + * - Automatically determines the appropriate signing method based on the transaction type. + * - Delegates signing to the Turnkey API, which returns the signed transaction and related metadata. + * - Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + * + * @param params.walletAccount - wallet account to use for signing the transaction. + * @param params.unsignedTransaction - unsigned transaction data (serialized as a string) to be signed. + * @param params.transactionType - type of transaction (e.g., "TRANSACTION_TYPE_ETHEREUM", "TRANSACTION_TYPE_SOLANA", "TRANSACTION_TYPE_TRON"). + * @param params.stampWith - parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + * @returns A promise that resolves to a `TSignTransactionResponse` object containing the signed transaction and any additional signing metadata. + * @throws {TurnkeyError} If there is an error signing the transaction or if the response is invalid. + */ + signTransaction = async (params: { + unsignedTransaction: string; + transactionType: v1TransactionType; + walletAccount: WalletAccount; + stampWith?: StamperType | undefined; + }): Promise => { + const { walletAccount, unsignedTransaction, transactionType, stampWith } = + params; + + return withTurnkeyErrorHandling( + async () => { + if (walletAccount.source === WalletSource.Connected) { + // this is a connected wallet account + + if (!walletAccount.signTransaction) { + const isEthereum = + walletAccount.addressFormat === "ADDRESS_FORMAT_ETHEREUM"; + + const reason = isEthereum + ? "Ethereum connected wallets do not support raw transaction signing due to EIP-1193 limitations." + : "This connected wallet does not support raw transaction signing."; + + throw new TurnkeyError( + `Failed to sign transaction: ${reason} ${ + isEthereum ? "Use signAndSendTransaction instead." : "" + }`, + TurnkeyErrorCodes.SIGN_TRANSACTION_ERROR, + ); + } + + return await walletAccount?.signTransaction(unsignedTransaction); + } + + // this is an embedded wallet account + const signTransaction = await this.httpClient.signTransaction( + { + signWith: walletAccount.address, + unsignedTransaction, + type: transactionType, + }, + stampWith, + ); + + return signTransaction.signedTransaction; + }, + { + errorMessage: "Failed to sign transaction", + errorCode: TurnkeyErrorCodes.SIGN_TRANSACTION_ERROR, + }, + ); + }; + + /** + * Signs and broadcasts a transaction using the specified wallet account. + * + * - For **connected wallets**: + * - Calls the wallet’s native `signAndSendTransaction` method. + * - Does **not** require an `rpcUrl`. + * + * - For **embedded wallets**: + * - Signs the transaction using the Turnkey API. + * - Requires an `rpcUrl` to broadcast the transaction. + * - Broadcasts the transaction using a JSON-RPC client. + * + * @param params.walletAccount - wallet account to use for signing and sending. + * @param params.unsignedTransaction - unsigned transaction (serialized string). + * @param params.transactionType - transaction type (e.g., "TRANSACTION_TYPE_SOLANA"). + * @param params.rpcUrl - required for embedded wallets to broadcast the signed transaction. + * @param params.stampWith - optional stamper to tag the signing request. + * @returns A promise that resolves to a transaction signature or hash. + * @throws {TurnkeyError} If signing or broadcasting fails. + */ + signAndSendTransaction = async (params: { + unsignedTransaction: string; + transactionType: v1TransactionType; + walletAccount: WalletAccount; + rpcUrl?: string; + stampWith?: StamperType | undefined; + }): Promise => { + const { + walletAccount, + unsignedTransaction, + transactionType, + rpcUrl, + stampWith, + } = params; + + return withTurnkeyErrorHandling( + async () => { + if (walletAccount.source === WalletSource.Connected) { + // this is a connected wallet account + switch (transactionType) { + case "TRANSACTION_TYPE_ETHEREUM": + if (!walletAccount.signAndSendTransaction) { + throw new TurnkeyError( + "This connected wallet does not support signAndSendTransaction.", + TurnkeyErrorCodes.SIGN_AND_SEND_TRANSACTION_ERROR, + ); + } + return await walletAccount.signAndSendTransaction( + unsignedTransaction, + ); + + case "TRANSACTION_TYPE_SOLANA": + if (!rpcUrl) { + throw new TurnkeyError( + "Missing rpcUrl: connected Solana wallets require an RPC URL to broadcast transactions.", + TurnkeyErrorCodes.SIGN_AND_SEND_TRANSACTION_ERROR, + ); + } + if (!walletAccount.signTransaction) { + throw new TurnkeyError( + "This connected wallet does not support signAndSendTransaction.", + TurnkeyErrorCodes.SIGN_AND_SEND_TRANSACTION_ERROR, + ); + } + const signature = + await walletAccount.signTransaction(unsignedTransaction); + return await broadcastTransaction({ + signedTransaction: signature, + rpcUrl, + transactionType, + }); + + default: + throw new TurnkeyError( + "Connected wallets do not support signAndSendTransaction for this transaction type.", + TurnkeyErrorCodes.SIGN_AND_SEND_TRANSACTION_ERROR, + ); + } + } + + // this is an embedded wallet account + + // embedded wallet requires an RPC URL to broadcast + // since Turnkey does not broadcast transactions directly + if (!rpcUrl) { + throw new TurnkeyError( + "Missing rpcUrl: embedded wallets require an RPC URL to broadcast transactions.", + TurnkeyErrorCodes.SIGN_AND_SEND_TRANSACTION_ERROR, + ); + } + + const signTransactionResponse = await this.httpClient.signTransaction( + { + signWith: walletAccount.address, + unsignedTransaction, + type: transactionType, + }, + stampWith, + ); + + const signedTx = signTransactionResponse.signedTransaction; + + const txHash = await broadcastTransaction({ + signedTransaction: signedTx, + rpcUrl, + transactionType, + }); + + return txHash; + }, + { + errorMessage: "Failed to sign and send transaction", + errorCode: TurnkeyErrorCodes.SIGN_AND_SEND_TRANSACTION_ERROR, + }, + ); + }; + + /** + * Fetches the user details for the current session or a specified user. + * + * - Retrieves user details from the Turnkey API using the provided userId and organizationId, or defaults to those from the active session. + * - If no userId is provided, the userId from the current session is used. + * - If no organizationId is provided, the organizationId from the current session is used. + * - Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + * - Ensures that an active session exists before making the request. + * + * @param params.organizationId - organization ID to specify the sub-organization (defaults to the current session's organizationId). + * @param params.userId - user ID to fetch specific user details (defaults to the current session's userId). + * @param params.stampWith - parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + * @returns A promise that resolves to a `v1User` object containing the user details. + * @throws {TurnkeyError} If there is no active session, if there is no userId, or if there is an error fetching user details. + */ + fetchUser = async (params?: { + organizationId?: string; + userId?: string; + stampWith?: StamperType | undefined; + }): Promise => { + const { stampWith } = params || {}; + const session = await this.storageManager.getActiveSession(); + if (!session) { + throw new TurnkeyError( + "No active session found. Please log in first.", + TurnkeyErrorCodes.NO_SESSION_FOUND, + ); + } + + const userId = params?.userId || session.userId; + if (!userId) { + throw new TurnkeyError( + "User ID must be provided to fetch user", + TurnkeyErrorCodes.INVALID_REQUEST, + ); + } + + const organizationId = params?.organizationId || session.organizationId; + + return withTurnkeyErrorHandling( + async () => { + const userResponse = await this.httpClient.getUser( + { organizationId, userId }, + stampWith, + ); + + if (!userResponse || !userResponse.user) { + throw new TurnkeyError( + "No user found in the response", + TurnkeyErrorCodes.BAD_RESPONSE, + ); + } + + return userResponse.user as User; + }, + { + errorMessage: "Failed to fetch user", + errorCode: TurnkeyErrorCodes.FETCH_USER_ERROR, + }, + ); + }; + + /** + * Updates the user's email address. + * + * - This function updates the user's email address and, if provided, verifies it using a verification token (typically from an OTP flow). + * - If a userId is provided, it updates the email for that specific user; otherwise, it uses the current session's userId. + * - If a verificationToken is not provided, the email will be updated but will not be marked as verified. + * - Automatically ensures an active session exists before making the request. + * - Handles session management and error reporting for both update and verification flows. + * + * @param params.email - new email address to set for the user. + * @param params.verificationToken - verification token from OTP email verification (required if verifying the email). + * @param params.userId - user ID to update a specific user's email (defaults to the current session's userId). + * @param params.stampWith - parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + * @returns A promise that resolves to the userId of the updated user. + * @throws {TurnkeyError} If there is no active session, if the userId is missing, or if there is an error updating or verifying the user email. + */ + updateUserEmail = async (params: { + email: string; + verificationToken?: string; + userId?: string; + stampWith?: StamperType | undefined; + }): Promise => { + const { verificationToken, email, stampWith } = params; + const session = await this.storageManager.getActiveSession(); + if (!session) { + throw new TurnkeyError( + "No active session found. Please log in first.", + TurnkeyErrorCodes.NO_SESSION_FOUND, + ); + } + + const userId = params?.userId || session.userId; + + return withTurnkeyErrorHandling( + async () => { + const existingUser = await this.httpClient.proxyGetAccount({ + filterType: FilterType.Email, + filterValue: email, + }); + + if (existingUser.organizationId) { + throw new TurnkeyError( + `Email ${email} is already associated with another user.`, + TurnkeyErrorCodes.ACCOUNT_ALREADY_EXISTS, + ); + } + + const res = await this.httpClient.updateUserEmail( + { + userId: userId, + userEmail: email, + ...(verificationToken && { verificationToken }), + }, + stampWith, + ); + + if (!res || !res.userId) { + throw new TurnkeyError( + "No user ID found in the update user email response", + TurnkeyErrorCodes.BAD_RESPONSE, + ); + } + + return res.userId; + }, + { + errorMessage: "Failed to update user email", + errorCode: TurnkeyErrorCodes.UPDATE_USER_EMAIL_ERROR, + }, + ); + }; + + /** + * Removes the user's email address. + * + * - This function removes the user's email address by setting it to an empty string. + * - If a userId is provided, it removes the email for that specific user; otherwise, it uses the current session's userId. + * - Automatically ensures an active session exists before making the request. + * - Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + * + * @param params.userId - user ID to remove a specific user's email address (defaults to the current session's userId). + * @param params.stampWith - parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + * @returns A promise that resolves to the userId of the user whose email was removed. + * @throws {TurnkeyError} If there is no active session, if the userId is missing, or if there is an error removing the user email. + */ + removeUserEmail = async (params?: { + userId?: string; + stampWith?: StamperType | undefined; + }): Promise => { + const { stampWith } = params || {}; + const session = await this.storageManager.getActiveSession(); + if (!session) { + throw new TurnkeyError( + "No active session found. Please log in first.", + TurnkeyErrorCodes.NO_SESSION_FOUND, + ); + } + return withTurnkeyErrorHandling( + async () => { + const userId = params?.userId || session.userId; + const res = await this.httpClient.updateUserEmail( + { + userId: userId, + userEmail: "", + }, + stampWith, + ); + if (!res || !res.userId) { + throw new TurnkeyError( + "No user ID found in the remove user email response", + TurnkeyErrorCodes.BAD_RESPONSE, + ); + } + return res.userId; + }, + { + errorMessage: "Failed to remove user email", + errorCode: TurnkeyErrorCodes.UPDATE_USER_EMAIL_ERROR, + }, + ); + }; + + /** + * Updates the user's phone number. + * + * - This function updates the user's phone number and, if provided, verifies it using a verification token (from an OTP flow). + * - If a userId is provided, it updates the phone number for that specific user; otherwise, it uses the current session's userId. + * - If a verificationToken is not provided, the phone number will be updated but will not be marked as verified. + * - Automatically ensures an active session exists before making the request. + * - Handles session management and error reporting for both update and verification flows. + * + * @param params.phoneNumber - new phone number to set for the user. + * @param params.verificationToken - verification token from OTP phone verification (required if verifying the phone number). + * @param params.userId - user ID to update a specific user's phone number (defaults to the current session's userId). + * @param params.stampWith - parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + * @returns A promise that resolves to the userId of the updated user. + * @throws {TurnkeyError} If there is no active session, if the userId is missing, or if there is an error updating or verifying the user phone number. + */ + updateUserPhoneNumber = async (params: { + phoneNumber: string; + verificationToken?: string; + userId?: string; + stampWith?: StamperType | undefined; + }): Promise => { + const { verificationToken, phoneNumber, stampWith } = params; + const session = await this.storageManager.getActiveSession(); + if (!session) { + throw new TurnkeyError( + "No active session found. Please log in first.", + TurnkeyErrorCodes.NO_SESSION_FOUND, + ); + } + + const userId = params?.userId || session.userId; + return withTurnkeyErrorHandling( + async () => { + const res = await this.httpClient.updateUserPhoneNumber( + { + userId, + userPhoneNumber: phoneNumber, + ...(verificationToken && { verificationToken }), + }, + stampWith, + ); + + if (!res || !res.userId) { + throw new TurnkeyError( + "Failed to update user phone number", + TurnkeyErrorCodes.UPDATE_USER_PHONE_NUMBER_ERROR, + ); + } + + return res.userId; + }, + { + errorMessage: "Failed to update user phone number", + errorCode: TurnkeyErrorCodes.UPDATE_USER_PHONE_NUMBER_ERROR, + }, + ); + }; + + /** + * Removes the user's phone number. + * + * - This function removes the user's phone number by setting it to an empty string. + * - If a userId is provided, it removes the phone number for that specific user; otherwise, it uses the current session's userId. + * - Automatically ensures an active session exists before making the request. + * - Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + * + * @param params.userId - user ID to remove a specific user's phone number (defaults to the current session's userId). + * @param params.stampWith - parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + * @returns A promise that resolves to the userId of the user whose phone number was removed. + * @throws {TurnkeyError} If there is no active session, if the userId is missing, or if there is an error removing the user phone number. + */ + removeUserPhoneNumber = async (params?: { + userId?: string; + stampWith?: StamperType | undefined; + }): Promise => { + const { stampWith } = params || {}; + const session = await this.storageManager.getActiveSession(); + if (!session) { + throw new TurnkeyError( + "No active session found. Please log in first.", + TurnkeyErrorCodes.NO_SESSION_FOUND, + ); + } + const userId = params?.userId || session.userId; + + return withTurnkeyErrorHandling( + async () => { + const res = await this.httpClient.updateUserPhoneNumber( + { + userId, + userPhoneNumber: "", + }, + stampWith, + ); + if (!res || !res.userId) { + throw new TurnkeyError( + "Failed to remove user phone number", + TurnkeyErrorCodes.UPDATE_USER_PHONE_NUMBER_ERROR, + ); + } + return res.userId; + }, + { + errorMessage: "Failed to remove user phone number", + errorCode: TurnkeyErrorCodes.UPDATE_USER_PHONE_NUMBER_ERROR, + }, + ); + }; + + /** + * Updates the user's name. + * + * - This function updates the user's display name. + * - If a userId is provided, it updates the name for that specific user; otherwise, it uses the current session's userId. + * - Automatically ensures an active session exists before making the request. + * - Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + * - Handles session management and error reporting for the update flow. + * + * @param params.userName - new name to set for the user. + * @param params.userId - user ID to update a specific user's name (defaults to the current session's userId). + * @param params.stampWith - parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + * @returns A promise that resolves to the userId of the updated user. + * @throws {TurnkeyError} If there is no active session, if the userId is missing, or if there is an error updating the user name. + */ + updateUserName = async (params: { + userName: string; + userId?: string; + stampWith?: StamperType | undefined; + }): Promise => { + const { userName, stampWith } = params; + const session = await this.storageManager.getActiveSession(); + if (!session) { + throw new TurnkeyError( + "No active session found. Please log in first.", + TurnkeyErrorCodes.NO_SESSION_FOUND, + ); + } + const userId = params?.userId || session.userId; + + return withTurnkeyErrorHandling( + async () => { + const res = await this.httpClient.updateUserName( + { + userId, + userName, + }, + stampWith, + ); + + if (!res || !res.userId) { + throw new TurnkeyError( + "No user ID found in the update user name response", + TurnkeyErrorCodes.BAD_RESPONSE, + ); + } + + return res.userId; + }, + { + errorMessage: "Failed to update user name", + errorCode: TurnkeyErrorCodes.UPDATE_USER_NAME_ERROR, + }, + ); + }; + + /** + * Adds an OAuth provider to the user. + * + * - This function adds an OAuth provider (e.g., Google, Apple) to the user account. + * - If a userId is provided, it adds the provider for that specific user; otherwise, it uses the current session's userId. + * - Automatically checks if an account already exists for the provided OIDC token and prevents duplicate associations. + * - If the user's email is not set or not verified, attempts to update and verify the email using the email from the OIDC token. + * - Handles session management and error reporting for the add provider flow. + * - Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + * + * @param params.providerName - name of the OAuth provider to add (e.g., "Google", "Apple"). + * @param params.oidcToken - OIDC token for the OAuth provider. + * @param params.userId - user ID to add the provider for a specific user (defaults to current session's userId). + * @param params.stampWith - parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + * @returns A promise that resolves to an array of provider IDs associated with the user. + * @throws {TurnkeyError} If there is no active session, if the account already exists, or if there is an error adding the OAuth provider. + */ + addOauthProvider = async (params: { + providerName: string; + oidcToken: string; + userId?: string; + stampWith?: StamperType | undefined; + }): Promise => { + const { providerName, oidcToken, stampWith } = params; + const session = await this.storageManager.getActiveSession(); + if (!session) { + throw new TurnkeyError( + "No active session found. Please log in first.", + TurnkeyErrorCodes.NO_SESSION_FOUND, + ); + } + + return withTurnkeyErrorHandling( + async () => { + const accountRes = await this.httpClient.proxyGetAccount({ + filterType: "OIDC_TOKEN", + filterValue: oidcToken, + }); + + if (!accountRes) { + throw new TurnkeyError( + `Account fetch failed}`, + TurnkeyErrorCodes.ACCOUNT_FETCH_ERROR, + ); + } + + if (accountRes.organizationId) { + throw new TurnkeyError( + "Account already exists with this OIDC token", + TurnkeyErrorCodes.ACCOUNT_ALREADY_EXISTS, + ); + } + + const userId = params?.userId || session.userId; + const { email: oidcEmail, iss } = jwtDecode(oidcToken) || {}; // Parse the oidc token so we can get the email. Pass it in to updateUser then call createOauthProviders. This will be verified by Turnkey. + + if (iss === googleISS) { + const verifiedSuborg = await this.httpClient.proxyGetAccount({ + filterType: "EMAIL", + filterValue: oidcEmail, + }); + const isVerified = + verifiedSuborg.organizationId === session.organizationId; + + const user = await this.fetchUser({ + userId, + stampWith, + }); + + if (!user?.userEmail && !isVerified) { + await this.updateUserEmail({ + email: oidcEmail, + userId, + stampWith, + }); + } + } + + const createProviderRes = await this.httpClient.createOauthProviders( + { + userId, + oauthProviders: [ + { + providerName, + oidcToken, + }, + ], + }, + stampWith, + ); + + if (!createProviderRes) { + throw new TurnkeyError( + "Failed to create OAuth provider", + TurnkeyErrorCodes.ADD_OAUTH_PROVIDER_ERROR, + ); + } + + return createProviderRes?.providerIds || []; + }, + { + errorMessage: "Failed to add OAuth provider", + errorCode: TurnkeyErrorCodes.ADD_OAUTH_PROVIDER_ERROR, + }, + ); + }; + + /** + * Removes a list of OAuth providers from the user. + * + * - This function removes OAuth providers (e.g., Google, Apple) from the user's account. + * - If a userId is provided, it removes the providers for that specific user; otherwise, it uses the current session's userId. + * - Automatically ensures an active session exists before making the request. + * - Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + * - Returns an array of remaining provider IDs associated with the user after removal. + * + * @param params.providerIds - IDs of the OAuth providers to remove. + * @param params.userId - user ID to remove the provider for a specific user (defaults to the current session's userId). + * @param params.stampWith - parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + * @returns A promise that resolves to an array of provider IDs that were removed. + * @throws {TurnkeyError} If there is no active session, if the userId is missing, or if there is an error removing the OAuth provider. + */ + removeOauthProviders = async (params: { + providerIds: string[]; + userId?: string; + stampWith?: StamperType | undefined; + }): Promise => { + const { providerIds, stampWith } = params; + const session = await this.storageManager.getActiveSession(); + if (!session) { + throw new TurnkeyError( + "No active session found. Please log in first.", + TurnkeyErrorCodes.NO_SESSION_FOUND, + ); + } + const userId = params?.userId || session.userId; + return withTurnkeyErrorHandling( + async () => { + const res = await this.httpClient.deleteOauthProviders( + { + userId, + providerIds, + }, + stampWith, + ); + if (!res) { + throw new TurnkeyError( + "Failed to remove OAuth provider", + TurnkeyErrorCodes.REMOVE_OAUTH_PROVIDER_ERROR, + ); + } + return res.providerIds; + }, + { + errorMessage: "Failed to remove OAuth provider", + errorCode: TurnkeyErrorCodes.REMOVE_OAUTH_PROVIDER_ERROR, + }, + ); + }; + + /** + * Adds a new passkey authenticator for the user. + * + * - This function prompts the user to create a new passkey (WebAuthn/FIDO2) and adds it as an authenticator for the user. + * - Handles both web and React Native environments, automatically selecting the appropriate passkey creation flow. + * - If a userId is provided, the passkey is added for that specific user; otherwise, it uses the current session's userId. + * - The passkey's name and display name can be customized; if not provided, defaults are generated. + * - The resulting passkey attestation and challenge are registered with Turnkey as a new authenticator. + * + * @param params.name - name of the passkey (defaults to "Turnkey Passkey-`timestamp`"). + * @param params.displayName - display name of the passkey (defaults to the value of `name`). + * @param params.userId - user ID to add the passkey for a specific user (defaults to the current session's userId). + * @param params.stampWith - parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + * @returns A promise that resolves to an array of authenticator IDs for the newly added passkey(s). + * @throws {TurnkeyError} If there is no active session, if passkey creation fails, or if there is an error adding the passkey. + */ + addPasskey = async (params?: { + name?: string; + displayName?: string; + userId?: string; + stampWith?: StamperType | undefined; + }): Promise => { + const { stampWith } = params || {}; + const name = params?.name || `Turnkey Passkey-${Date.now()}`; + const displayName = params?.displayName || name; + + return withTurnkeyErrorHandling( + async () => { + const session = await this.storageManager.getActiveSession(); + if (!session) { + throw new TurnkeyError( + "No active session found. Please log in first.", + TurnkeyErrorCodes.NO_SESSION_FOUND, + ); + } + + const userId = params?.userId || session.userId; + + const { encodedChallenge, attestation } = await this.createPasskey({ + name, + displayName, + ...(stampWith && { stampWith }), + }); + + if (!attestation || !encodedChallenge) { + throw new TurnkeyError( + "Failed to create passkey challenge and attestation", + TurnkeyErrorCodes.CREATE_PASSKEY_ERROR, + ); + } + + const res = await this.httpClient.createAuthenticators( + { + userId, + authenticators: [ + { + authenticatorName: name, + challenge: encodedChallenge, + attestation, + }, + ], + }, + stampWith, + ); + + return res?.authenticatorIds || []; + }, + { + errorMessage: "Failed to add passkey", + errorCode: TurnkeyErrorCodes.ADD_PASSKEY_ERROR, + }, + ); + }; + + /** + * Removes passkeys (authenticator) from the user. + * + * - This function removes passkeys (WebAuthn/FIDO2 authenticators) from the user's account. + * - If a userId is provided, it removes the passkeys for that specific user; otherwise, it uses the current session's userId. + * - Automatically ensures an active session exists before making the request. + * - Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + * - Returns an array of remaining authenticator IDs for the user after removal. + * + * @param params.authenticatorIds - IDs of the authenticators (passkeys) to remove. + * @param params.userId - user ID to remove the passkeys for a specific user (defaults to the current session's userId). + * @param params.stampWith - parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + * @returns A promise that resolves to an array of authenticator IDs that were removed. + * @throws {TurnkeyError} If there is no active session, if the userId is missing, or if there is an error removing the passkeys. + */ + removePasskeys = async (params: { + authenticatorIds: string[]; + userId?: string; + stampWith?: StamperType | undefined; + }): Promise => { + const { authenticatorIds, stampWith } = params; + const session = await this.storageManager.getActiveSession(); + if (!session) { + throw new TurnkeyError( + "No active session found. Please log in first.", + TurnkeyErrorCodes.NO_SESSION_FOUND, + ); + } + const userId = params?.userId || session.userId; + + return withTurnkeyErrorHandling( + async () => { + const res = await this.httpClient.deleteAuthenticators( + { + userId, + authenticatorIds, + }, + stampWith, + ); + if (!res) { + throw new TurnkeyError( + "No response found in the remove passkey response", + TurnkeyErrorCodes.REMOVE_PASSKEY_ERROR, + ); + } + return res.authenticatorIds; + }, + { + errorMessage: "Failed to remove passkey", + errorCode: TurnkeyErrorCodes.REMOVE_PASSKEY_ERROR, + }, + ); + }; + + /** + * Creates a new wallet for sub-organization. + * + * - This function creates a new wallet for the current sub-organization. + * - If an organizationId is provided, the wallet will be created under that specific sub-organization; otherwise, it uses the current session's organizationId. + * - If a list of address formats is provided, accounts will be created in the wallet based on those formats (starting from path index 0). + * - If a list of account parameters is provided, those accounts will be created in the wallet. + * - If no accounts or address formats are provided, default Ethereum and Solana accounts will be created. + * - Optionally allows specifying the mnemonic length for the wallet seed phrase (defaults to 12). + * - Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + * + * @param params.walletName - name of the wallet to create. + * @param params.accounts - array of account parameters or address formats to create in the wallet. + * @param params.organizationId - organization ID to create the wallet under a specific sub-organization (defaults to the current session's organizationId). + * @param params.mnemonicLength - mnemonic length for the wallet seed phrase (defaults to 12). + * @param params.stampWith - parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + * @returns A promise that resolves to the ID of the newly created wallet. + * @throws {TurnkeyError} If there is no active session or if there is an error creating the wallet. + */ + createWallet = async (params: { + walletName: string; + accounts?: v1WalletAccountParams[] | v1AddressFormat[]; + organizationId?: string; + mnemonicLength?: number; + stampWith?: StamperType | undefined; + }): Promise => { + const { walletName, accounts, organizationId, mnemonicLength, stampWith } = + params; + const session = await this.storageManager.getActiveSession(); + if (!session) { + throw new TurnkeyError( + "No active session found. Please log in first.", + TurnkeyErrorCodes.NO_SESSION_FOUND, + ); + } + + let walletAccounts: v1WalletAccountParams[] = []; + if (accounts && !isWalletAccountArray(accounts)) { + walletAccounts = generateWalletAccountsFromAddressFormat({ + addresses: accounts, + }); + } else { + walletAccounts = (accounts as v1WalletAccountParams[]) || [ + ...DEFAULT_ETHEREUM_ACCOUNTS, + ...DEFAULT_SOLANA_ACCOUNTS, + ]; + } + + return withTurnkeyErrorHandling( + async () => { + const res = await this.httpClient.createWallet( + { + organizationId: organizationId || session.organizationId, + walletName, + accounts: walletAccounts, + mnemonicLength: mnemonicLength || 12, + }, + stampWith, + ); + + if (!res || !res.walletId) { + throw new TurnkeyError( + "No wallet found in the create wallet response", + TurnkeyErrorCodes.BAD_RESPONSE, + ); + } + return res.walletId; + }, + { + errorMessage: "Failed to create wallet", + errorCode: TurnkeyErrorCodes.CREATE_WALLET_ERROR, + }, + ); + }; + + /** + * Creates new accounts in the specified wallet. + * + * - This function creates new wallet accounts based on the provided account parameters or address formats. + * - If a walletId is provided, it creates the accounts in that specific wallet; otherwise, it uses the current session's wallet. + * - If a list of address formats is provided, it will create accounts in the wallet based on those formats, automatically determining the next available path indexes to avoid duplicates with existing accounts. + * - If account parameters are provided, they are used directly for account creation. + * - Automatically queries existing wallet accounts to prevent duplicate account creation for the same address format and path. + * - Supports stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + * + * @param params.accounts - An array of account parameters or address formats to create in the wallet. + * @param params.walletId - ID of the wallet to create accounts in. + * @param params.organizationId - organization ID to create the accounts under a specific organization (walletId must be associated with the sub-organization). + * @param params.stampWith - parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + * @returns A promise that resolves to an array of addresses for the newly created accounts. + * @throws {TurnkeyError} If there is no active session, if the wallet does not exist, or if there is an error creating the wallet accounts. + */ + createWalletAccounts = async (params: { + accounts: v1WalletAccountParams[] | v1AddressFormat[]; + walletId: string; + organizationId?: string; + stampWith?: StamperType | undefined; + }): Promise => { + const { accounts, walletId, organizationId, stampWith } = params; + const session = await this.storageManager.getActiveSession(); + if (!session) { + throw new TurnkeyError( + "No active session found. Please log in first.", + TurnkeyErrorCodes.NO_SESSION_FOUND, + ); + } + return withTurnkeyErrorHandling( + async () => { + let walletAccounts: v1WalletAccountParams[] = []; + if (accounts && !isWalletAccountArray(accounts)) { + // Query existing wallet accounts to avoid duplicates + const existingWalletAccounts = + await this.httpClient.getWalletAccounts( + { + walletId, + organizationId: organizationId || session.organizationId, + paginationOptions: { limit: "100" }, + }, + stampWith, + ); + walletAccounts = generateWalletAccountsFromAddressFormat({ + addresses: accounts, + existingWalletAccounts: existingWalletAccounts.accounts || [], + }); + } else { + walletAccounts = accounts; + } + + const res = await this.httpClient.createWalletAccounts( + { + organizationId: organizationId || session.organizationId, + walletId, + accounts: walletAccounts, + }, + stampWith, + ); + + if (!res || !res.addresses) { + throw new TurnkeyError( + "No account found in the create wallet account response", + TurnkeyErrorCodes.BAD_RESPONSE, + ); + } + return res.addresses; + }, + { + errorMessage: "Failed to create wallet account", + errorCode: TurnkeyErrorCodes.CREATE_WALLET_ACCOUNT_ERROR, + }, + ); + }; + + /** + * Exports a wallet as an encrypted bundle. + * + * - This function exports the specified wallet and its accounts as an encrypted bundle, suitable for backup or transfer. + * - The exported bundle contains the wallet's seed phrase, encrypted to the provided target public key. + * - If a targetPublicKey is provided, the bundle will be encrypted to that public key; otherwise, an error will be thrown. + * - If an organizationId is provided, the wallet will be exported under that sub-organization; otherwise, the current session's organizationId is used. + * - Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + * - The exported bundle can later be imported using the `importWallet` method. + * + * @param params.walletId - ID of the wallet to export. + * @param params.targetPublicKey - public key to encrypt the bundle to (required). + * @param params.organizationId - organization ID to export the wallet under a specific sub-organization (walletId must be associated with the sub-organization). + * @param params.stampWith - parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + * @returns A promise that resolves to an `ExportBundle` object containing the encrypted wallet seed phrase and metadata. + * @throws {TurnkeyError} If there is no active session, if the targetPublicKey is missing, or if there is an error exporting the wallet. + */ + exportWallet = async (params: { + walletId: string; + targetPublicKey: string; + organizationId?: string; + stampWith?: StamperType | undefined; + }): Promise => { + const { walletId, targetPublicKey, stampWith, organizationId } = params; + const session = await this.storageManager.getActiveSession(); + if (!session) { + throw new TurnkeyError( + "No active session found. Please log in first.", + TurnkeyErrorCodes.NO_SESSION_FOUND, + ); + } + return withTurnkeyErrorHandling( + async () => { + const res = await this.httpClient.exportWallet( + { + walletId, + targetPublicKey, + organizationId: organizationId || session.organizationId, + }, + stampWith, + ); + + if (!res.exportBundle) { + throw new TurnkeyError( + "No export bundle found in the response", + TurnkeyErrorCodes.BAD_RESPONSE, + ); + } + return res.exportBundle as ExportBundle; + }, + { + errorMessage: "Failed to export wallet", + errorCode: TurnkeyErrorCodes.EXPORT_WALLET_ERROR, + }, + ); + }; + + /** + * Exports a private key as an encrypted bundle. + * + * - This function exports the specified private key as an encrypted bundle, suitable for backup or transfer. + * - The exported bundle contains the private key's key material, encrypted to the provided target public key. + * - If a targetPublicKey is provided, the bundle will be encrypted to that public key; otherwise, an error will be thrown. + * - If an organizationId is provided, the private key will be exported under that sub-organization; otherwise, the current session's organizationId is used. + * - Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + * + * @param params.privateKeyId - ID of the private key to export. + * @param params.targetPublicKey - public key to encrypt the bundle to (required). + * @param params.organizationId - organization ID to export the private key under a specific sub + * @param params.stampWith - parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + * @returns A promise that resolves to an `ExportBundle` object containing the encrypted private key and metadata. + * @throws {TurnkeyError} If there is no active session, if the targetPublicKey is missing, or if there is an error exporting the private key. + */ + exportPrivateKey = async (params: { + privateKeyId: string; + targetPublicKey: string; + organizationId?: string; + stampWith?: StamperType | undefined; + }): Promise => { + const { privateKeyId, targetPublicKey, stampWith, organizationId } = params; + const session = await this.storageManager.getActiveSession(); + if (!session) { + throw new TurnkeyError( + "No active session found. Please log in first.", + TurnkeyErrorCodes.NO_SESSION_FOUND, + ); + } + return withTurnkeyErrorHandling( + async () => { + const res = await this.httpClient.exportPrivateKey( + { + privateKeyId, + targetPublicKey, + organizationId: organizationId || session.organizationId, + }, + stampWith, + ); + if (!res.exportBundle) { + throw new TurnkeyError( + "No export bundle found in the response", + TurnkeyErrorCodes.BAD_RESPONSE, + ); + } + return res.exportBundle as ExportBundle; + }, + { + errorMessage: "Failed to export private key", + errorCode: TurnkeyErrorCodes.EXPORT_PRIVATE_KEY_ERROR, + }, + ); + }; + + /** + * Exports a wallet account as an encrypted bundle. + * + * - This function exports the specified wallet account as an encrypted bundle, suitable for backup or transfer. + * - The exported bundle contains the wallet account's key material, encrypted to the provided target public key. + * - If a targetPublicKey is provided, the bundle will be encrypted to that public key; otherwise, an error will be thrown. + * - If an organizationId is provided, the wallet account will be exported under that sub-organization; otherwise, the current session's organizationId is used. + * - Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + * + * @param params.address - address of the wallet account to export. + * @param params.targetPublicKey - public key to encrypt the bundle to. + * @param params.organizationId - organization ID to export the wallet account under a specific sub-organization. + * @param params.stampWith - parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + * @returns A promise that resolves to an `ExportBundle` object containing the encrypted wallet account and metadata. + * @throws {TurnkeyError} If there is no active session, if the targetPublicKey is missing, or if there is an error exporting the wallet account. + * + */ + exportWalletAccount = async (params: { + address: string; + targetPublicKey: string; + organizationId?: string; + stampWith?: StamperType | undefined; + }): Promise => { + const { address, targetPublicKey, stampWith, organizationId } = params; + const session = await this.storageManager.getActiveSession(); + if (!session) { + throw new TurnkeyError( + "No active session found. Please log in first.", + TurnkeyErrorCodes.NO_SESSION_FOUND, + ); + } + return withTurnkeyErrorHandling( + async () => { + const res = await this.httpClient.exportWalletAccount( + { + address, + targetPublicKey, + organizationId: organizationId || session.organizationId, + }, + stampWith, + ); + if (!res.exportBundle) { + throw new TurnkeyError( + "No export bundle found in the response", + TurnkeyErrorCodes.BAD_RESPONSE, + ); + } + return res.exportBundle as ExportBundle; + }, + { + errorMessage: "Failed to export wallet account", + errorCode: TurnkeyErrorCodes.EXPORT_WALLET_ACCOUNT_ERROR, + }, + ); + }; + + /** + * Imports a wallet from an encrypted bundle. + * + * - This function imports a wallet using the provided encrypted bundle and creates accounts based on the provided parameters. + * - If a userId is provided, the wallet will be imported for that specific user; otherwise, it uses the current session's userId. + * - If an accounts array is provided, those accounts will be created in the imported wallet; otherwise, default Ethereum and Solana accounts will be created. + * - The encrypted bundle MUST be encrypted to + * - Automatically ensures an active session exists before making the request. + * - Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + * + * @param params.encryptedBundle - encrypted bundle containing the wallet seed phrase and metadata. + * @param params.walletName - name of the wallet to create upon import. + * @param params.accounts - array of account parameters to create in the imported wallet (defaults to standard Ethereum and Solana accounts). + * @param params.userId - user ID to import the wallet for a specific user (defaults to the current session's userId). + * @param params.stampWith - parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + * @returns A promise that resolves to the ID of the imported wallet. + * @throws {TurnkeyError} If there is no active session, if the encrypted bundle is invalid, or if there is an error importing the wallet. + */ + importWallet = async (params: { + encryptedBundle: string; + walletName: string; + accounts?: v1WalletAccountParams[]; + userId?: string; + stampWith?: StamperType | undefined; + }): Promise => { + const { encryptedBundle, accounts, walletName, userId, stampWith } = params; + + const session = await this.storageManager.getActiveSession(); + if (!session) { + throw new TurnkeyError( + "No active session found. Please log in first.", + TurnkeyErrorCodes.NO_SESSION_FOUND, + ); + } + + return withTurnkeyErrorHandling( + async () => { + const res = await this.httpClient.importWallet( + { + organizationId: session.organizationId, + userId: userId || session.userId, + encryptedBundle, + walletName, + accounts: accounts || [ + ...DEFAULT_ETHEREUM_ACCOUNTS, + ...DEFAULT_SOLANA_ACCOUNTS, + ], + }, + stampWith, + ); + + if (!res || !res.walletId) { + throw new TurnkeyError( + "No wallet ID found in the import response", + TurnkeyErrorCodes.BAD_RESPONSE, + ); + } + return res.walletId; + }, + { + errorMessage: "Failed to import wallet", + errorCode: TurnkeyErrorCodes.IMPORT_WALLET_ERROR, + customMessageByMessages: { + "invalid mnemonic": { + message: "Invalid mnemonic input", + code: TurnkeyErrorCodes.BAD_REQUEST, + }, + }, + }, + ); + }; + + /** + * Imports a private key from an encrypted bundle. + * + * - This function imports a private key using the provided encrypted bundle. + * - If a userId is provided, the private key will be imported for that specific user; otherwise, it uses the current session's userId. + * - Requires address formats to + * - Automatically infers the cryptographic curve used to generate the private key based on the address format (can be optionally overriden if needed). + * - The encrypted bundle MUST be encrypted to ensure security. + * - Automatically ensures an active session exists before making the request. + * - Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + * + * @param params.encryptedBundle - encrypted bundle containing the private key key material and metadata. + * @param params.privateKeyName - name of the private key to create upon import. + * @param params.curve - the cryptographic curve used to generate a given private key + * @param params.addressFormat - address format of the private key to import. + * @param params.userId - user ID to import the wallet for a specific user (defaults to the current session's userId). + * @param params.stampWith - parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + * @returns A promise that resolves to the ID of the imported wallet. + * @throws {TurnkeyError} If there is no active session, if the encrypted bundle is invalid, or if there is an error importing the wallet. + */ + importPrivateKey = async (params: { + encryptedBundle: string; + privateKeyName: string; + curve: v1Curve; + addressFormats: v1AddressFormat[]; + userId?: string; + stampWith?: StamperType | undefined; + }): Promise => { + const { + encryptedBundle, + privateKeyName, + addressFormats, + curve, + userId, + stampWith, + } = params; + + const session = await this.storageManager.getActiveSession(); + if (!session) { + throw new TurnkeyError( + "No active session found. Please log in first.", + TurnkeyErrorCodes.NO_SESSION_FOUND, + ); + } + + return withTurnkeyErrorHandling( + async () => { + const res = await this.httpClient.importPrivateKey( + { + organizationId: session.organizationId, + userId: userId || session.userId, + encryptedBundle, + privateKeyName, + curve, + addressFormats, + }, + stampWith, + ); + + if (!res || !res.privateKeyId) { + throw new TurnkeyError( + "No wallet ID found in the import response", + TurnkeyErrorCodes.BAD_RESPONSE, + ); + } + return res.privateKeyId; + }, + { + errorMessage: "Failed to import wallet", + errorCode: TurnkeyErrorCodes.IMPORT_WALLET_ERROR, + customMessageByMessages: { + "invalid mnemonic": { + message: "Invalid mnemonic input", + code: TurnkeyErrorCodes.BAD_REQUEST, + }, + }, + }, + ); + }; + + /** + * Deletes the current sub-organization (sub-org) for the active session. + * + * - This function deletes the sub-organization associated with the current active session. + * - By default, the deletion will fail if any wallets associated with the sub-organization have not been exported. + * - If `deleteWithoutExport` is set to true, the sub-organization will be deleted even if its wallets have not been exported (potentially resulting in loss of access to those wallets). + * - Requires an active session; otherwise, an error is thrown. + * - Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + * + * @param params.deleteWithoutExport - flag to delete the sub-organization without requiring all wallets to be exported first (defaults to false). + * @param params.stampWith - parameter to stamp the request with a specific stamper. + * @returns A promise that resolves to a `TDeleteSubOrganizationResponse` object containing the result of the deletion. + * @throws {TurnkeyError} If there is no active session or if there is an error deleting the sub-organization. + */ + deleteSubOrganization = async (params?: { + deleteWithoutExport?: boolean; + stampWith?: StamperType | undefined; + }): Promise => { + const { deleteWithoutExport = false, stampWith } = params || {}; + const session = await this.storageManager.getActiveSession(); + if (!session) { + throw new TurnkeyError( + "No active session found. Please log in first.", + TurnkeyErrorCodes.NO_SESSION_FOUND, + ); + } + + return withTurnkeyErrorHandling( + async () => { + return await this.httpClient.deleteSubOrganization( + { deleteWithoutExport }, + stampWith, + ); + }, + { + errorMessage: "Failed to delete sub-organization", + errorCode: TurnkeyErrorCodes.DELETE_SUB_ORGANIZATION_ERROR, + }, + ); + }; + + /** + * Stores a session token and updates the session associated with the specified session key, or by default the active session. + * + * - This function parses and stores a signed JWT session token in local storage, associating it with the given session key. + * - If a sessionKey is provided, the session will be stored under that key; otherwise, it will use the default session key. + * - If a session already exists for the session key, its associated key pair will be deleted before storing the new session. + * - After storing the session, any unused key pairs are automatically cleared from storage. + * - Ensures that session management is consistent and prevents orphaned key pairs. + * + * @param params.sessionToken - JWT session token to store. + * @param params.sessionKey - session key to store the session under (defaults to the default session key). + * @returns A promise that resolves when the session is successfully stored. + * @throws {TurnkeyError} If there is an error storing the session or cleaning up key pairs. + */ + storeSession = async (params: { + sessionToken: string; + sessionKey?: string; + }): Promise => { + const { sessionToken, sessionKey = SessionKey.DefaultSessionkey } = params; + if (!sessionToken) return; + + withTurnkeyErrorHandling( + async () => { + const sessionToReplace = + await this.storageManager.getSession(sessionKey); + + await this.storageManager.storeSession(sessionToken, sessionKey); + + if (sessionToReplace) { + await this.apiKeyStamper?.deleteKeyPair(sessionToReplace.publicKey!); + } + }, + { + errorMessage: "Failed to store session", + errorCode: TurnkeyErrorCodes.STORE_SESSION_ERROR, + }, + { + finallyFn: async () => await this.clearUnusedKeyPairs(), + }, + ); + }; + + /** + * Clears the session associated with the specified session key, or the active session by default. + * + * - This function deletes the session and its associated key pair from storage. + * - If a sessionKey is provided, it will clear the session under that key; otherwise, it will clear the default (active) session. + * - Removes the session data from local storage and deletes the corresponding API key pair from the key store. + * - Throws an error if the session does not exist or if there is an error during the clearing process. + * + * @param params.sessionKey - session key to clear the session under (defaults to the default session key). + * @returns A promise that resolves when the session is successfully cleared. + * @throws {TurnkeyError} If the session does not exist or if there is an error clearing the session. + */ + clearSession = async (params?: { sessionKey?: string }): Promise => { + const { sessionKey = SessionKey.DefaultSessionkey } = params || {}; + withTurnkeyErrorHandling( + async () => { + const session = await this.storageManager.getSession(sessionKey); + if (session) { + await this.apiKeyStamper?.deleteKeyPair(session.publicKey!); + await this.storageManager.clearSession(sessionKey); + } else { + throw new TurnkeyError( + `No session found with key: ${sessionKey}`, + TurnkeyErrorCodes.NOT_FOUND, + ); + } + }, + { + errorMessage: "Failed to delete session", + errorCode: TurnkeyErrorCodes.CLEAR_SESSION_ERROR, + }, + ); + }; + + /** + * Clears all sessions and resets the active session state. + * + * - This function removes all session data from the client and persistent storage, including all associated key pairs. + * - Iterates through all stored session keys, clearing each session and deleting its corresponding API key pair. + * - After clearing, there will be no active session, and all session-related data will be removed from local storage. + * - Throws an error if no sessions exist or if there is an error during the clearing process. + * + * @returns A promise that resolves when all sessions are successfully cleared. + * @throws {TurnkeyError} If no sessions exist or if there is an error clearing all sessions. + */ + clearAllSessions = async (): Promise => { + withTurnkeyErrorHandling( + async () => { + const sessionKeys = await this.storageManager.listSessionKeys(); + if (sessionKeys.length === 0) { + throw new TurnkeyError( + "No sessions found to clear.", + TurnkeyErrorCodes.NO_SESSION_FOUND, + ); + } + for (const sessionKey of sessionKeys) { + this.clearSession({ sessionKey }); + } + }, + { + errorMessage: "Failed to clear all sessions", + errorCode: TurnkeyErrorCodes.CLEAR_ALL_SESSIONS_ERROR, + }, + ); + }; + + /** + * Refreshes the session associated with the specified session key, or the active session by default. + * + * - This function refreshes the session and updates the session token and key pair associated with the given session key. + * - If a sessionKey is provided, it will refresh the session under that key; otherwise, it will use the current active session key. + * - Optionally allows specifying a new expiration time for the session, a custom public key, and whether to invalidate the existing session after refreshing. + * - Makes a request to the Turnkey API to stamp a new login and stores the refreshed session token. + * - Automatically manages key pair cleanup and session storage to ensure consistency. + * - Optionally allows stamping the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet). + * + * @param params.sessionKey - session key to refresh the session under (defaults to the active session key). + * @param params.expirationSeconds - expiration time in seconds for the refreshed session (defaults to the configured default). + * @param params.publicKey - public key to use for the refreshed session (if not provided, a new key pair will be generated). + * @param params.invalidateExisitng - flag to invalidate the existing session before refreshing (defaults to false). + * @param params.stampWith - parameter to stamp the request with a specific stamper. + * @returns A promise that resolves to a `TStampLoginResponse` object containing the refreshed session details. + * @throws {TurnkeyError} If the session key does not exist, if there is no active session, or if there is an error refreshing the session. + */ + refreshSession = async (params?: { + expirationSeconds?: string; + publicKey?: string; + sessionKey?: string; + invalidateExisitng?: boolean; + stampWith?: StamperType | undefined; + }): Promise => { + const { + sessionKey = await this.storageManager.getActiveSessionKey(), + expirationSeconds = DEFAULT_SESSION_EXPIRATION_IN_SECONDS, + publicKey, + invalidateExisitng = false, + } = params || {}; + if (!sessionKey) { + throw new TurnkeyError( + "No session key provided or active session to refresh session", + TurnkeyErrorCodes.NO_SESSION_FOUND, + ); + } + const session = await this.getSession({ + sessionKey: sessionKey, + }); + if (!session) { + throw new TurnkeyError( + `No active session found: ${sessionKey}`, + TurnkeyErrorCodes.NO_SESSION_FOUND, + ); + } + + if (!this.httpClient) { + throw new TurnkeyError( + "HTTP client is not initialized. Please initialize the client before refreshing the session.", + TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED, + ); + } + + let keyPair: string | undefined; + return withTurnkeyErrorHandling( + async () => { + keyPair = publicKey ?? (await this.apiKeyStamper?.createKeyPair()); + if (!keyPair) { + throw new TurnkeyError( + "Failed to create new key pair.", + TurnkeyErrorCodes.INTERNAL_ERROR, + ); + } + const res = await this.httpClient.stampLogin( + { + publicKey: keyPair, + expirationSeconds, + invalidateExisting: invalidateExisitng, + }, + params?.stampWith, + ); + + if (!res || !res.session) { + throw new TurnkeyError( + "No session found in the refresh response", + TurnkeyErrorCodes.BAD_RESPONSE, + ); + } + + await this.storeSession({ + sessionToken: res.session, + ...(sessionKey && { sessionKey }), + }); + return res; + }, + { + errorMessage: "Failed to refresh session", + errorCode: TurnkeyErrorCodes.REFRESH_SESSION_ERROR, + }, + ); + }; + + /** + * Retrieves the session associated with the specified session key, or the active session by default. + * + * - This function retrieves the session object from storage, using the provided session key or, if not specified, the current active session key. + * - If no session key is provided and there is no active session, it returns undefined. + * - Returns the session details, including public key, organization ID, user ID, and expiration. + * + * @param params.sessionKey - session key to retrieve a specific session (defaults to the current active session key). + * @returns A promise that resolves to a `Session` object containing the session details, or undefined if not found. + * @throws {TurnkeyError} If there is an error retrieving the session from storage. + */ + getSession = async (params?: { + sessionKey?: string; + }): Promise => { + return withTurnkeyErrorHandling( + async () => { + const { sessionKey = await this.storageManager.getActiveSessionKey() } = + params || {}; + return this.storageManager.getSession(sessionKey); + }, + { + errorMessage: "Failed to get session with key " + params?.sessionKey, + errorCode: TurnkeyErrorCodes.GET_SESSION_ERROR, + }, + ); + }; + + /** + * Retrieves all sessions stored in persistent storage. + * + * - This function fetches all session objects currently stored by the client, including those that are not active. + * - Returns a record mapping each session key to its corresponding `Session` object. + * - Useful for session management, auditing, or displaying all available sessions to the user. + * - Automatically skips any session keys that do not have a valid session object. + * + * @returns A promise that resolves to a record of session keys and their corresponding `Session` objects, or `undefined` if no sessions exist. + * @throws {TurnkeyError} If there is an error retrieving sessions from storage. + */ + getAllSessions = async (): Promise | undefined> => { + return withTurnkeyErrorHandling( + async () => { + const sessionKeys = await this.storageManager.listSessionKeys(); + if (!sessionKeys || sessionKeys.length === 0) { + return undefined; + } + const sessions: Record = {}; + for (const sessionKey of sessionKeys) { + const session = await this.storageManager.getSession(sessionKey); + if (session) { + sessions[sessionKey] = session; + } + } + return sessions || undefined; + }, + { + errorMessage: "Failed to get all sessions", + errorCode: TurnkeyErrorCodes.GET_ALL_SESSIONS_ERROR, + }, + ); + }; + + /** + * Sets the active session to the specified session key. + * + * - This function updates the `activeSessionKey` in persistent storage to the specified session key. + * - Ensures that subsequent operations use the session associated with this key as the active session. + * - Does not validate whether the session key exists or is valid; it simply updates the pointer. + * - Useful for switching between multiple stored sessions or restoring a previous session context. + * + * @param params.sessionKey - session key to set as the active session. + * @returns A promise that resolves when the active session key is successfully set. + * @throws {TurnkeyError} If the client is not initialized or if there is an error setting the active session key. + */ + setActiveSession = async (params: { sessionKey: string }): Promise => { + const { sessionKey } = params; + return withTurnkeyErrorHandling( + async () => { + await this.storageManager.setActiveSessionKey(sessionKey); + }, + { + errorMessage: "Failed to set active session", + errorCode: TurnkeyErrorCodes.SET_ACTIVE_SESSION_ERROR, + }, + ); + }; + + /** + * Retrieves the active session key currently set in persistent storage. + * + * - This function fetches the session key that is currently marked as active in the client's persistent storage. + * - The active session key determines which session is used for all session-dependent operations. + * - If no active session key is set, returns `undefined`. + * - Useful for determining which session is currently in use, especially when managing multiple sessions. + * + * @returns A promise that resolves to the active session key as a string, or `undefined` if no active session is set. + * @throws {TurnkeyError} If there is an error retrieving the active session key from storage. + */ + getActiveSessionKey = async (): Promise => { + return withTurnkeyErrorHandling( + async () => { + return await this.storageManager.getActiveSessionKey(); + }, + { + errorMessage: "Failed to get active session key", + errorCode: TurnkeyErrorCodes.GET_ACTIVE_SESSION_KEY_ERROR, + }, + ); + }; + + /** + * Clears any unused API key pairs from persistent storage. + * + * - This function scans all API key pairs stored in indexedDB and removes any key pairs that are not associated with a session in persistent storage. + * - Ensures that only key pairs referenced by existing sessions are retained, preventing orphaned or stale key pairs from accumulating. + * - Iterates through all stored session keys and builds a map of in-use public keys, then deletes any key pairs not present in this map. + * - Intended to be called after session changes (e.g., login, logout, session replacement) to keep key storage clean and secure. + * + * @returns A promise that resolves when all unused key pairs are successfully cleared. + * @throws {TurnkeyError} If there is an error listing, checking, or deleting unused key pairs. + */ + clearUnusedKeyPairs = async (): Promise => { + withTurnkeyErrorHandling( + async () => { + const publicKeys = await this.apiKeyStamper?.listKeyPairs(); + if (!publicKeys || publicKeys.length === 0) { + return; + } + const sessionKeys = await this.storageManager?.listSessionKeys(); + + const sessionTokensMap: Record = {}; + for (const sessionKey of sessionKeys) { + const session = await this.storageManager.getSession(sessionKey); + if (session) { + sessionTokensMap[session.publicKey!] = sessionKey; + } + } + + for (const publicKey of publicKeys) { + if (!sessionTokensMap[publicKey]) { + try { + await this.apiKeyStamper?.deleteKeyPair(publicKey); + } catch (error) { + throw new TurnkeyError( + `Failed to delete unused key pair ${publicKey}`, + TurnkeyErrorCodes.INTERNAL_ERROR, + error, + ); + } + } + } + }, + { + errorMessage: "Failed to clear unused key pairs", + errorCode: TurnkeyErrorCodes.CLEAR_UNUSED_KEY_PAIRS_ERROR, + }, + ); + }; + + /** + * Creates a new API key pair and returns the public key. + * + * - This function generates a new API key pair and stores it in the underlying key store (IndexedDB). + * - If an external key pair is provided, it will use that key pair for creation instead of generating a new one. + * - If `storeOverride` is set to true, the generated or provided public key will be set as the override key in the API key stamper, making it the active key for subsequent signing operations. + * - Ensures the API key stamper is initialized before proceeding. + * - Handles both native CryptoKeyPair objects and raw key material. + * + * @param params.externalKeyPair - An externally generated key pair (either a CryptoKeyPair or an object with publicKey/privateKey strings) to use instead of generating a new one. + * @param params.storeOverride - If true, sets the generated or provided public key as the override key in the API key stamper (defaults to false). + * @returnparams.s A promise that resolves to the public key of the created or provided API key pair as a string. + * @throws {TurnkeyError} If the API key stamper is not initialized or if there is an error during key pair creation or storage. + */ + createApiKeyPair = async (params?: { + externalKeyPair?: CryptoKeyPair | { publicKey: string; privateKey: string }; + storeOverride?: boolean; + }): Promise => { + return withTurnkeyErrorHandling( + async () => { + const externalKeyPair = params?.externalKeyPair; + const storeOverride = params?.storeOverride ?? false; + + if (!this.apiKeyStamper) { + throw new TurnkeyError( + "API Key Stamper is not initialized.", + TurnkeyErrorCodes.INTERNAL_ERROR, + ); + } + const publicKey = await this.apiKeyStamper.createKeyPair( + externalKeyPair ? externalKeyPair : undefined, + ); + + if (storeOverride && publicKey) { + await this.apiKeyStamper.setPublicKeyOverride(publicKey); + } + + return publicKey; + }, + { + errorMessage: "Failed to create API key pair", + errorCode: TurnkeyErrorCodes.CREATE_API_KEY_PAIR_ERROR, + }, + ); + }; + + /** + * Fetches the WalletKit proxy authentication configuration from the auth proxy. + * + * - This function makes a request to the Turnkey auth proxy to retrieve the current WalletKit configuration, + * including supported authentication methods, OAuth providers, and any custom proxy settings. + * - Useful for dynamically configuring the client UI or authentication flows based on the proxy's capabilities. + * - Ensures that the client is aware of the latest proxy-side configuration, which may affect available login/signup options. + * + * @returns A promise that resolves to a `ProxyTGetWalletKitConfigResponse` object containing the proxy authentication configuration. + * @throws {TurnkeyError} If there is an error retrieving the proxy authentication configuration from the auth proxy. + */ + getProxyAuthConfig = async (): Promise => { + return withTurnkeyErrorHandling( + async () => { + const res = await this.httpClient.proxyGetWalletKitConfig({}); + + if (!res) { + throw new TurnkeyError( + `Failed to fetch auth proxy config`, + TurnkeyErrorCodes.GET_PROXY_AUTH_CONFIG_ERROR, + ); + } + + return res; + }, + { + errorMessage: "Failed to get auth proxy config", + errorCode: TurnkeyErrorCodes.GET_PROXY_AUTH_CONFIG_ERROR, + }, + ); + }; +} diff --git a/packages/core/src/__generated__/sdk-client-base.ts b/packages/core/src/__generated__/sdk-client-base.ts new file mode 100644 index 000000000..f7e73c523 --- /dev/null +++ b/packages/core/src/__generated__/sdk-client-base.ts @@ -0,0 +1,4907 @@ +/* @generated by codegen. DO NOT EDIT BY HAND */ + +import { + TERMINAL_ACTIVITY_STATUSES, + TActivityResponse, + TActivityStatus, + TSignedRequest, +} from "@turnkey/http"; + +import { + GrpcStatus, + TStamper, + TurnkeyRequestError, + TurnkeyHttpClientConfig, + StorageBase, +} from "../__types__/base"; + +import { VERSION } from "../__generated__/version"; + +import type * as SdkTypes from "@turnkey/sdk-types"; + +import { TurnkeyError, TurnkeyErrorCodes } from "@turnkey/sdk-types"; + +import { StamperType } from "../__types__/base"; + +export class TurnkeySDKClientBase { + config: TurnkeyHttpClientConfig; + + // Store stampers + private apiKeyStamper?: TStamper | undefined; + private passkeyStamper?: TStamper | undefined; + private walletStamper?: TStamper | undefined; + + // Storage manager + private storageManager?: StorageBase | undefined; + + constructor(config: TurnkeyHttpClientConfig) { + this.config = config; + + if (config.apiKeyStamper) { + this.apiKeyStamper = config.apiKeyStamper; + } + if (config.passkeyStamper) { + this.passkeyStamper = config.passkeyStamper; + } + if (config.walletStamper) { + this.walletStamper = config.walletStamper; + } + if (config.storageManager) { + this.storageManager = config.storageManager; + } + } + + private getStamper(stampWith?: StamperType): TStamper | undefined { + if (!stampWith) + return this.apiKeyStamper || this.passkeyStamper || this.walletStamper; + + switch (stampWith) { + case StamperType.ApiKey: + return this.apiKeyStamper; + case StamperType.Passkey: + return this.passkeyStamper; + case StamperType.Wallet: + return this.walletStamper; + default: + return this.apiKeyStamper; + } + } + + async request( + url: string, + body: TBodyType, + stampWith?: StamperType, + ): Promise { + const fullUrl = this.config.apiBaseUrl + url; + const stringifiedBody = JSON.stringify(body); + var headers: Record = { + "X-Client-Version": VERSION, + }; + + // Use the specified stamper for this request + const activeStamper = this.getStamper(stampWith); + + if (activeStamper) { + const stamp = await activeStamper.stamp(stringifiedBody); + headers[stamp.stampHeaderName] = stamp.stampHeaderValue; + } + + if (this.config.readOnlySession) { + headers["X-Session"] = this.config.readOnlySession; + } + + const response = await fetch(fullUrl, { + method: "POST", + headers: headers, + body: stringifiedBody, + redirect: "follow", + }); + + if (!response.ok) { + let res: GrpcStatus; + try { + res = await response.json(); + } catch (_) { + throw new Error(`${response.status} ${response.statusText}`); + } + + throw new TurnkeyRequestError(res); + } + + const data = await response.json(); + return data as TResponseType; + } + + async activity( + url: string, + body: TBodyType, + resultKey: string, + stampWith?: StamperType, + ): Promise { + const pollingDuration = this.config.activityPoller?.intervalMs ?? 1000; + const maxRetries = this.config.activityPoller?.numRetries ?? 3; + + const sleep = (ms: number) => + new Promise((resolve) => setTimeout(resolve, ms)); + + const handleResponse = (activityData: TActivityResponse): TResponseType => { + const { result, status } = activityData.activity; + + if (status === "ACTIVITY_STATUS_COMPLETED") { + return { + ...result[`${resultKey}` as keyof SdkTypes.v1Result], + ...activityData, + } as TResponseType; + } + + return activityData as TResponseType; + }; + + let attempts = 0; + + const pollStatus = async (activityId: string): Promise => { + const pollBody = { activityId }; + // Pass the stampWith parameter to getActivity + const pollData = (await this.getActivity( + pollBody, + stampWith, + )) as TActivityResponse; + + if (attempts > maxRetries) { + return handleResponse(pollData); + } + + attempts += 1; + + if ( + !TERMINAL_ACTIVITY_STATUSES.includes( + pollData.activity.status as TActivityStatus, + ) + ) { + await sleep(pollingDuration); + return pollStatus(activityId); + } + + return handleResponse(pollData); + }; + + // Use the specified stamper for the initial request + const responseData = (await this.request( + url, + body, + stampWith, + )) as TActivityResponse; + + if ( + !TERMINAL_ACTIVITY_STATUSES.includes( + responseData.activity.status as TActivityStatus, + ) + ) { + return pollStatus(responseData.activity.id); + } + + return handleResponse(responseData); + } + + async activityDecision( + url: string, + body: TBodyType, + stampWith?: StamperType, + ): Promise { + // Use the specified stamper for this request + const activityData = (await this.request( + url, + body, + stampWith, + )) as TActivityResponse; + + return { + ...activityData["activity"]["result"], + ...activityData, + } as TResponseType; + } + + async authProxyRequest( + url: string, + body: TBodyType, + ): Promise { + if (!this.config.authProxyUrl || !this.config.authProxyConfigId) { + throw new TurnkeyError( + "Auth Proxy URL or ID is not configured.", + TurnkeyErrorCodes.INVALID_CONFIGURATION, + ); + } + const fullUrl = this.config.authProxyUrl + url; + const stringifiedBody = JSON.stringify(body); + var headers: Record = { + "Content-Type": "application/json", + "X-Auth-Proxy-Config-ID": this.config.authProxyConfigId, + }; + + const response = await fetch(fullUrl, { + method: "POST", + headers: headers, + body: stringifiedBody, + }); + + if (!response.ok) { + let res: GrpcStatus; + try { + res = await response.json(); + } catch (_) { + throw new Error(`${response.status} ${response.statusText}`); + } + + throw new TurnkeyRequestError(res); + } + + const data = await response.json(); + return data as TResponseType; + } + + getActivity = async ( + input: SdkTypes.TGetActivityBody, + stampWith?: StamperType, + ): Promise => { + const session = await this.storageManager?.getActiveSession(); + return this.request( + "/public/v1/query/get_activity", + { + ...input, + organizationId: + input.organizationId ?? + session?.organizationId ?? + this.config.organizationId, + }, + stampWith, + ); + }; + + stampGetActivity = async ( + input: SdkTypes.TGetActivityBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, ...parameters } = input; + + const fullUrl = this.config.apiBaseUrl + "/public/v1/query/get_activity"; + const bodyWithType = { + parameters, + organizationId, + type: "ACTIVITY_TYPE_GET_ACTIVITY", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + getApiKey = async ( + input: SdkTypes.TGetApiKeyBody, + stampWith?: StamperType, + ): Promise => { + const session = await this.storageManager?.getActiveSession(); + return this.request( + "/public/v1/query/get_api_key", + { + ...input, + organizationId: + input.organizationId ?? + session?.organizationId ?? + this.config.organizationId, + }, + stampWith, + ); + }; + + stampGetApiKey = async ( + input: SdkTypes.TGetApiKeyBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, ...parameters } = input; + + const fullUrl = this.config.apiBaseUrl + "/public/v1/query/get_api_key"; + const bodyWithType = { + parameters, + organizationId, + type: "ACTIVITY_TYPE_GET_API_KEY", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + getApiKeys = async ( + input: SdkTypes.TGetApiKeysBody = {}, + stampWith?: StamperType, + ): Promise => { + const session = await this.storageManager?.getActiveSession(); + return this.request( + "/public/v1/query/get_api_keys", + { + ...input, + organizationId: + input.organizationId ?? + session?.organizationId ?? + this.config.organizationId, + }, + stampWith, + ); + }; + + stampGetApiKeys = async ( + input: SdkTypes.TGetApiKeysBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, ...parameters } = input; + + const fullUrl = this.config.apiBaseUrl + "/public/v1/query/get_api_keys"; + const bodyWithType = { + parameters, + organizationId, + type: "ACTIVITY_TYPE_GET_API_KEYS", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + getAttestationDocument = async ( + input: SdkTypes.TGetAttestationDocumentBody, + stampWith?: StamperType, + ): Promise => { + const session = await this.storageManager?.getActiveSession(); + return this.request( + "/public/v1/query/get_attestation", + { + ...input, + organizationId: + input.organizationId ?? + session?.organizationId ?? + this.config.organizationId, + }, + stampWith, + ); + }; + + stampGetAttestationDocument = async ( + input: SdkTypes.TGetAttestationDocumentBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, ...parameters } = input; + + const fullUrl = this.config.apiBaseUrl + "/public/v1/query/get_attestation"; + const bodyWithType = { + parameters, + organizationId, + type: "ACTIVITY_TYPE_GET_ATTESTATION_DOCUMENT", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + getAuthenticator = async ( + input: SdkTypes.TGetAuthenticatorBody, + stampWith?: StamperType, + ): Promise => { + const session = await this.storageManager?.getActiveSession(); + return this.request( + "/public/v1/query/get_authenticator", + { + ...input, + organizationId: + input.organizationId ?? + session?.organizationId ?? + this.config.organizationId, + }, + stampWith, + ); + }; + + stampGetAuthenticator = async ( + input: SdkTypes.TGetAuthenticatorBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/query/get_authenticator"; + const bodyWithType = { + parameters, + organizationId, + type: "ACTIVITY_TYPE_GET_AUTHENTICATOR", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + getAuthenticators = async ( + input: SdkTypes.TGetAuthenticatorsBody, + stampWith?: StamperType, + ): Promise => { + const session = await this.storageManager?.getActiveSession(); + return this.request( + "/public/v1/query/get_authenticators", + { + ...input, + organizationId: + input.organizationId ?? + session?.organizationId ?? + this.config.organizationId, + }, + stampWith, + ); + }; + + stampGetAuthenticators = async ( + input: SdkTypes.TGetAuthenticatorsBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/query/get_authenticators"; + const bodyWithType = { + parameters, + organizationId, + type: "ACTIVITY_TYPE_GET_AUTHENTICATORS", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + getOauthProviders = async ( + input: SdkTypes.TGetOauthProvidersBody, + stampWith?: StamperType, + ): Promise => { + const session = await this.storageManager?.getActiveSession(); + return this.request( + "/public/v1/query/get_oauth_providers", + { + ...input, + organizationId: + input.organizationId ?? + session?.organizationId ?? + this.config.organizationId, + }, + stampWith, + ); + }; + + stampGetOauthProviders = async ( + input: SdkTypes.TGetOauthProvidersBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/query/get_oauth_providers"; + const bodyWithType = { + parameters, + organizationId, + type: "ACTIVITY_TYPE_GET_OAUTH_PROVIDERS", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + getOrganization = async ( + input: SdkTypes.TGetOrganizationBody = {}, + stampWith?: StamperType, + ): Promise => { + const session = await this.storageManager?.getActiveSession(); + return this.request( + "/public/v1/query/get_organization", + { + ...input, + organizationId: + input.organizationId ?? + session?.organizationId ?? + this.config.organizationId, + }, + stampWith, + ); + }; + + stampGetOrganization = async ( + input: SdkTypes.TGetOrganizationBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/query/get_organization"; + const bodyWithType = { + parameters, + organizationId, + type: "ACTIVITY_TYPE_GET_ORGANIZATION", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + getOrganizationConfigs = async ( + input: SdkTypes.TGetOrganizationConfigsBody, + stampWith?: StamperType, + ): Promise => { + const session = await this.storageManager?.getActiveSession(); + return this.request( + "/public/v1/query/get_organization_configs", + { + ...input, + organizationId: + input.organizationId ?? + session?.organizationId ?? + this.config.organizationId, + }, + stampWith, + ); + }; + + stampGetOrganizationConfigs = async ( + input: SdkTypes.TGetOrganizationConfigsBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/query/get_organization_configs"; + const bodyWithType = { + parameters, + organizationId, + type: "ACTIVITY_TYPE_GET_ORGANIZATION_CONFIGS", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + getPolicy = async ( + input: SdkTypes.TGetPolicyBody, + stampWith?: StamperType, + ): Promise => { + const session = await this.storageManager?.getActiveSession(); + return this.request( + "/public/v1/query/get_policy", + { + ...input, + organizationId: + input.organizationId ?? + session?.organizationId ?? + this.config.organizationId, + }, + stampWith, + ); + }; + + stampGetPolicy = async ( + input: SdkTypes.TGetPolicyBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, ...parameters } = input; + + const fullUrl = this.config.apiBaseUrl + "/public/v1/query/get_policy"; + const bodyWithType = { + parameters, + organizationId, + type: "ACTIVITY_TYPE_GET_POLICY", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + getPolicyEvaluations = async ( + input: SdkTypes.TGetPolicyEvaluationsBody, + stampWith?: StamperType, + ): Promise => { + const session = await this.storageManager?.getActiveSession(); + return this.request( + "/public/v1/query/get_policy_evaluations", + { + ...input, + organizationId: + input.organizationId ?? + session?.organizationId ?? + this.config.organizationId, + }, + stampWith, + ); + }; + + stampGetPolicyEvaluations = async ( + input: SdkTypes.TGetPolicyEvaluationsBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/query/get_policy_evaluations"; + const bodyWithType = { + parameters, + organizationId, + type: "ACTIVITY_TYPE_GET_POLICY_EVALUATIONS", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + getPrivateKey = async ( + input: SdkTypes.TGetPrivateKeyBody, + stampWith?: StamperType, + ): Promise => { + const session = await this.storageManager?.getActiveSession(); + return this.request( + "/public/v1/query/get_private_key", + { + ...input, + organizationId: + input.organizationId ?? + session?.organizationId ?? + this.config.organizationId, + }, + stampWith, + ); + }; + + stampGetPrivateKey = async ( + input: SdkTypes.TGetPrivateKeyBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, ...parameters } = input; + + const fullUrl = this.config.apiBaseUrl + "/public/v1/query/get_private_key"; + const bodyWithType = { + parameters, + organizationId, + type: "ACTIVITY_TYPE_GET_PRIVATE_KEY", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + getSmartContractInterface = async ( + input: SdkTypes.TGetSmartContractInterfaceBody, + stampWith?: StamperType, + ): Promise => { + const session = await this.storageManager?.getActiveSession(); + return this.request( + "/public/v1/query/get_smart_contract_interface", + { + ...input, + organizationId: + input.organizationId ?? + session?.organizationId ?? + this.config.organizationId, + }, + stampWith, + ); + }; + + stampGetSmartContractInterface = async ( + input: SdkTypes.TGetSmartContractInterfaceBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/query/get_smart_contract_interface"; + const bodyWithType = { + parameters, + organizationId, + type: "ACTIVITY_TYPE_GET_SMART_CONTRACT_INTERFACE", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + getUser = async ( + input: SdkTypes.TGetUserBody, + stampWith?: StamperType, + ): Promise => { + const session = await this.storageManager?.getActiveSession(); + return this.request( + "/public/v1/query/get_user", + { + ...input, + organizationId: + input.organizationId ?? + session?.organizationId ?? + this.config.organizationId, + }, + stampWith, + ); + }; + + stampGetUser = async ( + input: SdkTypes.TGetUserBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, ...parameters } = input; + + const fullUrl = this.config.apiBaseUrl + "/public/v1/query/get_user"; + const bodyWithType = { + parameters, + organizationId, + type: "ACTIVITY_TYPE_GET_USER", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + getWallet = async ( + input: SdkTypes.TGetWalletBody, + stampWith?: StamperType, + ): Promise => { + const session = await this.storageManager?.getActiveSession(); + return this.request( + "/public/v1/query/get_wallet", + { + ...input, + organizationId: + input.organizationId ?? + session?.organizationId ?? + this.config.organizationId, + }, + stampWith, + ); + }; + + stampGetWallet = async ( + input: SdkTypes.TGetWalletBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, ...parameters } = input; + + const fullUrl = this.config.apiBaseUrl + "/public/v1/query/get_wallet"; + const bodyWithType = { + parameters, + organizationId, + type: "ACTIVITY_TYPE_GET_WALLET", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + getWalletAccount = async ( + input: SdkTypes.TGetWalletAccountBody, + stampWith?: StamperType, + ): Promise => { + const session = await this.storageManager?.getActiveSession(); + return this.request( + "/public/v1/query/get_wallet_account", + { + ...input, + organizationId: + input.organizationId ?? + session?.organizationId ?? + this.config.organizationId, + }, + stampWith, + ); + }; + + stampGetWalletAccount = async ( + input: SdkTypes.TGetWalletAccountBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/query/get_wallet_account"; + const bodyWithType = { + parameters, + organizationId, + type: "ACTIVITY_TYPE_GET_WALLET_ACCOUNT", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + getActivities = async ( + input: SdkTypes.TGetActivitiesBody = {}, + stampWith?: StamperType, + ): Promise => { + const session = await this.storageManager?.getActiveSession(); + return this.request( + "/public/v1/query/list_activities", + { + ...input, + organizationId: + input.organizationId ?? + session?.organizationId ?? + this.config.organizationId, + }, + stampWith, + ); + }; + + stampGetActivities = async ( + input: SdkTypes.TGetActivitiesBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, ...parameters } = input; + + const fullUrl = this.config.apiBaseUrl + "/public/v1/query/list_activities"; + const bodyWithType = { + parameters, + organizationId, + type: "ACTIVITY_TYPE_GET_ACTIVITIES", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + getPolicies = async ( + input: SdkTypes.TGetPoliciesBody = {}, + stampWith?: StamperType, + ): Promise => { + const session = await this.storageManager?.getActiveSession(); + return this.request( + "/public/v1/query/list_policies", + { + ...input, + organizationId: + input.organizationId ?? + session?.organizationId ?? + this.config.organizationId, + }, + stampWith, + ); + }; + + stampGetPolicies = async ( + input: SdkTypes.TGetPoliciesBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, ...parameters } = input; + + const fullUrl = this.config.apiBaseUrl + "/public/v1/query/list_policies"; + const bodyWithType = { + parameters, + organizationId, + type: "ACTIVITY_TYPE_GET_POLICIES", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + listPrivateKeyTags = async ( + input: SdkTypes.TListPrivateKeyTagsBody, + stampWith?: StamperType, + ): Promise => { + const session = await this.storageManager?.getActiveSession(); + return this.request( + "/public/v1/query/list_private_key_tags", + { + ...input, + organizationId: + input.organizationId ?? + session?.organizationId ?? + this.config.organizationId, + }, + stampWith, + ); + }; + + stampListPrivateKeyTags = async ( + input: SdkTypes.TListPrivateKeyTagsBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/query/list_private_key_tags"; + const bodyWithType = { + parameters, + organizationId, + type: "ACTIVITY_TYPE_LIST_PRIVATE_KEY_TAGS", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + getPrivateKeys = async ( + input: SdkTypes.TGetPrivateKeysBody = {}, + stampWith?: StamperType, + ): Promise => { + const session = await this.storageManager?.getActiveSession(); + return this.request( + "/public/v1/query/list_private_keys", + { + ...input, + organizationId: + input.organizationId ?? + session?.organizationId ?? + this.config.organizationId, + }, + stampWith, + ); + }; + + stampGetPrivateKeys = async ( + input: SdkTypes.TGetPrivateKeysBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/query/list_private_keys"; + const bodyWithType = { + parameters, + organizationId, + type: "ACTIVITY_TYPE_GET_PRIVATE_KEYS", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + getSmartContractInterfaces = async ( + input: SdkTypes.TGetSmartContractInterfacesBody, + stampWith?: StamperType, + ): Promise => { + const session = await this.storageManager?.getActiveSession(); + return this.request( + "/public/v1/query/list_smart_contract_interfaces", + { + ...input, + organizationId: + input.organizationId ?? + session?.organizationId ?? + this.config.organizationId, + }, + stampWith, + ); + }; + + stampGetSmartContractInterfaces = async ( + input: SdkTypes.TGetSmartContractInterfacesBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + + "/public/v1/query/list_smart_contract_interfaces"; + const bodyWithType = { + parameters, + organizationId, + type: "ACTIVITY_TYPE_GET_SMART_CONTRACT_INTERFACES", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + getSubOrgIds = async ( + input: SdkTypes.TGetSubOrgIdsBody = {}, + stampWith?: StamperType, + ): Promise => { + const session = await this.storageManager?.getActiveSession(); + return this.request( + "/public/v1/query/list_suborgs", + { + ...input, + organizationId: + input.organizationId ?? + session?.organizationId ?? + this.config.organizationId, + }, + stampWith, + ); + }; + + stampGetSubOrgIds = async ( + input: SdkTypes.TGetSubOrgIdsBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, ...parameters } = input; + + const fullUrl = this.config.apiBaseUrl + "/public/v1/query/list_suborgs"; + const bodyWithType = { + parameters, + organizationId, + type: "ACTIVITY_TYPE_GET_SUB_ORG_IDS", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + listUserTags = async ( + input: SdkTypes.TListUserTagsBody = {}, + stampWith?: StamperType, + ): Promise => { + const session = await this.storageManager?.getActiveSession(); + return this.request( + "/public/v1/query/list_user_tags", + { + ...input, + organizationId: + input.organizationId ?? + session?.organizationId ?? + this.config.organizationId, + }, + stampWith, + ); + }; + + stampListUserTags = async ( + input: SdkTypes.TListUserTagsBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, ...parameters } = input; + + const fullUrl = this.config.apiBaseUrl + "/public/v1/query/list_user_tags"; + const bodyWithType = { + parameters, + organizationId, + type: "ACTIVITY_TYPE_LIST_USER_TAGS", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + getUsers = async ( + input: SdkTypes.TGetUsersBody = {}, + stampWith?: StamperType, + ): Promise => { + const session = await this.storageManager?.getActiveSession(); + return this.request( + "/public/v1/query/list_users", + { + ...input, + organizationId: + input.organizationId ?? + session?.organizationId ?? + this.config.organizationId, + }, + stampWith, + ); + }; + + stampGetUsers = async ( + input: SdkTypes.TGetUsersBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, ...parameters } = input; + + const fullUrl = this.config.apiBaseUrl + "/public/v1/query/list_users"; + const bodyWithType = { + parameters, + organizationId, + type: "ACTIVITY_TYPE_GET_USERS", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + getVerifiedSubOrgIds = async ( + input: SdkTypes.TGetVerifiedSubOrgIdsBody, + stampWith?: StamperType, + ): Promise => { + const session = await this.storageManager?.getActiveSession(); + return this.request( + "/public/v1/query/list_verified_suborgs", + { + ...input, + organizationId: + input.organizationId ?? + session?.organizationId ?? + this.config.organizationId, + }, + stampWith, + ); + }; + + stampGetVerifiedSubOrgIds = async ( + input: SdkTypes.TGetVerifiedSubOrgIdsBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/query/list_verified_suborgs"; + const bodyWithType = { + parameters, + organizationId, + type: "ACTIVITY_TYPE_GET_VERIFIED_SUB_ORG_IDS", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + getWalletAccounts = async ( + input: SdkTypes.TGetWalletAccountsBody, + stampWith?: StamperType, + ): Promise => { + const session = await this.storageManager?.getActiveSession(); + return this.request( + "/public/v1/query/list_wallet_accounts", + { + ...input, + organizationId: + input.organizationId ?? + session?.organizationId ?? + this.config.organizationId, + }, + stampWith, + ); + }; + + stampGetWalletAccounts = async ( + input: SdkTypes.TGetWalletAccountsBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/query/list_wallet_accounts"; + const bodyWithType = { + parameters, + organizationId, + type: "ACTIVITY_TYPE_GET_WALLET_ACCOUNTS", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + getWallets = async ( + input: SdkTypes.TGetWalletsBody = {}, + stampWith?: StamperType, + ): Promise => { + const session = await this.storageManager?.getActiveSession(); + return this.request( + "/public/v1/query/list_wallets", + { + ...input, + organizationId: + input.organizationId ?? + session?.organizationId ?? + this.config.organizationId, + }, + stampWith, + ); + }; + + stampGetWallets = async ( + input: SdkTypes.TGetWalletsBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, ...parameters } = input; + + const fullUrl = this.config.apiBaseUrl + "/public/v1/query/list_wallets"; + const bodyWithType = { + parameters, + organizationId, + type: "ACTIVITY_TYPE_GET_WALLETS", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + getWhoami = async ( + input: SdkTypes.TGetWhoamiBody = {}, + stampWith?: StamperType, + ): Promise => { + const session = await this.storageManager?.getActiveSession(); + return this.request( + "/public/v1/query/whoami", + { + ...input, + organizationId: + input.organizationId ?? + session?.organizationId ?? + this.config.organizationId, + }, + stampWith, + ); + }; + + stampGetWhoami = async ( + input: SdkTypes.TGetWhoamiBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, ...parameters } = input; + + const fullUrl = this.config.apiBaseUrl + "/public/v1/query/whoami"; + const bodyWithType = { + parameters, + organizationId, + type: "ACTIVITY_TYPE_GET_WHOAMI", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + approveActivity = async ( + input: SdkTypes.TApproveActivityBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + return this.activityDecision( + "/public/v1/submit/approve_activity", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_APPROVE_ACTIVITY", + }, + stampWith, + ); + }; + + stampApproveActivity = async ( + input: SdkTypes.TApproveActivityBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/approve_activity"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_APPROVE_ACTIVITY", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + createApiKeys = async ( + input: SdkTypes.TCreateApiKeysBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/create_api_keys", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_CREATE_API_KEYS_V2", + }, + "createApiKeysResult", + stampWith, + ); + }; + + stampCreateApiKeys = async ( + input: SdkTypes.TCreateApiKeysBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/create_api_keys"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_CREATE_API_KEYS_V2", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + createApiOnlyUsers = async ( + input: SdkTypes.TCreateApiOnlyUsersBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/create_api_only_users", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_CREATE_API_ONLY_USERS", + }, + "createApiOnlyUsersResult", + stampWith, + ); + }; + + stampCreateApiOnlyUsers = async ( + input: SdkTypes.TCreateApiOnlyUsersBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/create_api_only_users"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_CREATE_API_ONLY_USERS", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + createAuthenticators = async ( + input: SdkTypes.TCreateAuthenticatorsBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/create_authenticators", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_CREATE_AUTHENTICATORS_V2", + }, + "createAuthenticatorsResult", + stampWith, + ); + }; + + stampCreateAuthenticators = async ( + input: SdkTypes.TCreateAuthenticatorsBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/create_authenticators"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_CREATE_AUTHENTICATORS_V2", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + createInvitations = async ( + input: SdkTypes.TCreateInvitationsBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/create_invitations", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_CREATE_INVITATIONS", + }, + "createInvitationsResult", + stampWith, + ); + }; + + stampCreateInvitations = async ( + input: SdkTypes.TCreateInvitationsBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/create_invitations"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_CREATE_INVITATIONS", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + createOauthProviders = async ( + input: SdkTypes.TCreateOauthProvidersBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/create_oauth_providers", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_CREATE_OAUTH_PROVIDERS", + }, + "createOauthProvidersResult", + stampWith, + ); + }; + + stampCreateOauthProviders = async ( + input: SdkTypes.TCreateOauthProvidersBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/create_oauth_providers"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_CREATE_OAUTH_PROVIDERS", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + createPolicies = async ( + input: SdkTypes.TCreatePoliciesBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/create_policies", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_CREATE_POLICIES", + }, + "createPoliciesResult", + stampWith, + ); + }; + + stampCreatePolicies = async ( + input: SdkTypes.TCreatePoliciesBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/create_policies"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_CREATE_POLICIES", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + createPolicy = async ( + input: SdkTypes.TCreatePolicyBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/create_policy", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_CREATE_POLICY_V3", + }, + "createPolicyResult", + stampWith, + ); + }; + + stampCreatePolicy = async ( + input: SdkTypes.TCreatePolicyBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = this.config.apiBaseUrl + "/public/v1/submit/create_policy"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_CREATE_POLICY_V3", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + createPrivateKeyTag = async ( + input: SdkTypes.TCreatePrivateKeyTagBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/create_private_key_tag", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_CREATE_PRIVATE_KEY_TAG", + }, + "createPrivateKeyTagResult", + stampWith, + ); + }; + + stampCreatePrivateKeyTag = async ( + input: SdkTypes.TCreatePrivateKeyTagBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/create_private_key_tag"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_CREATE_PRIVATE_KEY_TAG", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + createPrivateKeys = async ( + input: SdkTypes.TCreatePrivateKeysBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/create_private_keys", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_CREATE_PRIVATE_KEYS_V2", + }, + "createPrivateKeysResultV2", + stampWith, + ); + }; + + stampCreatePrivateKeys = async ( + input: SdkTypes.TCreatePrivateKeysBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/create_private_keys"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_CREATE_PRIVATE_KEYS_V2", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + createReadOnlySession = async ( + input: SdkTypes.TCreateReadOnlySessionBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/create_read_only_session", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_CREATE_READ_ONLY_SESSION", + }, + "createReadOnlySessionResult", + stampWith, + ); + }; + + stampCreateReadOnlySession = async ( + input: SdkTypes.TCreateReadOnlySessionBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/create_read_only_session"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_CREATE_READ_ONLY_SESSION", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + createReadWriteSession = async ( + input: SdkTypes.TCreateReadWriteSessionBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/create_read_write_session", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_CREATE_READ_WRITE_SESSION_V2", + }, + "createReadWriteSessionResultV2", + stampWith, + ); + }; + + stampCreateReadWriteSession = async ( + input: SdkTypes.TCreateReadWriteSessionBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/create_read_write_session"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_CREATE_READ_WRITE_SESSION_V2", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + createSmartContractInterface = async ( + input: SdkTypes.TCreateSmartContractInterfaceBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/create_smart_contract_interface", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_CREATE_SMART_CONTRACT_INTERFACE", + }, + "createSmartContractInterfaceResult", + stampWith, + ); + }; + + stampCreateSmartContractInterface = async ( + input: SdkTypes.TCreateSmartContractInterfaceBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + + "/public/v1/submit/create_smart_contract_interface"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_CREATE_SMART_CONTRACT_INTERFACE", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + createSubOrganization = async ( + input: SdkTypes.TCreateSubOrganizationBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/create_sub_organization", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_CREATE_SUB_ORGANIZATION_V7", + }, + "createSubOrganizationResultV7", + stampWith, + ); + }; + + stampCreateSubOrganization = async ( + input: SdkTypes.TCreateSubOrganizationBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/create_sub_organization"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_CREATE_SUB_ORGANIZATION_V7", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + createUserTag = async ( + input: SdkTypes.TCreateUserTagBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/create_user_tag", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_CREATE_USER_TAG", + }, + "createUserTagResult", + stampWith, + ); + }; + + stampCreateUserTag = async ( + input: SdkTypes.TCreateUserTagBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/create_user_tag"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_CREATE_USER_TAG", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + createUsers = async ( + input: SdkTypes.TCreateUsersBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/create_users", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_CREATE_USERS_V3", + }, + "createUsersResult", + stampWith, + ); + }; + + stampCreateUsers = async ( + input: SdkTypes.TCreateUsersBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = this.config.apiBaseUrl + "/public/v1/submit/create_users"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_CREATE_USERS_V3", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + createWallet = async ( + input: SdkTypes.TCreateWalletBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/create_wallet", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_CREATE_WALLET", + }, + "createWalletResult", + stampWith, + ); + }; + + stampCreateWallet = async ( + input: SdkTypes.TCreateWalletBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = this.config.apiBaseUrl + "/public/v1/submit/create_wallet"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_CREATE_WALLET", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + createWalletAccounts = async ( + input: SdkTypes.TCreateWalletAccountsBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/create_wallet_accounts", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_CREATE_WALLET_ACCOUNTS", + }, + "createWalletAccountsResult", + stampWith, + ); + }; + + stampCreateWalletAccounts = async ( + input: SdkTypes.TCreateWalletAccountsBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/create_wallet_accounts"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_CREATE_WALLET_ACCOUNTS", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + deleteApiKeys = async ( + input: SdkTypes.TDeleteApiKeysBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/delete_api_keys", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_DELETE_API_KEYS", + }, + "deleteApiKeysResult", + stampWith, + ); + }; + + stampDeleteApiKeys = async ( + input: SdkTypes.TDeleteApiKeysBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/delete_api_keys"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_DELETE_API_KEYS", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + deleteAuthenticators = async ( + input: SdkTypes.TDeleteAuthenticatorsBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/delete_authenticators", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_DELETE_AUTHENTICATORS", + }, + "deleteAuthenticatorsResult", + stampWith, + ); + }; + + stampDeleteAuthenticators = async ( + input: SdkTypes.TDeleteAuthenticatorsBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/delete_authenticators"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_DELETE_AUTHENTICATORS", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + deleteInvitation = async ( + input: SdkTypes.TDeleteInvitationBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/delete_invitation", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_DELETE_INVITATION", + }, + "deleteInvitationResult", + stampWith, + ); + }; + + stampDeleteInvitation = async ( + input: SdkTypes.TDeleteInvitationBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/delete_invitation"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_DELETE_INVITATION", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + deleteOauthProviders = async ( + input: SdkTypes.TDeleteOauthProvidersBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/delete_oauth_providers", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_DELETE_OAUTH_PROVIDERS", + }, + "deleteOauthProvidersResult", + stampWith, + ); + }; + + stampDeleteOauthProviders = async ( + input: SdkTypes.TDeleteOauthProvidersBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/delete_oauth_providers"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_DELETE_OAUTH_PROVIDERS", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + deletePolicy = async ( + input: SdkTypes.TDeletePolicyBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/delete_policy", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_DELETE_POLICY", + }, + "deletePolicyResult", + stampWith, + ); + }; + + stampDeletePolicy = async ( + input: SdkTypes.TDeletePolicyBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = this.config.apiBaseUrl + "/public/v1/submit/delete_policy"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_DELETE_POLICY", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + deletePrivateKeyTags = async ( + input: SdkTypes.TDeletePrivateKeyTagsBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/delete_private_key_tags", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_DELETE_PRIVATE_KEY_TAGS", + }, + "deletePrivateKeyTagsResult", + stampWith, + ); + }; + + stampDeletePrivateKeyTags = async ( + input: SdkTypes.TDeletePrivateKeyTagsBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/delete_private_key_tags"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_DELETE_PRIVATE_KEY_TAGS", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + deletePrivateKeys = async ( + input: SdkTypes.TDeletePrivateKeysBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/delete_private_keys", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_DELETE_PRIVATE_KEYS", + }, + "deletePrivateKeysResult", + stampWith, + ); + }; + + stampDeletePrivateKeys = async ( + input: SdkTypes.TDeletePrivateKeysBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/delete_private_keys"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_DELETE_PRIVATE_KEYS", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + deleteSmartContractInterface = async ( + input: SdkTypes.TDeleteSmartContractInterfaceBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/delete_smart_contract_interface", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_DELETE_SMART_CONTRACT_INTERFACE", + }, + "deleteSmartContractInterfaceResult", + stampWith, + ); + }; + + stampDeleteSmartContractInterface = async ( + input: SdkTypes.TDeleteSmartContractInterfaceBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + + "/public/v1/submit/delete_smart_contract_interface"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_DELETE_SMART_CONTRACT_INTERFACE", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + deleteSubOrganization = async ( + input: SdkTypes.TDeleteSubOrganizationBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/delete_sub_organization", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_DELETE_SUB_ORGANIZATION", + }, + "deleteSubOrganizationResult", + stampWith, + ); + }; + + stampDeleteSubOrganization = async ( + input: SdkTypes.TDeleteSubOrganizationBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/delete_sub_organization"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_DELETE_SUB_ORGANIZATION", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + deleteUserTags = async ( + input: SdkTypes.TDeleteUserTagsBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/delete_user_tags", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_DELETE_USER_TAGS", + }, + "deleteUserTagsResult", + stampWith, + ); + }; + + stampDeleteUserTags = async ( + input: SdkTypes.TDeleteUserTagsBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/delete_user_tags"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_DELETE_USER_TAGS", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + deleteUsers = async ( + input: SdkTypes.TDeleteUsersBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/delete_users", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_DELETE_USERS", + }, + "deleteUsersResult", + stampWith, + ); + }; + + stampDeleteUsers = async ( + input: SdkTypes.TDeleteUsersBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = this.config.apiBaseUrl + "/public/v1/submit/delete_users"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_DELETE_USERS", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + deleteWallets = async ( + input: SdkTypes.TDeleteWalletsBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/delete_wallets", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_DELETE_WALLETS", + }, + "deleteWalletsResult", + stampWith, + ); + }; + + stampDeleteWallets = async ( + input: SdkTypes.TDeleteWalletsBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = this.config.apiBaseUrl + "/public/v1/submit/delete_wallets"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_DELETE_WALLETS", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + emailAuth = async ( + input: SdkTypes.TEmailAuthBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/email_auth", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_EMAIL_AUTH_V2", + }, + "emailAuthResult", + stampWith, + ); + }; + + stampEmailAuth = async ( + input: SdkTypes.TEmailAuthBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = this.config.apiBaseUrl + "/public/v1/submit/email_auth"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_EMAIL_AUTH_V2", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + exportPrivateKey = async ( + input: SdkTypes.TExportPrivateKeyBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/export_private_key", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_EXPORT_PRIVATE_KEY", + }, + "exportPrivateKeyResult", + stampWith, + ); + }; + + stampExportPrivateKey = async ( + input: SdkTypes.TExportPrivateKeyBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/export_private_key"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_EXPORT_PRIVATE_KEY", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + exportWallet = async ( + input: SdkTypes.TExportWalletBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/export_wallet", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_EXPORT_WALLET", + }, + "exportWalletResult", + stampWith, + ); + }; + + stampExportWallet = async ( + input: SdkTypes.TExportWalletBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = this.config.apiBaseUrl + "/public/v1/submit/export_wallet"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_EXPORT_WALLET", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + exportWalletAccount = async ( + input: SdkTypes.TExportWalletAccountBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/export_wallet_account", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_EXPORT_WALLET_ACCOUNT", + }, + "exportWalletAccountResult", + stampWith, + ); + }; + + stampExportWalletAccount = async ( + input: SdkTypes.TExportWalletAccountBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/export_wallet_account"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_EXPORT_WALLET_ACCOUNT", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + importPrivateKey = async ( + input: SdkTypes.TImportPrivateKeyBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/import_private_key", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_IMPORT_PRIVATE_KEY", + }, + "importPrivateKeyResult", + stampWith, + ); + }; + + stampImportPrivateKey = async ( + input: SdkTypes.TImportPrivateKeyBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/import_private_key"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_IMPORT_PRIVATE_KEY", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + importWallet = async ( + input: SdkTypes.TImportWalletBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/import_wallet", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_IMPORT_WALLET", + }, + "importWalletResult", + stampWith, + ); + }; + + stampImportWallet = async ( + input: SdkTypes.TImportWalletBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = this.config.apiBaseUrl + "/public/v1/submit/import_wallet"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_IMPORT_WALLET", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + initFiatOnRamp = async ( + input: SdkTypes.TInitFiatOnRampBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/init_fiat_on_ramp", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_INIT_FIAT_ON_RAMP", + }, + "initFiatOnRampResult", + stampWith, + ); + }; + + stampInitFiatOnRamp = async ( + input: SdkTypes.TInitFiatOnRampBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/init_fiat_on_ramp"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_INIT_FIAT_ON_RAMP", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + initImportPrivateKey = async ( + input: SdkTypes.TInitImportPrivateKeyBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/init_import_private_key", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_INIT_IMPORT_PRIVATE_KEY", + }, + "initImportPrivateKeyResult", + stampWith, + ); + }; + + stampInitImportPrivateKey = async ( + input: SdkTypes.TInitImportPrivateKeyBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/init_import_private_key"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_INIT_IMPORT_PRIVATE_KEY", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + initImportWallet = async ( + input: SdkTypes.TInitImportWalletBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/init_import_wallet", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_INIT_IMPORT_WALLET", + }, + "initImportWalletResult", + stampWith, + ); + }; + + stampInitImportWallet = async ( + input: SdkTypes.TInitImportWalletBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/init_import_wallet"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_INIT_IMPORT_WALLET", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + initOtp = async ( + input: SdkTypes.TInitOtpBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/init_otp", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_INIT_OTP", + }, + "initOtpResult", + stampWith, + ); + }; + + stampInitOtp = async ( + input: SdkTypes.TInitOtpBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = this.config.apiBaseUrl + "/public/v1/submit/init_otp"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_INIT_OTP", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + initOtpAuth = async ( + input: SdkTypes.TInitOtpAuthBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/init_otp_auth", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_INIT_OTP_AUTH_V2", + }, + "initOtpAuthResultV2", + stampWith, + ); + }; + + stampInitOtpAuth = async ( + input: SdkTypes.TInitOtpAuthBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = this.config.apiBaseUrl + "/public/v1/submit/init_otp_auth"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_INIT_OTP_AUTH_V2", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + initUserEmailRecovery = async ( + input: SdkTypes.TInitUserEmailRecoveryBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/init_user_email_recovery", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_INIT_USER_EMAIL_RECOVERY", + }, + "initUserEmailRecoveryResult", + stampWith, + ); + }; + + stampInitUserEmailRecovery = async ( + input: SdkTypes.TInitUserEmailRecoveryBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/init_user_email_recovery"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_INIT_USER_EMAIL_RECOVERY", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + oauth = async ( + input: SdkTypes.TOauthBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/oauth", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_OAUTH", + }, + "oauthResult", + stampWith, + ); + }; + + stampOauth = async ( + input: SdkTypes.TOauthBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = this.config.apiBaseUrl + "/public/v1/submit/oauth"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_OAUTH", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + oauthLogin = async ( + input: SdkTypes.TOauthLoginBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/oauth_login", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_OAUTH_LOGIN", + }, + "oauthLoginResult", + stampWith, + ); + }; + + stampOauthLogin = async ( + input: SdkTypes.TOauthLoginBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = this.config.apiBaseUrl + "/public/v1/submit/oauth_login"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_OAUTH_LOGIN", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + otpAuth = async ( + input: SdkTypes.TOtpAuthBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/otp_auth", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_OTP_AUTH", + }, + "otpAuthResult", + stampWith, + ); + }; + + stampOtpAuth = async ( + input: SdkTypes.TOtpAuthBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = this.config.apiBaseUrl + "/public/v1/submit/otp_auth"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_OTP_AUTH", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + otpLogin = async ( + input: SdkTypes.TOtpLoginBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/otp_login", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_OTP_LOGIN", + }, + "otpLoginResult", + stampWith, + ); + }; + + stampOtpLogin = async ( + input: SdkTypes.TOtpLoginBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = this.config.apiBaseUrl + "/public/v1/submit/otp_login"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_OTP_LOGIN", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + recoverUser = async ( + input: SdkTypes.TRecoverUserBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/recover_user", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_RECOVER_USER", + }, + "recoverUserResult", + stampWith, + ); + }; + + stampRecoverUser = async ( + input: SdkTypes.TRecoverUserBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = this.config.apiBaseUrl + "/public/v1/submit/recover_user"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_RECOVER_USER", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + rejectActivity = async ( + input: SdkTypes.TRejectActivityBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + return this.activityDecision( + "/public/v1/submit/reject_activity", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_REJECT_ACTIVITY", + }, + stampWith, + ); + }; + + stampRejectActivity = async ( + input: SdkTypes.TRejectActivityBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/reject_activity"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_REJECT_ACTIVITY", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + removeOrganizationFeature = async ( + input: SdkTypes.TRemoveOrganizationFeatureBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/remove_organization_feature", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_REMOVE_ORGANIZATION_FEATURE", + }, + "removeOrganizationFeatureResult", + stampWith, + ); + }; + + stampRemoveOrganizationFeature = async ( + input: SdkTypes.TRemoveOrganizationFeatureBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/remove_organization_feature"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_REMOVE_ORGANIZATION_FEATURE", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + setOrganizationFeature = async ( + input: SdkTypes.TSetOrganizationFeatureBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/set_organization_feature", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_SET_ORGANIZATION_FEATURE", + }, + "setOrganizationFeatureResult", + stampWith, + ); + }; + + stampSetOrganizationFeature = async ( + input: SdkTypes.TSetOrganizationFeatureBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/set_organization_feature"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_SET_ORGANIZATION_FEATURE", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + signRawPayload = async ( + input: SdkTypes.TSignRawPayloadBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/sign_raw_payload", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_SIGN_RAW_PAYLOAD_V2", + }, + "signRawPayloadResult", + stampWith, + ); + }; + + stampSignRawPayload = async ( + input: SdkTypes.TSignRawPayloadBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/sign_raw_payload"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_SIGN_RAW_PAYLOAD_V2", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + signRawPayloads = async ( + input: SdkTypes.TSignRawPayloadsBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/sign_raw_payloads", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_SIGN_RAW_PAYLOADS", + }, + "signRawPayloadsResult", + stampWith, + ); + }; + + stampSignRawPayloads = async ( + input: SdkTypes.TSignRawPayloadsBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/sign_raw_payloads"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_SIGN_RAW_PAYLOADS", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + signTransaction = async ( + input: SdkTypes.TSignTransactionBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/sign_transaction", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_SIGN_TRANSACTION_V2", + }, + "signTransactionResult", + stampWith, + ); + }; + + stampSignTransaction = async ( + input: SdkTypes.TSignTransactionBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/sign_transaction"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_SIGN_TRANSACTION_V2", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + stampLogin = async ( + input: SdkTypes.TStampLoginBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/stamp_login", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_STAMP_LOGIN", + }, + "stampLoginResult", + stampWith, + ); + }; + + stampStampLogin = async ( + input: SdkTypes.TStampLoginBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = this.config.apiBaseUrl + "/public/v1/submit/stamp_login"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_STAMP_LOGIN", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + updatePolicy = async ( + input: SdkTypes.TUpdatePolicyBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/update_policy", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_UPDATE_POLICY_V2", + }, + "updatePolicyResultV2", + stampWith, + ); + }; + + stampUpdatePolicy = async ( + input: SdkTypes.TUpdatePolicyBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = this.config.apiBaseUrl + "/public/v1/submit/update_policy"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_UPDATE_POLICY_V2", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + updatePrivateKeyTag = async ( + input: SdkTypes.TUpdatePrivateKeyTagBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/update_private_key_tag", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_UPDATE_PRIVATE_KEY_TAG", + }, + "updatePrivateKeyTagResult", + stampWith, + ); + }; + + stampUpdatePrivateKeyTag = async ( + input: SdkTypes.TUpdatePrivateKeyTagBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/update_private_key_tag"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_UPDATE_PRIVATE_KEY_TAG", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + updateRootQuorum = async ( + input: SdkTypes.TUpdateRootQuorumBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/update_root_quorum", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_UPDATE_ROOT_QUORUM", + }, + "updateRootQuorumResult", + stampWith, + ); + }; + + stampUpdateRootQuorum = async ( + input: SdkTypes.TUpdateRootQuorumBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/update_root_quorum"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_UPDATE_ROOT_QUORUM", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + updateUser = async ( + input: SdkTypes.TUpdateUserBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/update_user", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_UPDATE_USER", + }, + "updateUserResult", + stampWith, + ); + }; + + stampUpdateUser = async ( + input: SdkTypes.TUpdateUserBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = this.config.apiBaseUrl + "/public/v1/submit/update_user"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_UPDATE_USER", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + updateUserEmail = async ( + input: SdkTypes.TUpdateUserEmailBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/update_user_email", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_UPDATE_USER_EMAIL", + }, + "updateUserEmailResult", + stampWith, + ); + }; + + stampUpdateUserEmail = async ( + input: SdkTypes.TUpdateUserEmailBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/update_user_email"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_UPDATE_USER_EMAIL", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + updateUserName = async ( + input: SdkTypes.TUpdateUserNameBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/update_user_name", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_UPDATE_USER_NAME", + }, + "updateUserNameResult", + stampWith, + ); + }; + + stampUpdateUserName = async ( + input: SdkTypes.TUpdateUserNameBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/update_user_name"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_UPDATE_USER_NAME", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + updateUserPhoneNumber = async ( + input: SdkTypes.TUpdateUserPhoneNumberBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/update_user_phone_number", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_UPDATE_USER_PHONE_NUMBER", + }, + "updateUserPhoneNumberResult", + stampWith, + ); + }; + + stampUpdateUserPhoneNumber = async ( + input: SdkTypes.TUpdateUserPhoneNumberBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/update_user_phone_number"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_UPDATE_USER_PHONE_NUMBER", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + updateUserTag = async ( + input: SdkTypes.TUpdateUserTagBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/update_user_tag", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_UPDATE_USER_TAG", + }, + "updateUserTagResult", + stampWith, + ); + }; + + stampUpdateUserTag = async ( + input: SdkTypes.TUpdateUserTagBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = + this.config.apiBaseUrl + "/public/v1/submit/update_user_tag"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_UPDATE_USER_TAG", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + updateWallet = async ( + input: SdkTypes.TUpdateWalletBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/update_wallet", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_UPDATE_WALLET", + }, + "updateWalletResult", + stampWith, + ); + }; + + stampUpdateWallet = async ( + input: SdkTypes.TUpdateWalletBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = this.config.apiBaseUrl + "/public/v1/submit/update_wallet"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_UPDATE_WALLET", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + verifyOtp = async ( + input: SdkTypes.TVerifyOtpBody, + stampWith?: StamperType, + ): Promise => { + const { organizationId, timestampMs, ...rest } = input; + const session = await this.storageManager?.getActiveSession(); + + return this.activity( + "/public/v1/submit/verify_otp", + { + parameters: rest, + organizationId: + organizationId ?? + session?.organizationId ?? + this.config.organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_VERIFY_OTP", + }, + "verifyOtpResult", + stampWith, + ); + }; + + stampVerifyOtp = async ( + input: SdkTypes.TVerifyOtpBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, timestampMs, ...parameters } = input; + + const fullUrl = this.config.apiBaseUrl + "/public/v1/submit/verify_otp"; + const bodyWithType = { + parameters, + organizationId, + timestampMs: timestampMs ?? String(Date.now()), + type: "ACTIVITY_TYPE_VERIFY_OTP", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + testRateLimits = async ( + input: SdkTypes.TTestRateLimitsBody, + stampWith?: StamperType, + ): Promise => { + const session = await this.storageManager?.getActiveSession(); + return this.request( + "/tkhq/api/v1/test_rate_limits", + { + ...input, + organizationId: + input.organizationId ?? + session?.organizationId ?? + this.config.organizationId, + }, + stampWith, + ); + }; + + stampTestRateLimits = async ( + input: SdkTypes.TTestRateLimitsBody, + stampWith?: StamperType, + ): Promise => { + const activeStamper = this.getStamper(stampWith); + if (!activeStamper) { + return undefined; + } + + const { organizationId, ...parameters } = input; + + const fullUrl = this.config.apiBaseUrl + "/tkhq/api/v1/test_rate_limits"; + const bodyWithType = { + parameters, + organizationId, + type: "ACTIVITY_TYPE_TEST_RATE_LIMITS", + }; + + const stringifiedBody = JSON.stringify(bodyWithType); + const stamp = await activeStamper.stamp(stringifiedBody); + return { + body: stringifiedBody, + stamp: stamp, + url: fullUrl, + }; + }; + + proxyGetAccount = async ( + input: SdkTypes.ProxyTGetAccountBody, + ): Promise => { + return this.authProxyRequest("/v1/account", input); + }; + + proxyOAuthLogin = async ( + input: SdkTypes.ProxyTOAuthLoginBody, + ): Promise => { + return this.authProxyRequest("/v1/oauth_login", input); + }; + + proxyInitOtp = async ( + input: SdkTypes.ProxyTInitOtpBody, + ): Promise => { + return this.authProxyRequest("/v1/otp_init", input); + }; + + proxyOtpLogin = async ( + input: SdkTypes.ProxyTOtpLoginBody, + ): Promise => { + return this.authProxyRequest("/v1/otp_login", input); + }; + + proxyVerifyOtp = async ( + input: SdkTypes.ProxyTVerifyOtpBody, + ): Promise => { + return this.authProxyRequest("/v1/otp_verify", input); + }; + + proxySignup = async ( + input: SdkTypes.ProxyTSignupBody, + ): Promise => { + return this.authProxyRequest("/v1/signup", input); + }; + + proxyGetWalletKitConfig = async ( + input: SdkTypes.ProxyTGetWalletKitConfigBody, + ): Promise => { + return this.authProxyRequest("/v1/wallet_kit_config", input); + }; +} diff --git a/packages/core/src/__generated__/version.ts b/packages/core/src/__generated__/version.ts new file mode 100644 index 000000000..16e3dc6d5 --- /dev/null +++ b/packages/core/src/__generated__/version.ts @@ -0,0 +1 @@ +export const VERSION = "@turnkey/core@1.0.0-beta.4"; diff --git a/packages/core/src/__inputs__/auth_proxy.swagger.json b/packages/core/src/__inputs__/auth_proxy.swagger.json new file mode 100644 index 000000000..22e6e4799 --- /dev/null +++ b/packages/core/src/__inputs__/auth_proxy.swagger.json @@ -0,0 +1,708 @@ +{ + "swagger": "2.0", + "info": { + "title": "services/auth_proxy/v1/proxy_api.proto", + "version": "version not set" + }, + "tags": [ + { + "name": "AuthProxyService" + } + ], + "consumes": ["application/json"], + "produces": ["application/json"], + "paths": { + "/v1/account": { + "post": { + "summary": "Get Account", + "description": "Return sub-organization ID associated with a given contact or public identifier.", + "operationId": "AuthProxyService_GetAccount", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1GetAccountResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1GetAccountRequest" + } + } + ], + "tags": ["Users"] + } + }, + "/v1/oauth_login": { + "post": { + "summary": "OAuth Login", + "description": "Login using an OIDC token and public key.", + "operationId": "AuthProxyService_OAuthLogin", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1OAuthLoginResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1OAuthLoginRequest" + } + } + ], + "tags": ["Sessions"] + } + }, + "/v1/otp_init": { + "post": { + "summary": "Init OTP", + "description": "Initialize an OTP (email or SMS) for a user.", + "operationId": "AuthProxyService_InitOtp", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1InitOtpResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1InitOtpRequest" + } + } + ], + "tags": ["Auth"] + } + }, + "/v1/otp_login": { + "post": { + "summary": "OTP Login", + "description": "Login using a verified OTP token and public key.", + "operationId": "AuthProxyService_OtpLogin", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1OtpLoginResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1OtpLoginRequest" + } + } + ], + "tags": ["Sessions"] + } + }, + "/v1/otp_verify": { + "post": { + "summary": "Verify OTP", + "description": "Verify the OTP code previously sent to the user's contact.", + "operationId": "AuthProxyService_VerifyOtp", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1VerifyOtpResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1VerifyOtpRequest" + } + } + ], + "tags": ["Auth"] + } + }, + "/v1/signup": { + "post": { + "summary": "Signup", + "description": "Create a new sub-organization and user via the proxy API.", + "operationId": "AuthProxyService_Signup", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1SignupResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1SignupRequest" + } + } + ], + "tags": ["Auth"] + } + }, + "/v1/wallet_kit_config": { + "post": { + "summary": "Get WalletKit Config", + "description": "Get wallet kit settings and feature toggles for the calling organization.", + "operationId": "AuthProxyService_GetWalletKitConfig", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1GetWalletKitConfigResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1GetWalletKitConfigRequest" + } + } + ], + "tags": ["Organizations"] + } + } + }, + "definitions": { + "protobufAny": { + "type": "object", + "properties": { + "@type": { + "type": "string" + } + }, + "additionalProperties": {} + }, + "rpcStatus": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + }, + "details": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/protobufAny" + } + } + } + }, + "v1AddressFormat": { + "type": "string", + "enum": [ + "ADDRESS_FORMAT_UNCOMPRESSED", + "ADDRESS_FORMAT_COMPRESSED", + "ADDRESS_FORMAT_ETHEREUM", + "ADDRESS_FORMAT_SOLANA", + "ADDRESS_FORMAT_COSMOS", + "ADDRESS_FORMAT_TRON", + "ADDRESS_FORMAT_SUI", + "ADDRESS_FORMAT_APTOS", + "ADDRESS_FORMAT_BITCOIN_MAINNET_P2PKH", + "ADDRESS_FORMAT_BITCOIN_MAINNET_P2SH", + "ADDRESS_FORMAT_BITCOIN_MAINNET_P2WPKH", + "ADDRESS_FORMAT_BITCOIN_MAINNET_P2WSH", + "ADDRESS_FORMAT_BITCOIN_MAINNET_P2TR", + "ADDRESS_FORMAT_BITCOIN_TESTNET_P2PKH", + "ADDRESS_FORMAT_BITCOIN_TESTNET_P2SH", + "ADDRESS_FORMAT_BITCOIN_TESTNET_P2WPKH", + "ADDRESS_FORMAT_BITCOIN_TESTNET_P2WSH", + "ADDRESS_FORMAT_BITCOIN_TESTNET_P2TR", + "ADDRESS_FORMAT_BITCOIN_SIGNET_P2PKH", + "ADDRESS_FORMAT_BITCOIN_SIGNET_P2SH", + "ADDRESS_FORMAT_BITCOIN_SIGNET_P2WPKH", + "ADDRESS_FORMAT_BITCOIN_SIGNET_P2WSH", + "ADDRESS_FORMAT_BITCOIN_SIGNET_P2TR", + "ADDRESS_FORMAT_BITCOIN_REGTEST_P2PKH", + "ADDRESS_FORMAT_BITCOIN_REGTEST_P2SH", + "ADDRESS_FORMAT_BITCOIN_REGTEST_P2WPKH", + "ADDRESS_FORMAT_BITCOIN_REGTEST_P2WSH", + "ADDRESS_FORMAT_BITCOIN_REGTEST_P2TR", + "ADDRESS_FORMAT_SEI", + "ADDRESS_FORMAT_XLM", + "ADDRESS_FORMAT_DOGE_MAINNET", + "ADDRESS_FORMAT_DOGE_TESTNET", + "ADDRESS_FORMAT_TON_V3R2", + "ADDRESS_FORMAT_TON_V4R2", + "ADDRESS_FORMAT_TON_V5R1", + "ADDRESS_FORMAT_XRP" + ] + }, + "v1ApiKeyCurve": { + "type": "string", + "enum": [ + "API_KEY_CURVE_P256", + "API_KEY_CURVE_SECP256K1", + "API_KEY_CURVE_ED25519" + ] + }, + "v1ApiKeyParamsV2": { + "type": "object", + "properties": { + "apiKeyName": { + "type": "string", + "description": "Human-readable name for an API Key." + }, + "publicKey": { + "type": "string", + "description": "The public component of a cryptographic key pair used to sign messages and transactions." + }, + "curveType": { + "$ref": "#/definitions/v1ApiKeyCurve", + "description": "The curve type to be used for processing API key signatures." + }, + "expirationSeconds": { + "type": "string", + "description": "Optional window (in seconds) indicating how long the API Key should last." + } + }, + "required": ["apiKeyName", "publicKey", "curveType"] + }, + "v1Attestation": { + "type": "object", + "properties": { + "credentialId": { + "type": "string", + "description": "The cbor encoded then base64 url encoded id of the credential." + }, + "clientDataJson": { + "type": "string", + "description": "A base64 url encoded payload containing metadata about the signing context and the challenge." + }, + "attestationObject": { + "type": "string", + "description": "A base64 url encoded payload containing authenticator data and any attestation the webauthn provider chooses." + }, + "transports": { + "type": "array", + "items": { + "$ref": "#/definitions/v1AuthenticatorTransport" + }, + "description": "The type of authenticator transports." + } + }, + "required": [ + "credentialId", + "clientDataJson", + "attestationObject", + "transports" + ] + }, + "v1AuthenticatorParamsV2": { + "type": "object", + "properties": { + "authenticatorName": { + "type": "string", + "description": "Human-readable name for an Authenticator." + }, + "challenge": { + "type": "string", + "description": "Challenge presented for authentication purposes." + }, + "attestation": { + "$ref": "#/definitions/v1Attestation", + "description": "The attestation that proves custody of the authenticator and provides metadata about it." + } + }, + "required": ["authenticatorName", "challenge", "attestation"] + }, + "v1AuthenticatorTransport": { + "type": "string", + "enum": [ + "AUTHENTICATOR_TRANSPORT_BLE", + "AUTHENTICATOR_TRANSPORT_INTERNAL", + "AUTHENTICATOR_TRANSPORT_NFC", + "AUTHENTICATOR_TRANSPORT_USB", + "AUTHENTICATOR_TRANSPORT_HYBRID" + ] + }, + "v1Curve": { + "type": "string", + "enum": ["CURVE_SECP256K1", "CURVE_ED25519"] + }, + "v1GetAccountRequest": { + "type": "object", + "properties": { + "filterType": { + "type": "string", + "description": "Specifies the type of filter to apply, i.e 'CREDENTIAL_ID', 'NAME', 'USERNAME', 'EMAIL', 'PHONE_NUMBER', 'OIDC_TOKEN' or 'PUBLIC_KEY'" + }, + "filterValue": { + "type": "string", + "description": "The value of the filter to apply for the specified type. For example, a specific email or name string." + } + }, + "required": ["filterType", "filterValue"] + }, + "v1GetAccountResponse": { + "type": "object", + "properties": { + "organizationId": { + "type": "string" + } + }, + "required": ["organizationId"] + }, + "v1GetWalletKitConfigRequest": { + "type": "object" + }, + "v1GetWalletKitConfigResponse": { + "type": "object", + "properties": { + "facebookEnabled": { + "type": "boolean" + }, + "googleEnabled": { + "type": "boolean" + }, + "appleEnabled": { + "type": "boolean" + }, + "emailEnabled": { + "type": "boolean" + }, + "smsEnabled": { + "type": "boolean" + }, + "passkeyEnabled": { + "type": "boolean" + }, + "walletEnabled": { + "type": "boolean" + }, + "openOAuthInPage": { + "type": "boolean" + }, + "passkeySessionExpirationSeconds": { + "type": "string" + }, + "walletSessionExpirationSeconds": { + "type": "string" + }, + "organizationId": { + "type": "string" + } + }, + "required": [ + "facebookEnabled", + "googleEnabled", + "appleEnabled", + "emailEnabled", + "smsEnabled", + "passkeyEnabled", + "walletEnabled", + "openOAuthInPage", + "passkeySessionExpirationSeconds", + "walletSessionExpirationSeconds", + "organizationId" + ] + }, + "v1InitOtpRequest": { + "type": "object", + "properties": { + "otpType": { + "type": "string", + "description": "Enum to specifiy whether to send OTP via SMS or email" + }, + "contact": { + "type": "string", + "description": "Email or phone number to send the OTP code to" + } + }, + "required": ["otpType", "contact"] + }, + "v1InitOtpResponse": { + "type": "object", + "properties": { + "otpId": { + "type": "string", + "description": "Unique identifier for an OTP authentication" + } + }, + "required": ["otpId"] + }, + "v1OAuthLoginRequest": { + "type": "object", + "properties": { + "oidcToken": { + "type": "string", + "description": "Base64 encoded OIDC token" + }, + "publicKey": { + "type": "string", + "description": "Client-side public key generated by the user, which will be conditionally added to org data based on the validity of the oidc token associated with this request" + }, + "invalidateExisting": { + "type": "boolean", + "description": "Invalidate all other previously generated Login API keys" + } + }, + "required": ["oidcToken", "publicKey"] + }, + "v1OAuthLoginResponse": { + "type": "object", + "properties": { + "session": { + "type": "string", + "description": "Signed JWT containing an expiry, public key, session type, user id, and organization id" + } + }, + "required": ["session"] + }, + "v1OauthProviderParams": { + "type": "object", + "properties": { + "providerName": { + "type": "string", + "description": "Human-readable name to identify a Provider." + }, + "oidcToken": { + "type": "string", + "description": "Base64 encoded OIDC token" + } + }, + "required": ["providerName", "oidcToken"] + }, + "v1OtpLoginRequest": { + "type": "object", + "properties": { + "verificationToken": { + "type": "string", + "description": "Signed JWT containing a unique id, expiry, verification type, contact. Verification status of a user is updated when the token is consumed (in OTP_LOGIN requests)" + }, + "publicKey": { + "type": "string", + "description": "Client-side public key generated by the user, which will be conditionally added to org data based on the validity of the verification token" + }, + "invalidateExisting": { + "type": "boolean", + "description": "Invalidate all other previously generated Login API keys" + } + }, + "required": ["verificationToken", "publicKey"] + }, + "v1OtpLoginResponse": { + "type": "object", + "properties": { + "session": { + "type": "string", + "description": "Signed JWT containing an expiry, public key, session type, user id, and organization id" + } + }, + "required": ["session"] + }, + "v1PathFormat": { + "type": "string", + "enum": ["PATH_FORMAT_BIP32"] + }, + "v1SignupRequest": { + "type": "object", + "properties": { + "userEmail": { + "type": "string" + }, + "userPhoneNumber": { + "type": "string" + }, + "userTag": { + "type": "string" + }, + "userName": { + "type": "string" + }, + "subOrgName": { + "type": "string" + }, + "verificationToken": { + "type": "string" + }, + "apiKeys": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1ApiKeyParamsV2" + }, + "description": "A list of API Key parameters. This field, if not needed, should be an empty array in your request body." + }, + "authenticators": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1AuthenticatorParamsV2" + }, + "description": "A list of Authenticator parameters. This field, if not needed, should be an empty array in your request body." + }, + "oauthProviders": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1OauthProviderParams" + }, + "description": "A list of Oauth providers. This field, if not needed, should be an empty array in your request body." + }, + "wallet": { + "$ref": "#/definitions/v1WalletParams", + "description": "The wallet to create for the sub-organization" + } + }, + "required": ["apiKeys", "authenticators", "oauthProviders"] + }, + "v1SignupResponse": { + "type": "object", + "properties": { + "organizationId": { + "type": "string" + } + }, + "required": ["organizationId"] + }, + "v1VerifyOtpRequest": { + "type": "object", + "properties": { + "otpId": { + "type": "string", + "description": "ID representing the result of an init OTP activity." + }, + "otpCode": { + "type": "string", + "description": "OTP sent out to a user's contact (email or SMS)" + } + }, + "required": ["otpId", "otpCode"] + }, + "v1VerifyOtpResponse": { + "type": "object", + "properties": { + "verificationToken": { + "type": "string", + "description": "Signed JWT containing a unique id, expiry, verification type, contact. Verification status of a user is updated when the token is consumed (in OTP_LOGIN requests)" + } + }, + "required": ["verificationToken"] + }, + "v1WalletAccountParams": { + "type": "object", + "properties": { + "curve": { + "$ref": "#/definitions/v1Curve", + "description": "Cryptographic curve used to generate a wallet Account." + }, + "pathFormat": { + "$ref": "#/definitions/v1PathFormat", + "description": "Path format used to generate a wallet Account." + }, + "path": { + "type": "string", + "description": "Path used to generate a wallet Account." + }, + "addressFormat": { + "$ref": "#/definitions/v1AddressFormat", + "description": "Address format used to generate a wallet Acccount." + } + }, + "required": ["curve", "pathFormat", "path", "addressFormat"] + }, + "v1WalletParams": { + "type": "object", + "properties": { + "walletName": { + "type": "string", + "description": "Human-readable name for a Wallet." + }, + "accounts": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1WalletAccountParams" + }, + "description": "A list of wallet Accounts. This field, if not needed, should be an empty array in your request body." + }, + "mnemonicLength": { + "type": "integer", + "format": "int32", + "description": "Length of mnemonic to generate the Wallet seed. Defaults to 12. Accepted values: 12, 15, 18, 21, 24." + } + }, + "required": ["walletName", "accounts"] + } + } +} diff --git a/packages/core/src/__inputs__/public_api.swagger.json b/packages/core/src/__inputs__/public_api.swagger.json new file mode 100644 index 000000000..e75ad60c8 --- /dev/null +++ b/packages/core/src/__inputs__/public_api.swagger.json @@ -0,0 +1,10980 @@ +{ + "swagger": "2.0", + "info": { + "title": "API Reference", + "description": "Review our [API Introduction](../api-introduction) to get started.", + "version": "1.0", + "contact": {} + }, + "tags": [ + { + "name": "PublicApiService" + }, + { + "name": "Organizations", + "description": "An Organization is the highest level of hierarchy in Turnkey. It can contain many Users, Private Keys, and Policies managed by a Root Quorum. The Root Quorum consists of a set of Users with a consensus threshold. This consensus threshold must be reached by Quorum members in order for any actions to take place.\n\nSee [Root Quorum](../concepts/users/root-quorum) for more information" + }, + { + "name": "Invitations", + "description": "Invitations allow you to invite Users into your Organization via email. Alternatively, Users can be added directly without an Invitation if their ApiKey or Authenticator credentials are known ahead of time.\n\nSee [Users](./api#tag/Users) for more information" + }, + { + "name": "Policies", + "description": "Policies allow for deep customization of the security of your Organization. They can be used to grant permissions or restrict usage of Users and Private Keys. The Policy Engine analyzes all of your Policies on each request to determine whether an Activity is allowed.\n\nSee [Policy Overview](../managing-policies/overview) for more information" + }, + { + "name": "Wallets", + "description": "Wallets contain collections of deterministically generated cryptographic public / private key pairs that share a common seed. Turnkey securely holds the common seed, but only you can access it. In most cases, Wallets should be preferred over Private Keys since they can be represented by a mnemonic phrase, used across a variety of cryptographic curves, and can derive many addresses.\n\nDerived addresses can be used to create digital signatures using the corresponding underlying private key. See [Signing](./api#tag/Signing) for more information" + }, + { + "name": "Signing", + "description": "Signers allow you to create digital signatures. Signatures are used to validate the authenticity and integrity of a digital message. Turnkey makes it easy to produce signatures by allowing you to sign with an address. If Turnkey doesn't yet support an address format you need, you can generate and sign with the public key instead by using the address format `ADDRESS_FORMAT_COMPRESSED`." + }, + { + "name": "Private Keys", + "description": "Private Keys are cryptographic public / private key pairs that can be used for cryptocurrency needs or more generalized encryption. Turnkey securely holds all private key materials for you, but only you can access them.\n\nThe Private Key ID or any derived address can be used to create digital signatures. See [Signing](./api#tag/Signing) for more information" + }, + { + "name": "Private Key Tags", + "description": "Private Key Tags allow you to easily group and permission Private Keys through Policies." + }, + { + "name": "Users", + "description": "Users are responsible for any action taken within an Organization. They can have ApiKey or Auuthenticator credentials, allowing you to onboard teammates to the Organization, or create API-only Users to run as part of your infrastructure." + }, + { + "name": "User Tags", + "description": "User Key Tags allow you to easily group and permission Users through Policies." + }, + { + "name": "Authenticators", + "description": "Authenticators are WebAuthN hardware devices, such as a Macbook TouchID or Yubikey, that can be used to authenticate requests." + }, + { + "name": "API Keys", + "description": "API Keys are used to authenticate requests\n\nSee our [CLI](https://github.com/tkhq/tkcli) for instructions on generating API Keys" + }, + { + "name": "Activities", + "description": "Activities encapsulate all the possible actions that can be taken with Turnkey. Some examples include adding a new user, creating a private key, and signing a transaction.\n\nActivities that modify your Organization are processed asynchronously. To confirm processing is complete and retrieve the Activity results, these activities must be polled until that status has been updated to a finalized state: `COMPLETED` when the activity is successful or `FAILED` when the activity has failed" + }, + { + "name": "Consensus", + "description": "Policies can enforce consensus requirements for Activities. For example, adding a new user requires two admins to approve the request.\n\nActivities that have been proposed, but don't yet meet the Consesnsus requirements will have the status: `REQUIRES_CONSENSUS`. Activities in this state can be approved or rejected using the unique fingerprint generated when an Activity is created." + } + ], + "host": "api.turnkey.com", + "schemes": ["https"], + "consumes": ["application/json"], + "produces": ["application/json"], + "paths": { + "/public/v1/query/get_activity": { + "post": { + "summary": "Get activity", + "description": "Get details about an activity.", + "operationId": "PublicApiService_GetActivity", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1GetActivityRequest" + } + } + ], + "tags": ["Activities"] + } + }, + "/public/v1/query/get_api_key": { + "post": { + "summary": "Get API key", + "description": "Get details about an API key.", + "operationId": "PublicApiService_GetApiKey", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1GetApiKeyResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1GetApiKeyRequest" + } + } + ], + "tags": ["API keys"] + } + }, + "/public/v1/query/get_api_keys": { + "post": { + "summary": "Get API keys", + "description": "Get details about API keys for a user.", + "operationId": "PublicApiService_GetApiKeys", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1GetApiKeysResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1GetApiKeysRequest" + } + } + ], + "tags": ["API keys"] + } + }, + "/public/v1/query/get_attestation": { + "post": { + "summary": "Attestation", + "description": "Get the attestation document corresponding to an enclave.", + "operationId": "PublicApiService_GetAttestationDocument", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1GetAttestationDocumentResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1GetAttestationDocumentRequest" + } + } + ], + "tags": ["Attestation"] + } + }, + "/public/v1/query/get_authenticator": { + "post": { + "summary": "Get authenticator", + "description": "Get details about an authenticator.", + "operationId": "PublicApiService_GetAuthenticator", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1GetAuthenticatorResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1GetAuthenticatorRequest" + } + } + ], + "tags": ["Authenticators"] + } + }, + "/public/v1/query/get_authenticators": { + "post": { + "summary": "Get authenticators", + "description": "Get details about authenticators for a user.", + "operationId": "PublicApiService_GetAuthenticators", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1GetAuthenticatorsResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1GetAuthenticatorsRequest" + } + } + ], + "tags": ["Authenticators"] + } + }, + "/public/v1/query/get_oauth_providers": { + "post": { + "summary": "Get Oauth providers", + "description": "Get details about Oauth providers for a user.", + "operationId": "PublicApiService_GetOauthProviders", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1GetOauthProvidersResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1GetOauthProvidersRequest" + } + } + ], + "tags": ["User Auth"] + } + }, + "/public/v1/query/get_organization": { + "post": { + "summary": "Get organization", + "description": "Get details about an organization.", + "operationId": "PublicApiService_GetOrganization", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1GetOrganizationResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1GetOrganizationRequest" + } + } + ], + "tags": ["Organizations"] + } + }, + "/public/v1/query/get_organization_configs": { + "post": { + "summary": "Get configs", + "description": "Get quorum settings and features for an organization.", + "operationId": "PublicApiService_GetOrganizationConfigs", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1GetOrganizationConfigsResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1GetOrganizationConfigsRequest" + } + } + ], + "tags": ["Organizations"] + } + }, + "/public/v1/query/get_policy": { + "post": { + "summary": "Get policy", + "description": "Get details about a policy.", + "operationId": "PublicApiService_GetPolicy", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1GetPolicyResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1GetPolicyRequest" + } + } + ], + "tags": ["Policies"] + } + }, + "/public/v1/query/get_policy_evaluations": { + "post": { + "summary": "Get policy evaluations", + "description": "Get the policy evaluations for an activity.", + "operationId": "PublicApiService_GetPolicyEvaluations", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1GetPolicyEvaluationsResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1GetPolicyEvaluationsRequest" + } + } + ], + "tags": ["Activities"] + } + }, + "/public/v1/query/get_private_key": { + "post": { + "summary": "Get private key", + "description": "Get details about a private key.", + "operationId": "PublicApiService_GetPrivateKey", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1GetPrivateKeyResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1GetPrivateKeyRequest" + } + } + ], + "tags": ["Private Keys"] + } + }, + "/public/v1/query/get_smart_contract_interface": { + "post": { + "summary": "Get smart contract interface", + "description": "Get details about a smart contract interface.", + "operationId": "PublicApiService_GetSmartContractInterface", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1GetSmartContractInterfaceResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1GetSmartContractInterfaceRequest" + } + } + ], + "tags": ["Policies"] + } + }, + "/public/v1/query/get_user": { + "post": { + "summary": "Get user", + "description": "Get details about a user.", + "operationId": "PublicApiService_GetUser", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1GetUserResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1GetUserRequest" + } + } + ], + "tags": ["Users"] + } + }, + "/public/v1/query/get_wallet": { + "post": { + "summary": "Get wallet", + "description": "Get details about a wallet.", + "operationId": "PublicApiService_GetWallet", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1GetWalletResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1GetWalletRequest" + } + } + ], + "tags": ["Wallets"] + } + }, + "/public/v1/query/get_wallet_account": { + "post": { + "summary": "Get wallet account", + "description": "Get a single wallet account.", + "operationId": "PublicApiService_GetWalletAccount", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1GetWalletAccountResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1GetWalletAccountRequest" + } + } + ], + "tags": ["Wallets"] + } + }, + "/public/v1/query/list_activities": { + "post": { + "summary": "List activities", + "description": "List all activities within an organization.", + "operationId": "PublicApiService_GetActivities", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1GetActivitiesResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1GetActivitiesRequest" + } + } + ], + "tags": ["Activities"] + } + }, + "/public/v1/query/list_policies": { + "post": { + "summary": "List policies", + "description": "List all policies within an organization.", + "operationId": "PublicApiService_GetPolicies", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1GetPoliciesResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1GetPoliciesRequest" + } + } + ], + "tags": ["Policies"] + } + }, + "/public/v1/query/list_private_key_tags": { + "post": { + "summary": "List private key tags", + "description": "List all private key tags within an organization.", + "operationId": "PublicApiService_ListPrivateKeyTags", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ListPrivateKeyTagsResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1ListPrivateKeyTagsRequest" + } + } + ], + "tags": ["Private Key Tags"] + } + }, + "/public/v1/query/list_private_keys": { + "post": { + "summary": "List private keys", + "description": "List all private keys within an organization.", + "operationId": "PublicApiService_GetPrivateKeys", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1GetPrivateKeysResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1GetPrivateKeysRequest" + } + } + ], + "tags": ["Private Keys"] + } + }, + "/public/v1/query/list_smart_contract_interfaces": { + "post": { + "summary": "List smart contract interfaces", + "description": "List all smart contract interfaces within an organization.", + "operationId": "PublicApiService_GetSmartContractInterfaces", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1GetSmartContractInterfacesResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1GetSmartContractInterfacesRequest" + } + } + ], + "tags": ["Policies"] + } + }, + "/public/v1/query/list_suborgs": { + "post": { + "summary": "Get sub-organizations", + "description": "Get all suborg IDs associated given a parent org ID and an optional filter.", + "operationId": "PublicApiService_GetSubOrgIds", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1GetSubOrgIdsResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1GetSubOrgIdsRequest" + } + } + ], + "tags": ["Organizations"] + } + }, + "/public/v1/query/list_user_tags": { + "post": { + "summary": "List user tags", + "description": "List all user tags within an organization.", + "operationId": "PublicApiService_ListUserTags", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ListUserTagsResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1ListUserTagsRequest" + } + } + ], + "tags": ["User Tags"] + } + }, + "/public/v1/query/list_users": { + "post": { + "summary": "List users", + "description": "List all users within an organization.", + "operationId": "PublicApiService_GetUsers", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1GetUsersResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1GetUsersRequest" + } + } + ], + "tags": ["Users"] + } + }, + "/public/v1/query/list_verified_suborgs": { + "post": { + "summary": "Get verified sub-organizations", + "description": "Get all email or phone verified suborg IDs associated given a parent org ID.", + "operationId": "PublicApiService_GetVerifiedSubOrgIds", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1GetVerifiedSubOrgIdsResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1GetVerifiedSubOrgIdsRequest" + } + } + ], + "tags": ["Organizations"] + } + }, + "/public/v1/query/list_wallet_accounts": { + "post": { + "summary": "List wallets accounts", + "description": "List all accounts within a wallet.", + "operationId": "PublicApiService_GetWalletAccounts", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1GetWalletAccountsResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1GetWalletAccountsRequest" + } + } + ], + "tags": ["Wallets"] + } + }, + "/public/v1/query/list_wallets": { + "post": { + "summary": "List wallets", + "description": "List all wallets within an organization.", + "operationId": "PublicApiService_GetWallets", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1GetWalletsResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1GetWalletsRequest" + } + } + ], + "tags": ["Wallets"] + } + }, + "/public/v1/query/whoami": { + "post": { + "summary": "Who am I?", + "description": "Get basic information about your current API or WebAuthN user and their organization. Affords sub-organization look ups via parent organization for WebAuthN or API key users.", + "operationId": "PublicApiService_GetWhoami", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1GetWhoamiResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1GetWhoamiRequest" + } + } + ], + "tags": ["Sessions"] + } + }, + "/public/v1/submit/approve_activity": { + "post": { + "summary": "Approve activity", + "description": "Approve an activity.", + "operationId": "PublicApiService_ApproveActivity", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1ApproveActivityRequest" + } + } + ], + "tags": ["Consensus"] + } + }, + "/public/v1/submit/create_api_keys": { + "post": { + "summary": "Create API keys", + "description": "Add API keys to an existing user.", + "operationId": "PublicApiService_CreateApiKeys", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1CreateApiKeysRequest" + } + } + ], + "tags": ["API Keys"] + } + }, + "/public/v1/submit/create_api_only_users": { + "post": { + "summary": "Create API-only users", + "description": "Create API-only users in an existing organization.", + "operationId": "PublicApiService_CreateApiOnlyUsers", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1CreateApiOnlyUsersRequest" + } + } + ], + "tags": ["Users"] + } + }, + "/public/v1/submit/create_authenticators": { + "post": { + "summary": "Create authenticators", + "description": "Create authenticators to authenticate requests to Turnkey.", + "operationId": "PublicApiService_CreateAuthenticators", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1CreateAuthenticatorsRequest" + } + } + ], + "tags": ["Authenticators"] + } + }, + "/public/v1/submit/create_invitations": { + "post": { + "summary": "Create invitations", + "description": "Create invitations to join an existing organization.", + "operationId": "PublicApiService_CreateInvitations", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1CreateInvitationsRequest" + } + } + ], + "tags": ["Invitations"] + } + }, + "/public/v1/submit/create_oauth_providers": { + "post": { + "summary": "Create Oauth providers", + "description": "Create Oauth providers for a specified user.", + "operationId": "PublicApiService_CreateOauthProviders", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1CreateOauthProvidersRequest" + } + } + ], + "tags": ["User Auth"] + } + }, + "/public/v1/submit/create_policies": { + "post": { + "summary": "Create policies", + "description": "Create new policies.", + "operationId": "PublicApiService_CreatePolicies", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1CreatePoliciesRequest" + } + } + ], + "tags": ["Policies"] + } + }, + "/public/v1/submit/create_policy": { + "post": { + "summary": "Create policy", + "description": "Create a new policy.", + "operationId": "PublicApiService_CreatePolicy", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1CreatePolicyRequest" + } + } + ], + "tags": ["Policies"] + } + }, + "/public/v1/submit/create_private_key_tag": { + "post": { + "summary": "Create private key tag", + "description": "Create a private key tag and add it to private keys.", + "operationId": "PublicApiService_CreatePrivateKeyTag", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1CreatePrivateKeyTagRequest" + } + } + ], + "tags": ["Private Key Tags"] + } + }, + "/public/v1/submit/create_private_keys": { + "post": { + "summary": "Create private keys", + "description": "Create new private keys.", + "operationId": "PublicApiService_CreatePrivateKeys", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1CreatePrivateKeysRequest" + } + } + ], + "tags": ["Private Keys"] + } + }, + "/public/v1/submit/create_read_only_session": { + "post": { + "summary": "Create read only session", + "description": "Create a read only session for a user (valid for 1 hour).", + "operationId": "PublicApiService_CreateReadOnlySession", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1CreateReadOnlySessionRequest" + } + } + ], + "tags": ["Sessions"] + } + }, + "/public/v1/submit/create_read_write_session": { + "post": { + "summary": "Create read write session", + "description": "Create a read write session for a user.", + "operationId": "PublicApiService_CreateReadWriteSession", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1CreateReadWriteSessionRequest" + } + } + ], + "tags": ["Sessions"] + } + }, + "/public/v1/submit/create_smart_contract_interface": { + "post": { + "summary": "Create smart contract interface", + "description": "Create an ABI/IDL in JSON.", + "operationId": "PublicApiService_CreateSmartContractInterface", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1CreateSmartContractInterfaceRequest" + } + } + ], + "tags": ["Policies"] + } + }, + "/public/v1/submit/create_sub_organization": { + "post": { + "summary": "Create sub-organization", + "description": "Create a new sub-organization.", + "operationId": "PublicApiService_CreateSubOrganization", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1CreateSubOrganizationRequest" + } + } + ], + "tags": ["Organizations"] + } + }, + "/public/v1/submit/create_user_tag": { + "post": { + "summary": "Create user tag", + "description": "Create a user tag and add it to users.", + "operationId": "PublicApiService_CreateUserTag", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1CreateUserTagRequest" + } + } + ], + "tags": ["User Tags"] + } + }, + "/public/v1/submit/create_users": { + "post": { + "summary": "Create users", + "description": "Create users in an existing organization.", + "operationId": "PublicApiService_CreateUsers", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1CreateUsersRequest" + } + } + ], + "tags": ["Users"] + } + }, + "/public/v1/submit/create_wallet": { + "post": { + "summary": "Create wallet", + "description": "Create a wallet and derive addresses.", + "operationId": "PublicApiService_CreateWallet", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1CreateWalletRequest" + } + } + ], + "tags": ["Wallets"] + } + }, + "/public/v1/submit/create_wallet_accounts": { + "post": { + "summary": "Create wallet accounts", + "description": "Derive additional addresses using an existing wallet.", + "operationId": "PublicApiService_CreateWalletAccounts", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1CreateWalletAccountsRequest" + } + } + ], + "tags": ["Wallets"] + } + }, + "/public/v1/submit/delete_api_keys": { + "post": { + "summary": "Delete API keys", + "description": "Remove api keys from a user.", + "operationId": "PublicApiService_DeleteApiKeys", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1DeleteApiKeysRequest" + } + } + ], + "tags": ["API Keys"] + } + }, + "/public/v1/submit/delete_authenticators": { + "post": { + "summary": "Delete authenticators", + "description": "Remove authenticators from a user.", + "operationId": "PublicApiService_DeleteAuthenticators", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1DeleteAuthenticatorsRequest" + } + } + ], + "tags": ["Authenticators"] + } + }, + "/public/v1/submit/delete_invitation": { + "post": { + "summary": "Delete invitation", + "description": "Delete an existing invitation.", + "operationId": "PublicApiService_DeleteInvitation", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1DeleteInvitationRequest" + } + } + ], + "tags": ["Invitations"] + } + }, + "/public/v1/submit/delete_oauth_providers": { + "post": { + "summary": "Delete Oauth providers", + "description": "Remove Oauth providers for a specified user.", + "operationId": "PublicApiService_DeleteOauthProviders", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1DeleteOauthProvidersRequest" + } + } + ], + "tags": ["User Auth"] + } + }, + "/public/v1/submit/delete_policy": { + "post": { + "summary": "Delete policy", + "description": "Delete an existing policy.", + "operationId": "PublicApiService_DeletePolicy", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1DeletePolicyRequest" + } + } + ], + "tags": ["Policies"] + } + }, + "/public/v1/submit/delete_private_key_tags": { + "post": { + "summary": "Delete private key tags", + "description": "Delete private key tags within an organization.", + "operationId": "PublicApiService_DeletePrivateKeyTags", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1DeletePrivateKeyTagsRequest" + } + } + ], + "tags": ["Private Key Tags"] + } + }, + "/public/v1/submit/delete_private_keys": { + "post": { + "summary": "Delete private keys", + "description": "Delete private keys for an organization.", + "operationId": "PublicApiService_DeletePrivateKeys", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1DeletePrivateKeysRequest" + } + } + ], + "tags": ["Private Keys"] + } + }, + "/public/v1/submit/delete_smart_contract_interface": { + "post": { + "summary": "Delete smart contract interface", + "description": "Delete a smart contract interface.", + "operationId": "PublicApiService_DeleteSmartContractInterface", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1DeleteSmartContractInterfaceRequest" + } + } + ], + "tags": ["Policies"] + } + }, + "/public/v1/submit/delete_sub_organization": { + "post": { + "summary": "Delete sub-organization", + "description": "Delete a sub-organization.", + "operationId": "PublicApiService_DeleteSubOrganization", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1DeleteSubOrganizationRequest" + } + } + ], + "tags": ["Organizations"] + } + }, + "/public/v1/submit/delete_user_tags": { + "post": { + "summary": "Delete user tags", + "description": "Delete user tags within an organization.", + "operationId": "PublicApiService_DeleteUserTags", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1DeleteUserTagsRequest" + } + } + ], + "tags": ["User Tags"] + } + }, + "/public/v1/submit/delete_users": { + "post": { + "summary": "Delete users", + "description": "Delete users within an organization.", + "operationId": "PublicApiService_DeleteUsers", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1DeleteUsersRequest" + } + } + ], + "tags": ["Users"] + } + }, + "/public/v1/submit/delete_wallets": { + "post": { + "summary": "Delete wallets", + "description": "Delete wallets for an organization.", + "operationId": "PublicApiService_DeleteWallets", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1DeleteWalletsRequest" + } + } + ], + "tags": ["Wallets"] + } + }, + "/public/v1/submit/email_auth": { + "post": { + "summary": "Perform email auth", + "description": "Authenticate a user via email.", + "operationId": "PublicApiService_EmailAuth", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1EmailAuthRequest" + } + } + ], + "tags": ["User Auth"] + } + }, + "/public/v1/submit/export_private_key": { + "post": { + "summary": "Export private key", + "description": "Export a private key.", + "operationId": "PublicApiService_ExportPrivateKey", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1ExportPrivateKeyRequest" + } + } + ], + "tags": ["Private Keys"] + } + }, + "/public/v1/submit/export_wallet": { + "post": { + "summary": "Export wallet", + "description": "Export a wallet.", + "operationId": "PublicApiService_ExportWallet", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1ExportWalletRequest" + } + } + ], + "tags": ["Wallets"] + } + }, + "/public/v1/submit/export_wallet_account": { + "post": { + "summary": "Export wallet account", + "description": "Export a wallet account.", + "operationId": "PublicApiService_ExportWalletAccount", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1ExportWalletAccountRequest" + } + } + ], + "tags": ["Wallets"] + } + }, + "/public/v1/submit/import_private_key": { + "post": { + "summary": "Import private key", + "description": "Import a private key.", + "operationId": "PublicApiService_ImportPrivateKey", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1ImportPrivateKeyRequest" + } + } + ], + "tags": ["Private Keys"] + } + }, + "/public/v1/submit/import_wallet": { + "post": { + "summary": "Import wallet", + "description": "Import a wallet.", + "operationId": "PublicApiService_ImportWallet", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1ImportWalletRequest" + } + } + ], + "tags": ["Wallets"] + } + }, + "/public/v1/submit/init_fiat_on_ramp": { + "post": { + "summary": "Init fiat on ramp", + "description": "Initiate a fiat on ramp flow.", + "operationId": "PublicApiService_InitFiatOnRamp", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1InitFiatOnRampRequest" + } + } + ], + "tags": ["On Ramp"] + } + }, + "/public/v1/submit/init_import_private_key": { + "post": { + "summary": "Init import private key", + "description": "Initialize a new private key import.", + "operationId": "PublicApiService_InitImportPrivateKey", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1InitImportPrivateKeyRequest" + } + } + ], + "tags": ["Private Keys"] + } + }, + "/public/v1/submit/init_import_wallet": { + "post": { + "summary": "Init import wallet", + "description": "Initialize a new wallet import.", + "operationId": "PublicApiService_InitImportWallet", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1InitImportWalletRequest" + } + } + ], + "tags": ["Wallets"] + } + }, + "/public/v1/submit/init_otp": { + "post": { + "summary": "Init generic OTP", + "description": "Initiate a generic OTP activity.", + "operationId": "PublicApiService_InitOtp", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1InitOtpRequest" + } + } + ], + "tags": ["User Verification"] + } + }, + "/public/v1/submit/init_otp_auth": { + "post": { + "summary": "Init OTP auth", + "description": "Initiate an OTP auth activity.", + "operationId": "PublicApiService_InitOtpAuth", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1InitOtpAuthRequest" + } + } + ], + "tags": ["User Auth"] + } + }, + "/public/v1/submit/init_user_email_recovery": { + "post": { + "summary": "Init email recovery", + "description": "Initialize a new email recovery.", + "operationId": "PublicApiService_InitUserEmailRecovery", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1InitUserEmailRecoveryRequest" + } + } + ], + "tags": ["User Recovery"] + } + }, + "/public/v1/submit/oauth": { + "post": { + "summary": "Oauth", + "description": "Authenticate a user with an OIDC token (Oauth).", + "operationId": "PublicApiService_Oauth", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1OauthRequest" + } + } + ], + "tags": ["User Auth"] + } + }, + "/public/v1/submit/oauth_login": { + "post": { + "summary": "Login with Oauth", + "description": "Create an Oauth session for a user.", + "operationId": "PublicApiService_OauthLogin", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1OauthLoginRequest" + } + } + ], + "tags": ["Sessions"] + } + }, + "/public/v1/submit/otp_auth": { + "post": { + "summary": "OTP auth", + "description": "Authenticate a user with an OTP code sent via email or SMS.", + "operationId": "PublicApiService_OtpAuth", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1OtpAuthRequest" + } + } + ], + "tags": ["User Auth"] + } + }, + "/public/v1/submit/otp_login": { + "post": { + "summary": "Login with OTP", + "description": "Create an OTP session for a user.", + "operationId": "PublicApiService_OtpLogin", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1OtpLoginRequest" + } + } + ], + "tags": ["Sessions"] + } + }, + "/public/v1/submit/recover_user": { + "post": { + "summary": "Recover a user", + "description": "Complete the process of recovering a user by adding an authenticator.", + "operationId": "PublicApiService_RecoverUser", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1RecoverUserRequest" + } + } + ], + "tags": ["User Recovery"] + } + }, + "/public/v1/submit/reject_activity": { + "post": { + "summary": "Reject activity", + "description": "Reject an activity.", + "operationId": "PublicApiService_RejectActivity", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1RejectActivityRequest" + } + } + ], + "tags": ["Consensus"] + } + }, + "/public/v1/submit/remove_organization_feature": { + "post": { + "summary": "Remove organization feature", + "description": "Remove an organization feature. This activity must be approved by the current root quorum.", + "operationId": "PublicApiService_RemoveOrganizationFeature", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1RemoveOrganizationFeatureRequest" + } + } + ], + "tags": ["Features"] + } + }, + "/public/v1/submit/set_organization_feature": { + "post": { + "summary": "Set organization feature", + "description": "Set an organization feature. This activity must be approved by the current root quorum.", + "operationId": "PublicApiService_SetOrganizationFeature", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1SetOrganizationFeatureRequest" + } + } + ], + "tags": ["Features"] + } + }, + "/public/v1/submit/sign_raw_payload": { + "post": { + "summary": "Sign raw payload", + "description": "Sign a raw payload.", + "operationId": "PublicApiService_SignRawPayload", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1SignRawPayloadRequest" + } + } + ], + "tags": ["Signing"] + } + }, + "/public/v1/submit/sign_raw_payloads": { + "post": { + "summary": "Sign raw payloads", + "description": "Sign multiple raw payloads with the same signing parameters.", + "operationId": "PublicApiService_SignRawPayloads", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1SignRawPayloadsRequest" + } + } + ], + "tags": ["Signing"] + } + }, + "/public/v1/submit/sign_transaction": { + "post": { + "summary": "Sign transaction", + "description": "Sign a transaction.", + "operationId": "PublicApiService_SignTransaction", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1SignTransactionRequest" + } + } + ], + "tags": ["Signing"] + } + }, + "/public/v1/submit/stamp_login": { + "post": { + "summary": "Login with a stamp", + "description": "Create a session for a user through stamping client side (API key, wallet client, or passkey client).", + "operationId": "PublicApiService_StampLogin", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1StampLoginRequest" + } + } + ], + "tags": ["Sessions"] + } + }, + "/public/v1/submit/update_policy": { + "post": { + "summary": "Update policy", + "description": "Update an existing policy.", + "operationId": "PublicApiService_UpdatePolicy", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1UpdatePolicyRequest" + } + } + ], + "tags": ["Policies"] + } + }, + "/public/v1/submit/update_private_key_tag": { + "post": { + "summary": "Update private key tag", + "description": "Update human-readable name or associated private keys. Note that this activity is atomic: all of the updates will succeed at once, or all of them will fail.", + "operationId": "PublicApiService_UpdatePrivateKeyTag", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1UpdatePrivateKeyTagRequest" + } + } + ], + "tags": ["Private Key Tags"] + } + }, + "/public/v1/submit/update_root_quorum": { + "post": { + "summary": "Update root quorum", + "description": "Set the threshold and members of the root quorum. This activity must be approved by the current root quorum.", + "operationId": "PublicApiService_UpdateRootQuorum", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1UpdateRootQuorumRequest" + } + } + ], + "tags": ["Organizations"] + } + }, + "/public/v1/submit/update_user": { + "post": { + "summary": "Update user", + "description": "Update a user in an existing organization.", + "operationId": "PublicApiService_UpdateUser", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1UpdateUserRequest" + } + } + ], + "tags": ["Users"] + } + }, + "/public/v1/submit/update_user_email": { + "post": { + "summary": "Update user's email", + "description": "Update a user's email in an existing organization.", + "operationId": "PublicApiService_UpdateUserEmail", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1UpdateUserEmailRequest" + } + } + ], + "tags": ["Users"] + } + }, + "/public/v1/submit/update_user_name": { + "post": { + "summary": "Update user's name", + "description": "Update a user's name in an existing organization.", + "operationId": "PublicApiService_UpdateUserName", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1UpdateUserNameRequest" + } + } + ], + "tags": ["Users"] + } + }, + "/public/v1/submit/update_user_phone_number": { + "post": { + "summary": "Update user's phone number", + "description": "Update a user's phone number in an existing organization.", + "operationId": "PublicApiService_UpdateUserPhoneNumber", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1UpdateUserPhoneNumberRequest" + } + } + ], + "tags": ["Users"] + } + }, + "/public/v1/submit/update_user_tag": { + "post": { + "summary": "Update user tag", + "description": "Update human-readable name or associated users. Note that this activity is atomic: all of the updates will succeed at once, or all of them will fail.", + "operationId": "PublicApiService_UpdateUserTag", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1UpdateUserTagRequest" + } + } + ], + "tags": ["User Tags"] + } + }, + "/public/v1/submit/update_wallet": { + "post": { + "summary": "Update wallet", + "description": "Update a wallet for an organization.", + "operationId": "PublicApiService_UpdateWallet", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1UpdateWalletRequest" + } + } + ], + "tags": ["Wallets"] + } + }, + "/public/v1/submit/verify_otp": { + "post": { + "summary": "Verify generic OTP", + "description": "Verify a generic OTP.", + "operationId": "PublicApiService_VerifyOtp", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1ActivityResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1VerifyOtpRequest" + } + } + ], + "tags": ["User Verification"] + } + }, + "/tkhq/api/v1/noop-codegen-anchor": { + "post": { + "operationId": "PublicApiService_NOOPCodegenAnchor", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1NOOPCodegenAnchorResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "tags": ["PublicApiService"] + } + }, + "/tkhq/api/v1/test_rate_limits": { + "post": { + "summary": "Test rate limit", + "description": "Set a rate local rate limit just on the current endpoint, for purposes of testing with Vivosuite.", + "operationId": "PublicApiService_TestRateLimits", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/v1TestRateLimitsResponse" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/v1TestRateLimitsRequest" + } + } + ], + "tags": ["RateLimit"] + } + } + }, + "definitions": { + "apiApiKeyParams": { + "type": "object", + "properties": { + "apiKeyName": { + "type": "string", + "description": "Human-readable name for an API Key." + }, + "publicKey": { + "type": "string", + "description": "The public component of a cryptographic key pair used to sign messages and transactions." + }, + "expirationSeconds": { + "type": "string", + "description": "Optional window (in seconds) indicating how long the API Key should last." + } + }, + "required": ["apiKeyName", "publicKey"] + }, + "billingActivateBillingTierIntent": { + "type": "object", + "properties": { + "productId": { + "type": "string", + "description": "The product that the customer wants to subscribe to." + } + }, + "required": ["productId"] + }, + "billingActivateBillingTierResult": { + "type": "object", + "properties": { + "productId": { + "type": "string", + "description": "The id of the product being subscribed to." + } + }, + "required": ["productId"] + }, + "billingDeletePaymentMethodIntent": { + "type": "object", + "properties": { + "paymentMethodId": { + "type": "string", + "description": "The payment method that the customer wants to remove." + } + }, + "required": ["paymentMethodId"] + }, + "billingDeletePaymentMethodResult": { + "type": "object", + "properties": { + "paymentMethodId": { + "type": "string", + "description": "The payment method that was removed." + } + }, + "required": ["paymentMethodId"] + }, + "billingSetPaymentMethodIntent": { + "type": "object", + "properties": { + "number": { + "type": "string", + "description": "The account number of the customer's credit card." + }, + "cvv": { + "type": "string", + "description": "The verification digits of the customer's credit card." + }, + "expiryMonth": { + "type": "string", + "description": "The month that the credit card expires." + }, + "expiryYear": { + "type": "string", + "description": "The year that the credit card expires." + }, + "cardHolderEmail": { + "type": "string", + "description": "The email that will receive invoices for the credit card." + }, + "cardHolderName": { + "type": "string", + "description": "The name associated with the credit card." + } + }, + "required": [ + "number", + "cvv", + "expiryMonth", + "expiryYear", + "cardHolderEmail", + "cardHolderName" + ] + }, + "billingSetPaymentMethodIntentV2": { + "type": "object", + "properties": { + "paymentMethodId": { + "type": "string", + "description": "The id of the payment method that was created clientside." + }, + "cardHolderEmail": { + "type": "string", + "description": "The email that will receive invoices for the credit card." + }, + "cardHolderName": { + "type": "string", + "description": "The name associated with the credit card." + } + }, + "required": ["paymentMethodId", "cardHolderEmail", "cardHolderName"] + }, + "billingSetPaymentMethodResult": { + "type": "object", + "properties": { + "lastFour": { + "type": "string", + "description": "The last four digits of the credit card added." + }, + "cardHolderName": { + "type": "string", + "description": "The name associated with the payment method." + }, + "cardHolderEmail": { + "type": "string", + "description": "The email address associated with the payment method." + } + }, + "required": ["lastFour", "cardHolderName", "cardHolderEmail"] + }, + "datav1Tag": { + "type": "object", + "properties": { + "tagId": { + "type": "string", + "description": "Unique identifier for a given Tag." + }, + "tagName": { + "type": "string", + "description": "Human-readable name for a Tag." + }, + "tagType": { + "$ref": "#/definitions/v1TagType" + }, + "createdAt": { + "$ref": "#/definitions/externaldatav1Timestamp" + }, + "updatedAt": { + "$ref": "#/definitions/externaldatav1Timestamp" + } + }, + "required": ["tagId", "tagName", "tagType", "createdAt", "updatedAt"] + }, + "externalactivityv1PolicyEvaluation": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique identifier for a given policy evaluation." + }, + "activityId": { + "type": "string", + "description": "Unique identifier for a given Activity." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for the Organization the Activity belongs to." + }, + "voteId": { + "type": "string", + "description": "Unique identifier for the Vote associated with this policy evaluation." + }, + "policyEvaluations": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/privateumpv1PolicyEvaluation" + }, + "description": "Detailed evaluation result for each Policy that was run." + }, + "createdAt": { + "$ref": "#/definitions/externaldatav1Timestamp" + } + }, + "required": [ + "id", + "activityId", + "organizationId", + "voteId", + "policyEvaluations", + "createdAt" + ] + }, + "externaldatav1Address": { + "type": "object", + "properties": { + "format": { + "$ref": "#/definitions/v1AddressFormat" + }, + "address": { + "type": "string" + } + } + }, + "externaldatav1Credential": { + "type": "object", + "properties": { + "publicKey": { + "type": "string", + "description": "The public component of a cryptographic key pair used to sign messages and transactions." + }, + "type": { + "$ref": "#/definitions/v1CredentialType" + } + }, + "required": ["publicKey", "type"] + }, + "externaldatav1Quorum": { + "type": "object", + "properties": { + "threshold": { + "type": "integer", + "format": "int32", + "description": "Count of unique approvals required to meet quorum." + }, + "userIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Unique identifiers of quorum set members." + } + }, + "required": ["threshold", "userIds"] + }, + "externaldatav1SmartContractInterface": { + "type": "object", + "properties": { + "organizationId": { + "type": "string", + "description": "The Organization the Smart Contract Interface belongs to." + }, + "smartContractInterfaceId": { + "type": "string", + "description": "Unique identifier for a given Smart Contract Interface (ABI or IDL)." + }, + "smartContractAddress": { + "type": "string", + "description": "The address corresponding to the Smart Contract or Program." + }, + "smartContractInterface": { + "type": "string", + "description": "The JSON corresponding to the Smart Contract Interface (ABI or IDL)." + }, + "type": { + "type": "string", + "description": "The type corresponding to the Smart Contract Interface (either ETHEREUM or SOLANA)." + }, + "label": { + "type": "string", + "description": "The label corresponding to the Smart Contract Interface (either ETHEREUM or SOLANA)." + }, + "notes": { + "type": "string", + "description": "The notes corresponding to the Smart Contract Interface (either ETHEREUM or SOLANA)." + }, + "createdAt": { + "$ref": "#/definitions/externaldatav1Timestamp" + }, + "updatedAt": { + "$ref": "#/definitions/externaldatav1Timestamp" + } + }, + "required": [ + "organizationId", + "smartContractInterfaceId", + "smartContractAddress", + "smartContractInterface", + "type", + "label", + "notes", + "createdAt", + "updatedAt" + ] + }, + "externaldatav1Timestamp": { + "type": "object", + "properties": { + "seconds": { + "type": "string" + }, + "nanos": { + "type": "string" + } + }, + "required": ["seconds", "nanos"] + }, + "immutableactivityv1Address": { + "type": "object", + "properties": { + "format": { + "$ref": "#/definitions/v1AddressFormat" + }, + "address": { + "type": "string" + } + } + }, + "privateumpv1PolicyEvaluation": { + "type": "object", + "properties": { + "policyId": { + "type": "string" + }, + "outcome": { + "$ref": "#/definitions/v1Outcome" + } + } + }, + "protobufAny": { + "type": "object", + "properties": { + "@type": { + "type": "string" + } + }, + "additionalProperties": {} + }, + "rpcStatus": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + }, + "details": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/protobufAny" + } + } + } + }, + "v1AcceptInvitationIntent": { + "type": "object", + "properties": { + "invitationId": { + "type": "string", + "description": "Unique identifier for a given Invitation object." + }, + "userId": { + "type": "string", + "description": "Unique identifier for a given User." + }, + "authenticator": { + "$ref": "#/definitions/v1AuthenticatorParams", + "description": "WebAuthN hardware devices that can be used to log in to the Turnkey web app." + } + }, + "required": ["invitationId", "userId", "authenticator"] + }, + "v1AcceptInvitationIntentV2": { + "type": "object", + "properties": { + "invitationId": { + "type": "string", + "description": "Unique identifier for a given Invitation object." + }, + "userId": { + "type": "string", + "description": "Unique identifier for a given User." + }, + "authenticator": { + "$ref": "#/definitions/v1AuthenticatorParamsV2", + "description": "WebAuthN hardware devices that can be used to log in to the Turnkey web app." + } + }, + "required": ["invitationId", "userId", "authenticator"] + }, + "v1AcceptInvitationResult": { + "type": "object", + "properties": { + "invitationId": { + "type": "string", + "description": "Unique identifier for a given Invitation." + }, + "userId": { + "type": "string", + "description": "Unique identifier for a given User." + } + }, + "required": ["invitationId", "userId"] + }, + "v1AccessType": { + "type": "string", + "enum": ["ACCESS_TYPE_WEB", "ACCESS_TYPE_API", "ACCESS_TYPE_ALL"] + }, + "v1Activity": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique identifier for a given Activity object." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "status": { + "$ref": "#/definitions/v1ActivityStatus", + "description": "The current processing status of a specified Activity." + }, + "type": { + "$ref": "#/definitions/v1ActivityType", + "description": "Type of Activity, such as Add User, or Sign Transaction." + }, + "intent": { + "$ref": "#/definitions/v1Intent", + "description": "Intent object crafted by Turnkey based on the user request, used to assess the permissibility of an action." + }, + "result": { + "$ref": "#/definitions/v1Result", + "description": "Result of the intended action." + }, + "votes": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1Vote" + }, + "description": "A list of objects representing a particular User's approval or rejection of a Consensus request, including all relevant metadata." + }, + "fingerprint": { + "type": "string", + "description": "An artifact verifying a User's action." + }, + "canApprove": { + "type": "boolean" + }, + "canReject": { + "type": "boolean" + }, + "createdAt": { + "$ref": "#/definitions/externaldatav1Timestamp" + }, + "updatedAt": { + "$ref": "#/definitions/externaldatav1Timestamp" + }, + "failure": { + "$ref": "#/definitions/rpcStatus", + "description": "Failure reason of the intended action." + } + }, + "required": [ + "id", + "organizationId", + "status", + "type", + "intent", + "result", + "votes", + "fingerprint", + "canApprove", + "canReject", + "createdAt", + "updatedAt" + ] + }, + "v1ActivityResponse": { + "type": "object", + "properties": { + "activity": { + "$ref": "#/definitions/v1Activity", + "description": "An action that can be taken within the Turnkey infrastructure." + } + }, + "required": ["activity"] + }, + "v1ActivityStatus": { + "type": "string", + "enum": [ + "ACTIVITY_STATUS_CREATED", + "ACTIVITY_STATUS_PENDING", + "ACTIVITY_STATUS_COMPLETED", + "ACTIVITY_STATUS_FAILED", + "ACTIVITY_STATUS_CONSENSUS_NEEDED", + "ACTIVITY_STATUS_REJECTED" + ] + }, + "v1ActivityType": { + "type": "string", + "enum": [ + "ACTIVITY_TYPE_CREATE_API_KEYS", + "ACTIVITY_TYPE_CREATE_USERS", + "ACTIVITY_TYPE_CREATE_PRIVATE_KEYS", + "ACTIVITY_TYPE_SIGN_RAW_PAYLOAD", + "ACTIVITY_TYPE_CREATE_INVITATIONS", + "ACTIVITY_TYPE_ACCEPT_INVITATION", + "ACTIVITY_TYPE_CREATE_POLICY", + "ACTIVITY_TYPE_DISABLE_PRIVATE_KEY", + "ACTIVITY_TYPE_DELETE_USERS", + "ACTIVITY_TYPE_DELETE_API_KEYS", + "ACTIVITY_TYPE_DELETE_INVITATION", + "ACTIVITY_TYPE_DELETE_ORGANIZATION", + "ACTIVITY_TYPE_DELETE_POLICY", + "ACTIVITY_TYPE_CREATE_USER_TAG", + "ACTIVITY_TYPE_DELETE_USER_TAGS", + "ACTIVITY_TYPE_CREATE_ORGANIZATION", + "ACTIVITY_TYPE_SIGN_TRANSACTION", + "ACTIVITY_TYPE_APPROVE_ACTIVITY", + "ACTIVITY_TYPE_REJECT_ACTIVITY", + "ACTIVITY_TYPE_DELETE_AUTHENTICATORS", + "ACTIVITY_TYPE_CREATE_AUTHENTICATORS", + "ACTIVITY_TYPE_CREATE_PRIVATE_KEY_TAG", + "ACTIVITY_TYPE_DELETE_PRIVATE_KEY_TAGS", + "ACTIVITY_TYPE_SET_PAYMENT_METHOD", + "ACTIVITY_TYPE_ACTIVATE_BILLING_TIER", + "ACTIVITY_TYPE_DELETE_PAYMENT_METHOD", + "ACTIVITY_TYPE_CREATE_POLICY_V2", + "ACTIVITY_TYPE_CREATE_POLICY_V3", + "ACTIVITY_TYPE_CREATE_API_ONLY_USERS", + "ACTIVITY_TYPE_UPDATE_ROOT_QUORUM", + "ACTIVITY_TYPE_UPDATE_USER_TAG", + "ACTIVITY_TYPE_UPDATE_PRIVATE_KEY_TAG", + "ACTIVITY_TYPE_CREATE_AUTHENTICATORS_V2", + "ACTIVITY_TYPE_CREATE_ORGANIZATION_V2", + "ACTIVITY_TYPE_CREATE_USERS_V2", + "ACTIVITY_TYPE_ACCEPT_INVITATION_V2", + "ACTIVITY_TYPE_CREATE_SUB_ORGANIZATION", + "ACTIVITY_TYPE_CREATE_SUB_ORGANIZATION_V2", + "ACTIVITY_TYPE_UPDATE_ALLOWED_ORIGINS", + "ACTIVITY_TYPE_CREATE_PRIVATE_KEYS_V2", + "ACTIVITY_TYPE_UPDATE_USER", + "ACTIVITY_TYPE_UPDATE_POLICY", + "ACTIVITY_TYPE_SET_PAYMENT_METHOD_V2", + "ACTIVITY_TYPE_CREATE_SUB_ORGANIZATION_V3", + "ACTIVITY_TYPE_CREATE_WALLET", + "ACTIVITY_TYPE_CREATE_WALLET_ACCOUNTS", + "ACTIVITY_TYPE_INIT_USER_EMAIL_RECOVERY", + "ACTIVITY_TYPE_RECOVER_USER", + "ACTIVITY_TYPE_SET_ORGANIZATION_FEATURE", + "ACTIVITY_TYPE_REMOVE_ORGANIZATION_FEATURE", + "ACTIVITY_TYPE_SIGN_RAW_PAYLOAD_V2", + "ACTIVITY_TYPE_SIGN_TRANSACTION_V2", + "ACTIVITY_TYPE_EXPORT_PRIVATE_KEY", + "ACTIVITY_TYPE_EXPORT_WALLET", + "ACTIVITY_TYPE_CREATE_SUB_ORGANIZATION_V4", + "ACTIVITY_TYPE_EMAIL_AUTH", + "ACTIVITY_TYPE_EXPORT_WALLET_ACCOUNT", + "ACTIVITY_TYPE_INIT_IMPORT_WALLET", + "ACTIVITY_TYPE_IMPORT_WALLET", + "ACTIVITY_TYPE_INIT_IMPORT_PRIVATE_KEY", + "ACTIVITY_TYPE_IMPORT_PRIVATE_KEY", + "ACTIVITY_TYPE_CREATE_POLICIES", + "ACTIVITY_TYPE_SIGN_RAW_PAYLOADS", + "ACTIVITY_TYPE_CREATE_READ_ONLY_SESSION", + "ACTIVITY_TYPE_CREATE_OAUTH_PROVIDERS", + "ACTIVITY_TYPE_DELETE_OAUTH_PROVIDERS", + "ACTIVITY_TYPE_CREATE_SUB_ORGANIZATION_V5", + "ACTIVITY_TYPE_OAUTH", + "ACTIVITY_TYPE_CREATE_API_KEYS_V2", + "ACTIVITY_TYPE_CREATE_READ_WRITE_SESSION", + "ACTIVITY_TYPE_EMAIL_AUTH_V2", + "ACTIVITY_TYPE_CREATE_SUB_ORGANIZATION_V6", + "ACTIVITY_TYPE_DELETE_PRIVATE_KEYS", + "ACTIVITY_TYPE_DELETE_WALLETS", + "ACTIVITY_TYPE_CREATE_READ_WRITE_SESSION_V2", + "ACTIVITY_TYPE_DELETE_SUB_ORGANIZATION", + "ACTIVITY_TYPE_INIT_OTP_AUTH", + "ACTIVITY_TYPE_OTP_AUTH", + "ACTIVITY_TYPE_CREATE_SUB_ORGANIZATION_V7", + "ACTIVITY_TYPE_UPDATE_WALLET", + "ACTIVITY_TYPE_UPDATE_POLICY_V2", + "ACTIVITY_TYPE_CREATE_USERS_V3", + "ACTIVITY_TYPE_INIT_OTP_AUTH_V2", + "ACTIVITY_TYPE_INIT_OTP", + "ACTIVITY_TYPE_VERIFY_OTP", + "ACTIVITY_TYPE_OTP_LOGIN", + "ACTIVITY_TYPE_STAMP_LOGIN", + "ACTIVITY_TYPE_OAUTH_LOGIN", + "ACTIVITY_TYPE_UPDATE_USER_NAME", + "ACTIVITY_TYPE_UPDATE_USER_EMAIL", + "ACTIVITY_TYPE_UPDATE_USER_PHONE_NUMBER", + "ACTIVITY_TYPE_INIT_FIAT_ON_RAMP", + "ACTIVITY_TYPE_CREATE_SMART_CONTRACT_INTERFACE", + "ACTIVITY_TYPE_DELETE_SMART_CONTRACT_INTERFACE", + "ACTIVITY_TYPE_ENABLE_AUTH_PROXY", + "ACTIVITY_TYPE_DISABLE_AUTH_PROXY", + "ACTIVITY_TYPE_UPDATE_AUTH_PROXY_CONFIG" + ] + }, + "v1AddressFormat": { + "type": "string", + "enum": [ + "ADDRESS_FORMAT_UNCOMPRESSED", + "ADDRESS_FORMAT_COMPRESSED", + "ADDRESS_FORMAT_ETHEREUM", + "ADDRESS_FORMAT_SOLANA", + "ADDRESS_FORMAT_COSMOS", + "ADDRESS_FORMAT_TRON", + "ADDRESS_FORMAT_SUI", + "ADDRESS_FORMAT_APTOS", + "ADDRESS_FORMAT_BITCOIN_MAINNET_P2PKH", + "ADDRESS_FORMAT_BITCOIN_MAINNET_P2SH", + "ADDRESS_FORMAT_BITCOIN_MAINNET_P2WPKH", + "ADDRESS_FORMAT_BITCOIN_MAINNET_P2WSH", + "ADDRESS_FORMAT_BITCOIN_MAINNET_P2TR", + "ADDRESS_FORMAT_BITCOIN_TESTNET_P2PKH", + "ADDRESS_FORMAT_BITCOIN_TESTNET_P2SH", + "ADDRESS_FORMAT_BITCOIN_TESTNET_P2WPKH", + "ADDRESS_FORMAT_BITCOIN_TESTNET_P2WSH", + "ADDRESS_FORMAT_BITCOIN_TESTNET_P2TR", + "ADDRESS_FORMAT_BITCOIN_SIGNET_P2PKH", + "ADDRESS_FORMAT_BITCOIN_SIGNET_P2SH", + "ADDRESS_FORMAT_BITCOIN_SIGNET_P2WPKH", + "ADDRESS_FORMAT_BITCOIN_SIGNET_P2WSH", + "ADDRESS_FORMAT_BITCOIN_SIGNET_P2TR", + "ADDRESS_FORMAT_BITCOIN_REGTEST_P2PKH", + "ADDRESS_FORMAT_BITCOIN_REGTEST_P2SH", + "ADDRESS_FORMAT_BITCOIN_REGTEST_P2WPKH", + "ADDRESS_FORMAT_BITCOIN_REGTEST_P2WSH", + "ADDRESS_FORMAT_BITCOIN_REGTEST_P2TR", + "ADDRESS_FORMAT_SEI", + "ADDRESS_FORMAT_XLM", + "ADDRESS_FORMAT_DOGE_MAINNET", + "ADDRESS_FORMAT_DOGE_TESTNET", + "ADDRESS_FORMAT_TON_V3R2", + "ADDRESS_FORMAT_TON_V4R2", + "ADDRESS_FORMAT_TON_V5R1", + "ADDRESS_FORMAT_XRP" + ] + }, + "v1ApiKey": { + "type": "object", + "properties": { + "credential": { + "$ref": "#/definitions/externaldatav1Credential", + "description": "A User credential that can be used to authenticate to Turnkey." + }, + "apiKeyId": { + "type": "string", + "description": "Unique identifier for a given API Key." + }, + "apiKeyName": { + "type": "string", + "description": "Human-readable name for an API Key." + }, + "createdAt": { + "$ref": "#/definitions/externaldatav1Timestamp" + }, + "updatedAt": { + "$ref": "#/definitions/externaldatav1Timestamp" + }, + "expirationSeconds": { + "type": "string", + "format": "uint64", + "description": "Optional window (in seconds) indicating how long the API Key should last." + } + }, + "required": [ + "credential", + "apiKeyId", + "apiKeyName", + "createdAt", + "updatedAt" + ] + }, + "v1ApiKeyCurve": { + "type": "string", + "enum": [ + "API_KEY_CURVE_P256", + "API_KEY_CURVE_SECP256K1", + "API_KEY_CURVE_ED25519" + ] + }, + "v1ApiKeyParamsV2": { + "type": "object", + "properties": { + "apiKeyName": { + "type": "string", + "description": "Human-readable name for an API Key." + }, + "publicKey": { + "type": "string", + "description": "The public component of a cryptographic key pair used to sign messages and transactions." + }, + "curveType": { + "$ref": "#/definitions/v1ApiKeyCurve", + "description": "The curve type to be used for processing API key signatures." + }, + "expirationSeconds": { + "type": "string", + "description": "Optional window (in seconds) indicating how long the API Key should last." + } + }, + "required": ["apiKeyName", "publicKey", "curveType"] + }, + "v1ApiOnlyUserParams": { + "type": "object", + "properties": { + "userName": { + "type": "string", + "description": "The name of the new API-only User." + }, + "userEmail": { + "type": "string", + "description": "The email address for this API-only User (optional)." + }, + "userTags": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of tags assigned to the new API-only User. This field, if not needed, should be an empty array in your request body." + }, + "apiKeys": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/apiApiKeyParams" + }, + "description": "A list of API Key parameters. This field, if not needed, should be an empty array in your request body." + } + }, + "required": ["userName", "userTags", "apiKeys"] + }, + "v1ApproveActivityIntent": { + "type": "object", + "properties": { + "fingerprint": { + "type": "string", + "description": "An artifact verifying a User's action." + } + }, + "required": ["fingerprint"] + }, + "v1ApproveActivityRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_APPROVE_ACTIVITY"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1ApproveActivityIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1Attestation": { + "type": "object", + "properties": { + "credentialId": { + "type": "string", + "description": "The cbor encoded then base64 url encoded id of the credential." + }, + "clientDataJson": { + "type": "string", + "description": "A base64 url encoded payload containing metadata about the signing context and the challenge." + }, + "attestationObject": { + "type": "string", + "description": "A base64 url encoded payload containing authenticator data and any attestation the webauthn provider chooses." + }, + "transports": { + "type": "array", + "items": { + "$ref": "#/definitions/v1AuthenticatorTransport" + }, + "description": "The type of authenticator transports." + } + }, + "required": [ + "credentialId", + "clientDataJson", + "attestationObject", + "transports" + ] + }, + "v1Authenticator": { + "type": "object", + "properties": { + "transports": { + "type": "array", + "items": { + "$ref": "#/definitions/v1AuthenticatorTransport" + }, + "description": "Types of transports that may be used by an Authenticator (e.g., USB, NFC, BLE)." + }, + "attestationType": { + "type": "string" + }, + "aaguid": { + "type": "string", + "description": "Identifier indicating the type of the Security Key." + }, + "credentialId": { + "type": "string", + "description": "Unique identifier for a WebAuthn credential." + }, + "model": { + "type": "string", + "description": "The type of Authenticator device." + }, + "credential": { + "$ref": "#/definitions/externaldatav1Credential", + "description": "A User credential that can be used to authenticate to Turnkey." + }, + "authenticatorId": { + "type": "string", + "description": "Unique identifier for a given Authenticator." + }, + "authenticatorName": { + "type": "string", + "description": "Human-readable name for an Authenticator." + }, + "createdAt": { + "$ref": "#/definitions/externaldatav1Timestamp" + }, + "updatedAt": { + "$ref": "#/definitions/externaldatav1Timestamp" + } + }, + "required": [ + "transports", + "attestationType", + "aaguid", + "credentialId", + "model", + "credential", + "authenticatorId", + "authenticatorName", + "createdAt", + "updatedAt" + ] + }, + "v1AuthenticatorAttestationResponse": { + "type": "object", + "properties": { + "clientDataJson": { + "type": "string" + }, + "attestationObject": { + "type": "string" + }, + "transports": { + "type": "array", + "items": { + "$ref": "#/definitions/v1AuthenticatorTransport" + } + }, + "authenticatorAttachment": { + "type": "string", + "enum": ["cross-platform", "platform"], + "x-nullable": true + } + }, + "required": ["clientDataJson", "attestationObject"] + }, + "v1AuthenticatorParams": { + "type": "object", + "properties": { + "authenticatorName": { + "type": "string", + "description": "Human-readable name for an Authenticator." + }, + "userId": { + "type": "string", + "description": "Unique identifier for a given User." + }, + "attestation": { + "$ref": "#/definitions/v1PublicKeyCredentialWithAttestation" + }, + "challenge": { + "type": "string", + "description": "Challenge presented for authentication purposes." + } + }, + "required": ["authenticatorName", "userId", "attestation", "challenge"] + }, + "v1AuthenticatorParamsV2": { + "type": "object", + "properties": { + "authenticatorName": { + "type": "string", + "description": "Human-readable name for an Authenticator." + }, + "challenge": { + "type": "string", + "description": "Challenge presented for authentication purposes." + }, + "attestation": { + "$ref": "#/definitions/v1Attestation", + "description": "The attestation that proves custody of the authenticator and provides metadata about it." + } + }, + "required": ["authenticatorName", "challenge", "attestation"] + }, + "v1AuthenticatorTransport": { + "type": "string", + "enum": [ + "AUTHENTICATOR_TRANSPORT_BLE", + "AUTHENTICATOR_TRANSPORT_INTERNAL", + "AUTHENTICATOR_TRANSPORT_NFC", + "AUTHENTICATOR_TRANSPORT_USB", + "AUTHENTICATOR_TRANSPORT_HYBRID" + ] + }, + "v1Config": { + "type": "object", + "properties": { + "features": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1Feature" + } + }, + "quorum": { + "$ref": "#/definitions/externaldatav1Quorum" + } + } + }, + "v1CreateApiKeysIntent": { + "type": "object", + "properties": { + "apiKeys": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/apiApiKeyParams" + }, + "description": "A list of API Keys." + }, + "userId": { + "type": "string", + "description": "Unique identifier for a given User." + } + }, + "required": ["apiKeys", "userId"] + }, + "v1CreateApiKeysIntentV2": { + "type": "object", + "properties": { + "apiKeys": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1ApiKeyParamsV2" + }, + "description": "A list of API Keys." + }, + "userId": { + "type": "string", + "description": "Unique identifier for a given User." + } + }, + "required": ["apiKeys", "userId"] + }, + "v1CreateApiKeysRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_CREATE_API_KEYS_V2"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1CreateApiKeysIntentV2" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1CreateApiKeysResult": { + "type": "object", + "properties": { + "apiKeyIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of API Key IDs." + } + }, + "required": ["apiKeyIds"] + }, + "v1CreateApiOnlyUsersIntent": { + "type": "object", + "properties": { + "apiOnlyUsers": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1ApiOnlyUserParams" + }, + "description": "A list of API-only Users to create." + } + }, + "required": ["apiOnlyUsers"] + }, + "v1CreateApiOnlyUsersRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_CREATE_API_ONLY_USERS"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1CreateApiOnlyUsersIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1CreateApiOnlyUsersResult": { + "type": "object", + "properties": { + "userIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of API-only User IDs." + } + }, + "required": ["userIds"] + }, + "v1CreateAuthenticatorsIntent": { + "type": "object", + "properties": { + "authenticators": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1AuthenticatorParams" + }, + "description": "A list of Authenticators." + }, + "userId": { + "type": "string", + "description": "Unique identifier for a given User." + } + }, + "required": ["authenticators", "userId"] + }, + "v1CreateAuthenticatorsIntentV2": { + "type": "object", + "properties": { + "authenticators": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1AuthenticatorParamsV2" + }, + "description": "A list of Authenticators." + }, + "userId": { + "type": "string", + "description": "Unique identifier for a given User." + } + }, + "required": ["authenticators", "userId"] + }, + "v1CreateAuthenticatorsRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_CREATE_AUTHENTICATORS_V2"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1CreateAuthenticatorsIntentV2" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1CreateAuthenticatorsResult": { + "type": "object", + "properties": { + "authenticatorIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of Authenticator IDs." + } + }, + "required": ["authenticatorIds"] + }, + "v1CreateInvitationsIntent": { + "type": "object", + "properties": { + "invitations": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1InvitationParams" + }, + "description": "A list of Invitations." + } + }, + "required": ["invitations"] + }, + "v1CreateInvitationsRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_CREATE_INVITATIONS"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1CreateInvitationsIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1CreateInvitationsResult": { + "type": "object", + "properties": { + "invitationIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of Invitation IDs" + } + }, + "required": ["invitationIds"] + }, + "v1CreateOauthProvidersIntent": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "The ID of the User to add an Oauth provider to" + }, + "oauthProviders": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1OauthProviderParams" + }, + "description": "A list of Oauth providers." + } + }, + "required": ["userId", "oauthProviders"] + }, + "v1CreateOauthProvidersRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_CREATE_OAUTH_PROVIDERS"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1CreateOauthProvidersIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1CreateOauthProvidersResult": { + "type": "object", + "properties": { + "providerIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of unique identifiers for Oauth Providers" + } + }, + "required": ["providerIds"] + }, + "v1CreateOrganizationIntent": { + "type": "object", + "properties": { + "organizationName": { + "type": "string", + "description": "Human-readable name for an Organization." + }, + "rootEmail": { + "type": "string", + "description": "The root user's email address." + }, + "rootAuthenticator": { + "$ref": "#/definitions/v1AuthenticatorParams", + "description": "The root user's Authenticator." + }, + "rootUserId": { + "type": "string", + "description": "Unique identifier for the root user object." + } + }, + "required": ["organizationName", "rootEmail", "rootAuthenticator"] + }, + "v1CreateOrganizationIntentV2": { + "type": "object", + "properties": { + "organizationName": { + "type": "string", + "description": "Human-readable name for an Organization." + }, + "rootEmail": { + "type": "string", + "description": "The root user's email address." + }, + "rootAuthenticator": { + "$ref": "#/definitions/v1AuthenticatorParamsV2", + "description": "The root user's Authenticator." + }, + "rootUserId": { + "type": "string", + "description": "Unique identifier for the root user object." + } + }, + "required": ["organizationName", "rootEmail", "rootAuthenticator"] + }, + "v1CreateOrganizationResult": { + "type": "object", + "properties": { + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + } + }, + "required": ["organizationId"] + }, + "v1CreatePoliciesIntent": { + "type": "object", + "properties": { + "policies": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1CreatePolicyIntentV3" + }, + "description": "An array of policy intents to be created." + } + }, + "required": ["policies"] + }, + "v1CreatePoliciesRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_CREATE_POLICIES"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1CreatePoliciesIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1CreatePoliciesResult": { + "type": "object", + "properties": { + "policyIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of unique identifiers for the created policies." + } + }, + "required": ["policyIds"] + }, + "v1CreatePolicyIntent": { + "type": "object", + "properties": { + "policyName": { + "type": "string", + "description": "Human-readable name for a Policy." + }, + "selectors": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1Selector" + }, + "description": "A list of simple functions each including a subject, target and boolean. See Policy Engine Language section for additional details." + }, + "effect": { + "$ref": "#/definitions/v1Effect", + "description": "The instruction to DENY or ALLOW a particular activity following policy selector(s)." + }, + "notes": { + "type": "string" + } + }, + "required": ["policyName", "selectors", "effect"] + }, + "v1CreatePolicyIntentV2": { + "type": "object", + "properties": { + "policyName": { + "type": "string", + "description": "Human-readable name for a Policy." + }, + "selectors": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1SelectorV2" + }, + "description": "A list of simple functions each including a subject, target and boolean. See Policy Engine Language section for additional details." + }, + "effect": { + "$ref": "#/definitions/v1Effect", + "description": "Whether to ALLOW or DENY requests that match the condition and consensus requirements." + }, + "notes": { + "type": "string" + } + }, + "required": ["policyName", "selectors", "effect"] + }, + "v1CreatePolicyIntentV3": { + "type": "object", + "properties": { + "policyName": { + "type": "string", + "description": "Human-readable name for a Policy." + }, + "effect": { + "$ref": "#/definitions/v1Effect", + "description": "The instruction to DENY or ALLOW an activity." + }, + "condition": { + "type": "string", + "description": "The condition expression that triggers the Effect" + }, + "consensus": { + "type": "string", + "description": "The consensus expression that triggers the Effect" + }, + "notes": { + "type": "string" + } + }, + "required": ["policyName", "effect"] + }, + "v1CreatePolicyRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_CREATE_POLICY_V3"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1CreatePolicyIntentV3" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1CreatePolicyResult": { + "type": "object", + "properties": { + "policyId": { + "type": "string", + "description": "Unique identifier for a given Policy." + } + }, + "required": ["policyId"] + }, + "v1CreatePrivateKeyTagIntent": { + "type": "object", + "properties": { + "privateKeyTagName": { + "type": "string", + "description": "Human-readable name for a Private Key Tag." + }, + "privateKeyIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of Private Key IDs." + } + }, + "required": ["privateKeyTagName", "privateKeyIds"] + }, + "v1CreatePrivateKeyTagRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_CREATE_PRIVATE_KEY_TAG"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1CreatePrivateKeyTagIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1CreatePrivateKeyTagResult": { + "type": "object", + "properties": { + "privateKeyTagId": { + "type": "string", + "description": "Unique identifier for a given Private Key Tag." + }, + "privateKeyIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of Private Key IDs." + } + }, + "required": ["privateKeyTagId", "privateKeyIds"] + }, + "v1CreatePrivateKeysIntent": { + "type": "object", + "properties": { + "privateKeys": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1PrivateKeyParams" + }, + "description": "A list of Private Keys." + } + }, + "required": ["privateKeys"] + }, + "v1CreatePrivateKeysIntentV2": { + "type": "object", + "properties": { + "privateKeys": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1PrivateKeyParams" + }, + "description": "A list of Private Keys." + } + }, + "required": ["privateKeys"] + }, + "v1CreatePrivateKeysRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_CREATE_PRIVATE_KEYS_V2"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1CreatePrivateKeysIntentV2" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1CreatePrivateKeysResult": { + "type": "object", + "properties": { + "privateKeyIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of Private Key IDs." + } + }, + "required": ["privateKeyIds"] + }, + "v1CreatePrivateKeysResultV2": { + "type": "object", + "properties": { + "privateKeys": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1PrivateKeyResult" + }, + "description": "A list of Private Key IDs and addresses." + } + }, + "required": ["privateKeys"] + }, + "v1CreateReadOnlySessionIntent": { + "type": "object" + }, + "v1CreateReadOnlySessionRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_CREATE_READ_ONLY_SESSION"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1CreateReadOnlySessionIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1CreateReadOnlySessionResult": { + "type": "object", + "properties": { + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization. If the request is being made by a user and their Sub-Organization ID is unknown, this can be the Parent Organization ID. However, using the Sub-Organization ID is preferred due to performance reasons." + }, + "organizationName": { + "type": "string", + "description": "Human-readable name for an Organization." + }, + "userId": { + "type": "string", + "description": "Unique identifier for a given User." + }, + "username": { + "type": "string", + "description": "Human-readable name for a User." + }, + "session": { + "type": "string", + "description": "String representing a read only session" + }, + "sessionExpiry": { + "type": "string", + "format": "uint64", + "description": "UTC timestamp in seconds representing the expiry time for the read only session." + } + }, + "required": [ + "organizationId", + "organizationName", + "userId", + "username", + "session", + "sessionExpiry" + ] + }, + "v1CreateReadWriteSessionIntent": { + "type": "object", + "properties": { + "targetPublicKey": { + "type": "string", + "description": "Client-side public key generated by the user, to which the read write session bundle (credentials) will be encrypted." + }, + "email": { + "type": "string", + "description": "Email of the user to create a read write session for" + }, + "apiKeyName": { + "type": "string", + "description": "Optional human-readable name for an API Key. If none provided, default to Read Write Session - \u003cTimestamp\u003e" + }, + "expirationSeconds": { + "type": "string", + "description": "Expiration window (in seconds) indicating how long the API key is valid for. If not provided, a default of 15 minutes will be used." + } + }, + "required": ["targetPublicKey", "email"] + }, + "v1CreateReadWriteSessionIntentV2": { + "type": "object", + "properties": { + "targetPublicKey": { + "type": "string", + "description": "Client-side public key generated by the user, to which the read write session bundle (credentials) will be encrypted." + }, + "userId": { + "type": "string", + "description": "Unique identifier for a given User." + }, + "apiKeyName": { + "type": "string", + "description": "Optional human-readable name for an API Key. If none provided, default to Read Write Session - \u003cTimestamp\u003e" + }, + "expirationSeconds": { + "type": "string", + "description": "Expiration window (in seconds) indicating how long the API key is valid for. If not provided, a default of 15 minutes will be used." + }, + "invalidateExisting": { + "type": "boolean", + "description": "Invalidate all other previously generated ReadWriteSession API keys" + } + }, + "required": ["targetPublicKey"] + }, + "v1CreateReadWriteSessionRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_CREATE_READ_WRITE_SESSION_V2"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1CreateReadWriteSessionIntentV2" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1CreateReadWriteSessionResult": { + "type": "object", + "properties": { + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization. If the request is being made by a user and their Sub-Organization ID is unknown, this can be the Parent Organization ID. However, using the Sub-Organization ID is preferred due to performance reasons." + }, + "organizationName": { + "type": "string", + "description": "Human-readable name for an Organization." + }, + "userId": { + "type": "string", + "description": "Unique identifier for a given User." + }, + "username": { + "type": "string", + "description": "Human-readable name for a User." + }, + "apiKeyId": { + "type": "string", + "description": "Unique identifier for the created API key." + }, + "credentialBundle": { + "type": "string", + "description": "HPKE encrypted credential bundle" + } + }, + "required": [ + "organizationId", + "organizationName", + "userId", + "username", + "apiKeyId", + "credentialBundle" + ] + }, + "v1CreateReadWriteSessionResultV2": { + "type": "object", + "properties": { + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization. If the request is being made by a user and their Sub-Organization ID is unknown, this can be the Parent Organization ID. However, using the Sub-Organization ID is preferred due to performance reasons." + }, + "organizationName": { + "type": "string", + "description": "Human-readable name for an Organization." + }, + "userId": { + "type": "string", + "description": "Unique identifier for a given User." + }, + "username": { + "type": "string", + "description": "Human-readable name for a User." + }, + "apiKeyId": { + "type": "string", + "description": "Unique identifier for the created API key." + }, + "credentialBundle": { + "type": "string", + "description": "HPKE encrypted credential bundle" + } + }, + "required": [ + "organizationId", + "organizationName", + "userId", + "username", + "apiKeyId", + "credentialBundle" + ] + }, + "v1CreateSmartContractInterfaceIntent": { + "type": "object", + "properties": { + "smartContractAddress": { + "type": "string", + "description": "Corresponding contract address or program ID" + }, + "smartContractInterface": { + "type": "string", + "description": "ABI/IDL as a JSON string" + }, + "type": { + "$ref": "#/definitions/v1SmartContractInterfaceType" + }, + "label": { + "type": "string", + "description": "Human-readable name for a Smart Contract Interface." + }, + "notes": { + "type": "string", + "description": "Notes for a Smart Contract Interface." + } + }, + "required": [ + "smartContractAddress", + "smartContractInterface", + "type", + "label" + ] + }, + "v1CreateSmartContractInterfaceRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_CREATE_SMART_CONTRACT_INTERFACE"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1CreateSmartContractInterfaceIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1CreateSmartContractInterfaceResult": { + "type": "object", + "properties": { + "smartContractInterfaceId": { + "type": "string", + "description": "The ID of the created Smart Contract Interface." + } + }, + "required": ["smartContractInterfaceId"] + }, + "v1CreateSubOrganizationIntent": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name for this sub-organization" + }, + "rootAuthenticator": { + "$ref": "#/definitions/v1AuthenticatorParamsV2", + "description": "Root User authenticator for this new sub-organization" + } + }, + "required": ["name", "rootAuthenticator"] + }, + "v1CreateSubOrganizationIntentV2": { + "type": "object", + "properties": { + "subOrganizationName": { + "type": "string", + "description": "Name for this sub-organization" + }, + "rootUsers": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1RootUserParams" + }, + "description": "Root users to create within this sub-organization" + }, + "rootQuorumThreshold": { + "type": "integer", + "format": "int32", + "description": "The threshold of unique approvals to reach root quorum. This value must be less than or equal to the number of root users" + } + }, + "required": ["subOrganizationName", "rootUsers", "rootQuorumThreshold"] + }, + "v1CreateSubOrganizationIntentV3": { + "type": "object", + "properties": { + "subOrganizationName": { + "type": "string", + "description": "Name for this sub-organization" + }, + "rootUsers": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1RootUserParams" + }, + "description": "Root users to create within this sub-organization" + }, + "rootQuorumThreshold": { + "type": "integer", + "format": "int32", + "description": "The threshold of unique approvals to reach root quorum. This value must be less than or equal to the number of root users" + }, + "privateKeys": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1PrivateKeyParams" + }, + "description": "A list of Private Keys." + } + }, + "required": [ + "subOrganizationName", + "rootUsers", + "rootQuorumThreshold", + "privateKeys" + ] + }, + "v1CreateSubOrganizationIntentV4": { + "type": "object", + "properties": { + "subOrganizationName": { + "type": "string", + "description": "Name for this sub-organization" + }, + "rootUsers": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1RootUserParams" + }, + "description": "Root users to create within this sub-organization" + }, + "rootQuorumThreshold": { + "type": "integer", + "format": "int32", + "description": "The threshold of unique approvals to reach root quorum. This value must be less than or equal to the number of root users" + }, + "wallet": { + "$ref": "#/definitions/v1WalletParams", + "description": "The wallet to create for the sub-organization" + }, + "disableEmailRecovery": { + "type": "boolean", + "description": "Disable email recovery for the sub-organization" + }, + "disableEmailAuth": { + "type": "boolean", + "description": "Disable email auth for the sub-organization" + } + }, + "required": ["subOrganizationName", "rootUsers", "rootQuorumThreshold"] + }, + "v1CreateSubOrganizationIntentV5": { + "type": "object", + "properties": { + "subOrganizationName": { + "type": "string", + "description": "Name for this sub-organization" + }, + "rootUsers": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1RootUserParamsV2" + }, + "description": "Root users to create within this sub-organization" + }, + "rootQuorumThreshold": { + "type": "integer", + "format": "int32", + "description": "The threshold of unique approvals to reach root quorum. This value must be less than or equal to the number of root users" + }, + "wallet": { + "$ref": "#/definitions/v1WalletParams", + "description": "The wallet to create for the sub-organization" + }, + "disableEmailRecovery": { + "type": "boolean", + "description": "Disable email recovery for the sub-organization" + }, + "disableEmailAuth": { + "type": "boolean", + "description": "Disable email auth for the sub-organization" + } + }, + "required": ["subOrganizationName", "rootUsers", "rootQuorumThreshold"] + }, + "v1CreateSubOrganizationIntentV6": { + "type": "object", + "properties": { + "subOrganizationName": { + "type": "string", + "description": "Name for this sub-organization" + }, + "rootUsers": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1RootUserParamsV3" + }, + "description": "Root users to create within this sub-organization" + }, + "rootQuorumThreshold": { + "type": "integer", + "format": "int32", + "description": "The threshold of unique approvals to reach root quorum. This value must be less than or equal to the number of root users" + }, + "wallet": { + "$ref": "#/definitions/v1WalletParams", + "description": "The wallet to create for the sub-organization" + }, + "disableEmailRecovery": { + "type": "boolean", + "description": "Disable email recovery for the sub-organization" + }, + "disableEmailAuth": { + "type": "boolean", + "description": "Disable email auth for the sub-organization" + } + }, + "required": ["subOrganizationName", "rootUsers", "rootQuorumThreshold"] + }, + "v1CreateSubOrganizationIntentV7": { + "type": "object", + "properties": { + "subOrganizationName": { + "type": "string", + "description": "Name for this sub-organization" + }, + "rootUsers": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1RootUserParamsV4" + }, + "description": "Root users to create within this sub-organization" + }, + "rootQuorumThreshold": { + "type": "integer", + "format": "int32", + "description": "The threshold of unique approvals to reach root quorum. This value must be less than or equal to the number of root users" + }, + "wallet": { + "$ref": "#/definitions/v1WalletParams", + "description": "The wallet to create for the sub-organization" + }, + "disableEmailRecovery": { + "type": "boolean", + "description": "Disable email recovery for the sub-organization" + }, + "disableEmailAuth": { + "type": "boolean", + "description": "Disable email auth for the sub-organization" + }, + "disableSmsAuth": { + "type": "boolean", + "description": "Disable OTP SMS auth for the sub-organization" + }, + "disableOtpEmailAuth": { + "type": "boolean", + "description": "Disable OTP email auth for the sub-organization" + }, + "verificationToken": { + "type": "string", + "description": "Signed JWT containing a unique id, expiry, verification type, contact" + } + }, + "required": ["subOrganizationName", "rootUsers", "rootQuorumThreshold"] + }, + "v1CreateSubOrganizationRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_CREATE_SUB_ORGANIZATION_V7"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1CreateSubOrganizationIntentV7" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1CreateSubOrganizationResult": { + "type": "object", + "properties": { + "subOrganizationId": { + "type": "string" + }, + "rootUserIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": ["subOrganizationId"] + }, + "v1CreateSubOrganizationResultV3": { + "type": "object", + "properties": { + "subOrganizationId": { + "type": "string" + }, + "privateKeys": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1PrivateKeyResult" + }, + "description": "A list of Private Key IDs and addresses." + }, + "rootUserIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": ["subOrganizationId", "privateKeys"] + }, + "v1CreateSubOrganizationResultV4": { + "type": "object", + "properties": { + "subOrganizationId": { + "type": "string" + }, + "wallet": { + "$ref": "#/definitions/v1WalletResult" + }, + "rootUserIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": ["subOrganizationId"] + }, + "v1CreateSubOrganizationResultV5": { + "type": "object", + "properties": { + "subOrganizationId": { + "type": "string" + }, + "wallet": { + "$ref": "#/definitions/v1WalletResult" + }, + "rootUserIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": ["subOrganizationId"] + }, + "v1CreateSubOrganizationResultV6": { + "type": "object", + "properties": { + "subOrganizationId": { + "type": "string" + }, + "wallet": { + "$ref": "#/definitions/v1WalletResult" + }, + "rootUserIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": ["subOrganizationId"] + }, + "v1CreateSubOrganizationResultV7": { + "type": "object", + "properties": { + "subOrganizationId": { + "type": "string" + }, + "wallet": { + "$ref": "#/definitions/v1WalletResult" + }, + "rootUserIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": ["subOrganizationId"] + }, + "v1CreateUserTagIntent": { + "type": "object", + "properties": { + "userTagName": { + "type": "string", + "description": "Human-readable name for a User Tag." + }, + "userIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of User IDs." + } + }, + "required": ["userTagName", "userIds"] + }, + "v1CreateUserTagRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_CREATE_USER_TAG"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1CreateUserTagIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1CreateUserTagResult": { + "type": "object", + "properties": { + "userTagId": { + "type": "string", + "description": "Unique identifier for a given User Tag." + }, + "userIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of User IDs." + } + }, + "required": ["userTagId", "userIds"] + }, + "v1CreateUsersIntent": { + "type": "object", + "properties": { + "users": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1UserParams" + }, + "description": "A list of Users." + } + }, + "required": ["users"] + }, + "v1CreateUsersIntentV2": { + "type": "object", + "properties": { + "users": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1UserParamsV2" + }, + "description": "A list of Users." + } + }, + "required": ["users"] + }, + "v1CreateUsersIntentV3": { + "type": "object", + "properties": { + "users": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1UserParamsV3" + }, + "description": "A list of Users." + } + }, + "required": ["users"] + }, + "v1CreateUsersRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_CREATE_USERS_V3"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1CreateUsersIntentV3" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1CreateUsersResult": { + "type": "object", + "properties": { + "userIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of User IDs." + } + }, + "required": ["userIds"] + }, + "v1CreateWalletAccountsIntent": { + "type": "object", + "properties": { + "walletId": { + "type": "string", + "description": "Unique identifier for a given Wallet." + }, + "accounts": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1WalletAccountParams" + }, + "description": "A list of wallet Accounts." + } + }, + "required": ["walletId", "accounts"] + }, + "v1CreateWalletAccountsRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_CREATE_WALLET_ACCOUNTS"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1CreateWalletAccountsIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1CreateWalletAccountsResult": { + "type": "object", + "properties": { + "addresses": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of derived addresses." + } + }, + "required": ["addresses"] + }, + "v1CreateWalletIntent": { + "type": "object", + "properties": { + "walletName": { + "type": "string", + "description": "Human-readable name for a Wallet." + }, + "accounts": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1WalletAccountParams" + }, + "description": "A list of wallet Accounts. This field, if not needed, should be an empty array in your request body." + }, + "mnemonicLength": { + "type": "integer", + "format": "int32", + "description": "Length of mnemonic to generate the Wallet seed. Defaults to 12. Accepted values: 12, 15, 18, 21, 24." + } + }, + "required": ["walletName", "accounts"] + }, + "v1CreateWalletRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_CREATE_WALLET"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1CreateWalletIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1CreateWalletResult": { + "type": "object", + "properties": { + "walletId": { + "type": "string", + "description": "Unique identifier for a Wallet." + }, + "addresses": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of account addresses." + } + }, + "required": ["walletId", "addresses"] + }, + "v1CredPropsAuthenticationExtensionsClientOutputs": { + "type": "object", + "properties": { + "rk": { + "type": "boolean" + } + }, + "required": ["rk"] + }, + "v1CredentialType": { + "type": "string", + "enum": [ + "CREDENTIAL_TYPE_WEBAUTHN_AUTHENTICATOR", + "CREDENTIAL_TYPE_API_KEY_P256", + "CREDENTIAL_TYPE_RECOVER_USER_KEY_P256", + "CREDENTIAL_TYPE_API_KEY_SECP256K1", + "CREDENTIAL_TYPE_EMAIL_AUTH_KEY_P256", + "CREDENTIAL_TYPE_API_KEY_ED25519", + "CREDENTIAL_TYPE_OTP_AUTH_KEY_P256", + "CREDENTIAL_TYPE_READ_WRITE_SESSION_KEY_P256", + "CREDENTIAL_TYPE_OAUTH_KEY_P256", + "CREDENTIAL_TYPE_LOGIN" + ] + }, + "v1Curve": { + "type": "string", + "enum": ["CURVE_SECP256K1", "CURVE_ED25519"] + }, + "v1DeleteApiKeysIntent": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "Unique identifier for a given User." + }, + "apiKeyIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of API Key IDs." + } + }, + "required": ["userId", "apiKeyIds"] + }, + "v1DeleteApiKeysRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_DELETE_API_KEYS"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1DeleteApiKeysIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1DeleteApiKeysResult": { + "type": "object", + "properties": { + "apiKeyIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of API Key IDs." + } + }, + "required": ["apiKeyIds"] + }, + "v1DeleteAuthenticatorsIntent": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "Unique identifier for a given User." + }, + "authenticatorIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of Authenticator IDs." + } + }, + "required": ["userId", "authenticatorIds"] + }, + "v1DeleteAuthenticatorsRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_DELETE_AUTHENTICATORS"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1DeleteAuthenticatorsIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1DeleteAuthenticatorsResult": { + "type": "object", + "properties": { + "authenticatorIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Unique identifier for a given Authenticator." + } + }, + "required": ["authenticatorIds"] + }, + "v1DeleteInvitationIntent": { + "type": "object", + "properties": { + "invitationId": { + "type": "string", + "description": "Unique identifier for a given Invitation object." + } + }, + "required": ["invitationId"] + }, + "v1DeleteInvitationRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_DELETE_INVITATION"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1DeleteInvitationIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1DeleteInvitationResult": { + "type": "object", + "properties": { + "invitationId": { + "type": "string", + "description": "Unique identifier for a given Invitation." + } + }, + "required": ["invitationId"] + }, + "v1DeleteOauthProvidersIntent": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "The ID of the User to remove an Oauth provider from" + }, + "providerIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Unique identifier for a given Provider." + } + }, + "required": ["userId", "providerIds"] + }, + "v1DeleteOauthProvidersRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_DELETE_OAUTH_PROVIDERS"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1DeleteOauthProvidersIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1DeleteOauthProvidersResult": { + "type": "object", + "properties": { + "providerIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of unique identifiers for Oauth Providers" + } + }, + "required": ["providerIds"] + }, + "v1DeleteOrganizationIntent": { + "type": "object", + "properties": { + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + } + }, + "required": ["organizationId"] + }, + "v1DeleteOrganizationResult": { + "type": "object", + "properties": { + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + } + }, + "required": ["organizationId"] + }, + "v1DeletePolicyIntent": { + "type": "object", + "properties": { + "policyId": { + "type": "string", + "description": "Unique identifier for a given Policy." + } + }, + "required": ["policyId"] + }, + "v1DeletePolicyRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_DELETE_POLICY"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1DeletePolicyIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1DeletePolicyResult": { + "type": "object", + "properties": { + "policyId": { + "type": "string", + "description": "Unique identifier for a given Policy." + } + }, + "required": ["policyId"] + }, + "v1DeletePrivateKeyTagsIntent": { + "type": "object", + "properties": { + "privateKeyTagIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of Private Key Tag IDs." + } + }, + "required": ["privateKeyTagIds"] + }, + "v1DeletePrivateKeyTagsRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_DELETE_PRIVATE_KEY_TAGS"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1DeletePrivateKeyTagsIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1DeletePrivateKeyTagsResult": { + "type": "object", + "properties": { + "privateKeyTagIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of Private Key Tag IDs." + }, + "privateKeyIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of Private Key IDs." + } + }, + "required": ["privateKeyTagIds", "privateKeyIds"] + }, + "v1DeletePrivateKeysIntent": { + "type": "object", + "properties": { + "privateKeyIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of unique identifiers for private keys within an organization" + }, + "deleteWithoutExport": { + "type": "boolean", + "description": "Optional parameter for deleting the private keys, even if any have not been previously exported. If they have been exported, this field is ignored." + } + }, + "required": ["privateKeyIds"] + }, + "v1DeletePrivateKeysRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_DELETE_PRIVATE_KEYS"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1DeletePrivateKeysIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1DeletePrivateKeysResult": { + "type": "object", + "properties": { + "privateKeyIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of private key unique identifiers that were removed" + } + }, + "required": ["privateKeyIds"] + }, + "v1DeleteSmartContractInterfaceIntent": { + "type": "object", + "properties": { + "smartContractInterfaceId": { + "type": "string", + "description": "The ID of a Smart Contract Interface intended for deletion." + } + }, + "required": ["smartContractInterfaceId"] + }, + "v1DeleteSmartContractInterfaceRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_DELETE_SMART_CONTRACT_INTERFACE"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1DeleteSmartContractInterfaceIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1DeleteSmartContractInterfaceResult": { + "type": "object", + "properties": { + "smartContractInterfaceId": { + "type": "string", + "description": "The ID of the deleted Smart Contract Interface." + } + }, + "required": ["smartContractInterfaceId"] + }, + "v1DeleteSubOrganizationIntent": { + "type": "object", + "properties": { + "deleteWithoutExport": { + "type": "boolean", + "description": "Sub-organization deletion, by default, requires associated wallets and private keys to be exported for security reasons. Set this boolean to true to force sub-organization deletion even if some wallets or private keys within it have not been exported yet. Default: false." + } + } + }, + "v1DeleteSubOrganizationRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_DELETE_SUB_ORGANIZATION"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1DeleteSubOrganizationIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1DeleteSubOrganizationResult": { + "type": "object", + "properties": { + "subOrganizationUuid": { + "type": "string", + "description": "Unique identifier of the sub organization that was removed" + } + }, + "required": ["subOrganizationUuid"] + }, + "v1DeleteUserTagsIntent": { + "type": "object", + "properties": { + "userTagIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of User Tag IDs." + } + }, + "required": ["userTagIds"] + }, + "v1DeleteUserTagsRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_DELETE_USER_TAGS"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1DeleteUserTagsIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1DeleteUserTagsResult": { + "type": "object", + "properties": { + "userTagIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of User Tag IDs." + }, + "userIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of User IDs." + } + }, + "required": ["userTagIds", "userIds"] + }, + "v1DeleteUsersIntent": { + "type": "object", + "properties": { + "userIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of User IDs." + } + }, + "required": ["userIds"] + }, + "v1DeleteUsersRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_DELETE_USERS"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1DeleteUsersIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1DeleteUsersResult": { + "type": "object", + "properties": { + "userIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of User IDs." + } + }, + "required": ["userIds"] + }, + "v1DeleteWalletsIntent": { + "type": "object", + "properties": { + "walletIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of unique identifiers for wallets within an organization" + }, + "deleteWithoutExport": { + "type": "boolean", + "description": "Optional parameter for deleting the wallets, even if any have not been previously exported. If they have been exported, this field is ignored." + } + }, + "required": ["walletIds"] + }, + "v1DeleteWalletsRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_DELETE_WALLETS"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1DeleteWalletsIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1DeleteWalletsResult": { + "type": "object", + "properties": { + "walletIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of wallet unique identifiers that were removed" + } + }, + "required": ["walletIds"] + }, + "v1DisableAuthProxyIntent": { + "type": "object" + }, + "v1DisableAuthProxyResult": { + "type": "object" + }, + "v1DisablePrivateKeyIntent": { + "type": "object", + "properties": { + "privateKeyId": { + "type": "string", + "description": "Unique identifier for a given Private Key." + } + }, + "required": ["privateKeyId"] + }, + "v1DisablePrivateKeyResult": { + "type": "object", + "properties": { + "privateKeyId": { + "type": "string", + "description": "Unique identifier for a given Private Key." + } + }, + "required": ["privateKeyId"] + }, + "v1Effect": { + "type": "string", + "enum": ["EFFECT_ALLOW", "EFFECT_DENY"] + }, + "v1EmailAuthIntent": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "Email of the authenticating user." + }, + "targetPublicKey": { + "type": "string", + "description": "Client-side public key generated by the user, to which the email auth bundle (credentials) will be encrypted." + }, + "apiKeyName": { + "type": "string", + "description": "Optional human-readable name for an API Key. If none provided, default to Email Auth - \u003cTimestamp\u003e" + }, + "expirationSeconds": { + "type": "string", + "description": "Expiration window (in seconds) indicating how long the API key is valid for. If not provided, a default of 15 minutes will be used." + }, + "emailCustomization": { + "$ref": "#/definitions/v1EmailCustomizationParams", + "description": "Optional parameters for customizing emails. If not provided, the default email will be used." + }, + "invalidateExisting": { + "type": "boolean", + "description": "Invalidate all other previously generated Email Auth API keys" + }, + "sendFromEmailAddress": { + "type": "string", + "description": "Optional custom email address from which to send the email" + }, + "sendFromEmailSenderName": { + "type": "string", + "description": "Optional custom sender name for use with sendFromEmailAddress; if left empty, will default to 'Notifications'" + }, + "replyToEmailAddress": { + "type": "string", + "description": "Optional custom email address to use as reply-to" + } + }, + "required": ["email", "targetPublicKey"] + }, + "v1EmailAuthIntentV2": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "Email of the authenticating user." + }, + "targetPublicKey": { + "type": "string", + "description": "Client-side public key generated by the user, to which the email auth bundle (credentials) will be encrypted." + }, + "apiKeyName": { + "type": "string", + "description": "Optional human-readable name for an API Key. If none provided, default to Email Auth - \u003cTimestamp\u003e" + }, + "expirationSeconds": { + "type": "string", + "description": "Expiration window (in seconds) indicating how long the API key is valid for. If not provided, a default of 15 minutes will be used." + }, + "emailCustomization": { + "$ref": "#/definitions/v1EmailCustomizationParams", + "description": "Optional parameters for customizing emails. If not provided, the default email will be used." + }, + "invalidateExisting": { + "type": "boolean", + "description": "Invalidate all other previously generated Email Auth API keys" + }, + "sendFromEmailAddress": { + "type": "string", + "description": "Optional custom email address from which to send the email" + }, + "sendFromEmailSenderName": { + "type": "string", + "description": "Optional custom sender name for use with sendFromEmailAddress; if left empty, will default to 'Notifications'" + }, + "replyToEmailAddress": { + "type": "string", + "description": "Optional custom email address to use as reply-to" + } + }, + "required": ["email", "targetPublicKey"] + }, + "v1EmailAuthRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_EMAIL_AUTH_V2"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1EmailAuthIntentV2" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1EmailAuthResult": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "Unique identifier for the authenticating User." + }, + "apiKeyId": { + "type": "string", + "description": "Unique identifier for the created API key." + } + }, + "required": ["userId", "apiKeyId"] + }, + "v1EmailCustomizationParams": { + "type": "object", + "properties": { + "appName": { + "type": "string", + "description": "The name of the application." + }, + "logoUrl": { + "type": "string", + "description": "A URL pointing to a logo in PNG format. Note this logo will be resized to fit into 340px x 124px." + }, + "magicLinkTemplate": { + "type": "string", + "description": "A template for the URL to be used in a magic link button, e.g. `https://dapp.xyz/%s`. The auth bundle will be interpolated into the `%s`." + }, + "templateVariables": { + "type": "string", + "description": "JSON object containing key/value pairs to be used with custom templates." + }, + "templateId": { + "type": "string", + "description": "Unique identifier for a given Email Template. If not specified, the default is the most recent Email Template." + } + } + }, + "v1EnableAuthProxyIntent": { + "type": "object" + }, + "v1EnableAuthProxyResult": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "A User ID with permission to initiate authentication." + } + }, + "required": ["userId"] + }, + "v1ExportPrivateKeyIntent": { + "type": "object", + "properties": { + "privateKeyId": { + "type": "string", + "description": "Unique identifier for a given Private Key." + }, + "targetPublicKey": { + "type": "string", + "description": "Client-side public key generated by the user, to which the export bundle will be encrypted." + } + }, + "required": ["privateKeyId", "targetPublicKey"] + }, + "v1ExportPrivateKeyRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_EXPORT_PRIVATE_KEY"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1ExportPrivateKeyIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1ExportPrivateKeyResult": { + "type": "object", + "properties": { + "privateKeyId": { + "type": "string", + "description": "Unique identifier for a given Private Key." + }, + "exportBundle": { + "type": "string", + "description": "Export bundle containing a private key encrypted to the client's target public key." + } + }, + "required": ["privateKeyId", "exportBundle"] + }, + "v1ExportWalletAccountIntent": { + "type": "object", + "properties": { + "address": { + "type": "string", + "description": "Address to identify Wallet Account." + }, + "targetPublicKey": { + "type": "string", + "description": "Client-side public key generated by the user, to which the export bundle will be encrypted." + } + }, + "required": ["address", "targetPublicKey"] + }, + "v1ExportWalletAccountRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_EXPORT_WALLET_ACCOUNT"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1ExportWalletAccountIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1ExportWalletAccountResult": { + "type": "object", + "properties": { + "address": { + "type": "string", + "description": "Address to identify Wallet Account." + }, + "exportBundle": { + "type": "string", + "description": "Export bundle containing a private key encrypted by the client's target public key." + } + }, + "required": ["address", "exportBundle"] + }, + "v1ExportWalletIntent": { + "type": "object", + "properties": { + "walletId": { + "type": "string", + "description": "Unique identifier for a given Wallet." + }, + "targetPublicKey": { + "type": "string", + "description": "Client-side public key generated by the user, to which the export bundle will be encrypted." + }, + "language": { + "$ref": "#/definitions/v1MnemonicLanguage", + "description": "The language of the mnemonic to export. Defaults to English." + } + }, + "required": ["walletId", "targetPublicKey"] + }, + "v1ExportWalletRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_EXPORT_WALLET"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1ExportWalletIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1ExportWalletResult": { + "type": "object", + "properties": { + "walletId": { + "type": "string", + "description": "Unique identifier for a given Wallet." + }, + "exportBundle": { + "type": "string", + "description": "Export bundle containing a wallet mnemonic + optional newline passphrase encrypted by the client's target public key." + } + }, + "required": ["walletId", "exportBundle"] + }, + "v1Feature": { + "type": "object", + "properties": { + "name": { + "$ref": "#/definitions/v1FeatureName" + }, + "value": { + "type": "string" + } + } + }, + "v1FeatureName": { + "type": "string", + "enum": [ + "FEATURE_NAME_ROOT_USER_EMAIL_RECOVERY", + "FEATURE_NAME_WEBAUTHN_ORIGINS", + "FEATURE_NAME_EMAIL_AUTH", + "FEATURE_NAME_EMAIL_RECOVERY", + "FEATURE_NAME_WEBHOOK", + "FEATURE_NAME_SMS_AUTH", + "FEATURE_NAME_OTP_EMAIL_AUTH", + "FEATURE_NAME_AUTH_PROXY" + ] + }, + "v1FiatOnRampBlockchainNetwork": { + "type": "string", + "enum": [ + "FIAT_ON_RAMP_BLOCKCHAIN_NETWORK_BITCOIN", + "FIAT_ON_RAMP_BLOCKCHAIN_NETWORK_ETHEREUM", + "FIAT_ON_RAMP_BLOCKCHAIN_NETWORK_SOLANA", + "FIAT_ON_RAMP_BLOCKCHAIN_NETWORK_BASE" + ] + }, + "v1FiatOnRampCryptoCurrency": { + "type": "string", + "enum": [ + "FIAT_ON_RAMP_CRYPTO_CURRENCY_BTC", + "FIAT_ON_RAMP_CRYPTO_CURRENCY_ETH", + "FIAT_ON_RAMP_CRYPTO_CURRENCY_SOL", + "FIAT_ON_RAMP_CRYPTO_CURRENCY_USDC" + ] + }, + "v1FiatOnRampCurrency": { + "type": "string", + "enum": [ + "FIAT_ON_RAMP_CURRENCY_AUD", + "FIAT_ON_RAMP_CURRENCY_BGN", + "FIAT_ON_RAMP_CURRENCY_BRL", + "FIAT_ON_RAMP_CURRENCY_CAD", + "FIAT_ON_RAMP_CURRENCY_CHF", + "FIAT_ON_RAMP_CURRENCY_COP", + "FIAT_ON_RAMP_CURRENCY_CZK", + "FIAT_ON_RAMP_CURRENCY_DKK", + "FIAT_ON_RAMP_CURRENCY_DOP", + "FIAT_ON_RAMP_CURRENCY_EGP", + "FIAT_ON_RAMP_CURRENCY_EUR", + "FIAT_ON_RAMP_CURRENCY_GBP", + "FIAT_ON_RAMP_CURRENCY_HKD", + "FIAT_ON_RAMP_CURRENCY_IDR", + "FIAT_ON_RAMP_CURRENCY_ILS", + "FIAT_ON_RAMP_CURRENCY_JOD", + "FIAT_ON_RAMP_CURRENCY_KES", + "FIAT_ON_RAMP_CURRENCY_KWD", + "FIAT_ON_RAMP_CURRENCY_LKR", + "FIAT_ON_RAMP_CURRENCY_MXN", + "FIAT_ON_RAMP_CURRENCY_NGN", + "FIAT_ON_RAMP_CURRENCY_NOK", + "FIAT_ON_RAMP_CURRENCY_NZD", + "FIAT_ON_RAMP_CURRENCY_OMR", + "FIAT_ON_RAMP_CURRENCY_PEN", + "FIAT_ON_RAMP_CURRENCY_PLN", + "FIAT_ON_RAMP_CURRENCY_RON", + "FIAT_ON_RAMP_CURRENCY_SEK", + "FIAT_ON_RAMP_CURRENCY_THB", + "FIAT_ON_RAMP_CURRENCY_TRY", + "FIAT_ON_RAMP_CURRENCY_TWD", + "FIAT_ON_RAMP_CURRENCY_USD", + "FIAT_ON_RAMP_CURRENCY_VND", + "FIAT_ON_RAMP_CURRENCY_ZAR" + ] + }, + "v1FiatOnRampPaymentMethod": { + "type": "string", + "enum": [ + "FIAT_ON_RAMP_PAYMENT_METHOD_CREDIT_DEBIT_CARD", + "FIAT_ON_RAMP_PAYMENT_METHOD_APPLE_PAY", + "FIAT_ON_RAMP_PAYMENT_METHOD_GBP_BANK_TRANSFER", + "FIAT_ON_RAMP_PAYMENT_METHOD_GBP_OPEN_BANKING_PAYMENT", + "FIAT_ON_RAMP_PAYMENT_METHOD_GOOGLE_PAY", + "FIAT_ON_RAMP_PAYMENT_METHOD_SEPA_BANK_TRANSFER", + "FIAT_ON_RAMP_PAYMENT_METHOD_PIX_INSTANT_PAYMENT", + "FIAT_ON_RAMP_PAYMENT_METHOD_PAYPAL", + "FIAT_ON_RAMP_PAYMENT_METHOD_VENMO", + "FIAT_ON_RAMP_PAYMENT_METHOD_MOONPAY_BALANCE", + "FIAT_ON_RAMP_PAYMENT_METHOD_CRYPTO_ACCOUNT", + "FIAT_ON_RAMP_PAYMENT_METHOD_FIAT_WALLET", + "FIAT_ON_RAMP_PAYMENT_METHOD_ACH_BANK_ACCOUNT" + ] + }, + "v1FiatOnRampProvider": { + "type": "string", + "enum": [ + "FIAT_ON_RAMP_PROVIDER_COINBASE", + "FIAT_ON_RAMP_PROVIDER_MOONPAY" + ] + }, + "v1GetActivitiesRequest": { + "type": "object", + "properties": { + "organizationId": { + "type": "string", + "description": "Unique identifier for a given organization." + }, + "filterByStatus": { + "type": "array", + "items": { + "$ref": "#/definitions/v1ActivityStatus" + }, + "description": "Array of activity statuses filtering which activities will be listed in the response." + }, + "paginationOptions": { + "$ref": "#/definitions/v1Pagination", + "description": "Parameters used for cursor-based pagination." + }, + "filterByType": { + "type": "array", + "items": { + "$ref": "#/definitions/v1ActivityType" + }, + "description": "Array of activity types filtering which activities will be listed in the response." + } + }, + "required": ["organizationId"] + }, + "v1GetActivitiesResponse": { + "type": "object", + "properties": { + "activities": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1Activity" + }, + "description": "A list of activities." + } + }, + "required": ["activities"] + }, + "v1GetActivityRequest": { + "type": "object", + "properties": { + "organizationId": { + "type": "string", + "description": "Unique identifier for a given organization." + }, + "activityId": { + "type": "string", + "description": "Unique identifier for a given activity object." + } + }, + "required": ["organizationId", "activityId"] + }, + "v1GetApiKeyRequest": { + "type": "object", + "properties": { + "organizationId": { + "type": "string", + "description": "Unique identifier for a given organization." + }, + "apiKeyId": { + "type": "string", + "description": "Unique identifier for a given API key." + } + }, + "required": ["organizationId", "apiKeyId"] + }, + "v1GetApiKeyResponse": { + "type": "object", + "properties": { + "apiKey": { + "$ref": "#/definitions/v1ApiKey", + "description": "An API key." + } + }, + "required": ["apiKey"] + }, + "v1GetApiKeysRequest": { + "type": "object", + "properties": { + "organizationId": { + "type": "string", + "description": "Unique identifier for a given organization." + }, + "userId": { + "type": "string", + "description": "Unique identifier for a given user." + } + }, + "required": ["organizationId"] + }, + "v1GetApiKeysResponse": { + "type": "object", + "properties": { + "apiKeys": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1ApiKey" + }, + "description": "A list of API keys." + } + }, + "required": ["apiKeys"] + }, + "v1GetAttestationDocumentRequest": { + "type": "object", + "properties": { + "organizationId": { + "type": "string", + "description": "Unique identifier for a given organization." + }, + "enclaveType": { + "type": "string", + "description": "The enclave type, one of: ump, notarizer, signer, evm-parser." + } + }, + "required": ["organizationId", "enclaveType"] + }, + "v1GetAttestationDocumentResponse": { + "type": "object", + "properties": { + "attestationDocument": { + "type": "string", + "format": "byte", + "description": "Raw (CBOR-encoded) attestation document." + } + }, + "required": ["attestationDocument"] + }, + "v1GetAuthenticatorRequest": { + "type": "object", + "properties": { + "organizationId": { + "type": "string", + "description": "Unique identifier for a given organization." + }, + "authenticatorId": { + "type": "string", + "description": "Unique identifier for a given authenticator." + } + }, + "required": ["organizationId", "authenticatorId"] + }, + "v1GetAuthenticatorResponse": { + "type": "object", + "properties": { + "authenticator": { + "$ref": "#/definitions/v1Authenticator", + "description": "An authenticator." + } + }, + "required": ["authenticator"] + }, + "v1GetAuthenticatorsRequest": { + "type": "object", + "properties": { + "organizationId": { + "type": "string", + "description": "Unique identifier for a given organization." + }, + "userId": { + "type": "string", + "description": "Unique identifier for a given user." + } + }, + "required": ["organizationId", "userId"] + }, + "v1GetAuthenticatorsResponse": { + "type": "object", + "properties": { + "authenticators": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1Authenticator" + }, + "description": "A list of authenticators." + } + }, + "required": ["authenticators"] + }, + "v1GetOauthProvidersRequest": { + "type": "object", + "properties": { + "organizationId": { + "type": "string", + "description": "Unique identifier for a given organization." + }, + "userId": { + "type": "string", + "description": "Unique identifier for a given user." + } + }, + "required": ["organizationId"] + }, + "v1GetOauthProvidersResponse": { + "type": "object", + "properties": { + "oauthProviders": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1OauthProvider" + }, + "description": "A list of Oauth providers." + } + }, + "required": ["oauthProviders"] + }, + "v1GetOrganizationConfigsRequest": { + "type": "object", + "properties": { + "organizationId": { + "type": "string", + "description": "Unique identifier for a given organization." + } + }, + "required": ["organizationId"] + }, + "v1GetOrganizationConfigsResponse": { + "type": "object", + "properties": { + "configs": { + "$ref": "#/definitions/v1Config", + "description": "Organization configs including quorum settings and organization features." + } + }, + "required": ["configs"] + }, + "v1GetOrganizationRequest": { + "type": "object", + "properties": { + "organizationId": { + "type": "string", + "description": "Unique identifier for a given organization." + } + }, + "required": ["organizationId"] + }, + "v1GetOrganizationResponse": { + "type": "object", + "properties": { + "organizationData": { + "$ref": "#/definitions/v1OrganizationData", + "description": "Object representing the full current and deleted / disabled collection of users, policies, private keys, and invitations attributable to a particular organization." + } + }, + "required": ["organizationData"] + }, + "v1GetPoliciesRequest": { + "type": "object", + "properties": { + "organizationId": { + "type": "string", + "description": "Unique identifier for a given organization." + } + }, + "required": ["organizationId"] + }, + "v1GetPoliciesResponse": { + "type": "object", + "properties": { + "policies": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1Policy" + }, + "description": "A list of policies." + } + }, + "required": ["policies"] + }, + "v1GetPolicyEvaluationsRequest": { + "type": "object", + "properties": { + "organizationId": { + "type": "string", + "description": "Unique identifier for a given organization." + }, + "activityId": { + "type": "string", + "description": "Unique identifier for a given activity." + } + }, + "required": ["organizationId", "activityId"] + }, + "v1GetPolicyEvaluationsResponse": { + "type": "object", + "properties": { + "policyEvaluations": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/externalactivityv1PolicyEvaluation" + } + } + }, + "required": ["policyEvaluations"] + }, + "v1GetPolicyRequest": { + "type": "object", + "properties": { + "organizationId": { + "type": "string", + "description": "Unique identifier for a given organization." + }, + "policyId": { + "type": "string", + "description": "Unique identifier for a given policy." + } + }, + "required": ["organizationId", "policyId"] + }, + "v1GetPolicyResponse": { + "type": "object", + "properties": { + "policy": { + "$ref": "#/definitions/v1Policy", + "description": "Object that codifies rules defining the actions that are permissible within an organization." + } + }, + "required": ["policy"] + }, + "v1GetPrivateKeyRequest": { + "type": "object", + "properties": { + "organizationId": { + "type": "string", + "description": "Unique identifier for a given organization." + }, + "privateKeyId": { + "type": "string", + "description": "Unique identifier for a given private key." + } + }, + "required": ["organizationId", "privateKeyId"] + }, + "v1GetPrivateKeyResponse": { + "type": "object", + "properties": { + "privateKey": { + "$ref": "#/definitions/v1PrivateKey", + "description": "Cryptographic public/private key pair that can be used for cryptocurrency needs or more generalized encryption." + } + }, + "required": ["privateKey"] + }, + "v1GetPrivateKeysRequest": { + "type": "object", + "properties": { + "organizationId": { + "type": "string", + "description": "Unique identifier for a given organization." + } + }, + "required": ["organizationId"] + }, + "v1GetPrivateKeysResponse": { + "type": "object", + "properties": { + "privateKeys": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1PrivateKey" + }, + "description": "A list of private keys." + } + }, + "required": ["privateKeys"] + }, + "v1GetSmartContractInterfaceRequest": { + "type": "object", + "properties": { + "organizationId": { + "type": "string", + "description": "Unique identifier for a given organization." + }, + "smartContractInterfaceId": { + "type": "string", + "description": "Unique identifier for a given smart contract interface." + } + }, + "required": ["organizationId", "smartContractInterfaceId"] + }, + "v1GetSmartContractInterfaceResponse": { + "type": "object", + "properties": { + "smartContractInterface": { + "$ref": "#/definitions/externaldatav1SmartContractInterface", + "description": "Object to be used in conjunction with policies to guard transaction signing." + } + }, + "required": ["smartContractInterface"] + }, + "v1GetSmartContractInterfacesRequest": { + "type": "object", + "properties": { + "organizationId": { + "type": "string", + "description": "Unique identifier for a given organization." + } + }, + "required": ["organizationId"] + }, + "v1GetSmartContractInterfacesResponse": { + "type": "object", + "properties": { + "smartContractInterfaces": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/externaldatav1SmartContractInterface" + }, + "description": "A list of smart contract interfaces." + } + }, + "required": ["smartContractInterfaces"] + }, + "v1GetSubOrgIdsRequest": { + "type": "object", + "properties": { + "organizationId": { + "type": "string", + "description": "Unique identifier for the parent organization. This is used to find sub-organizations within it." + }, + "filterType": { + "type": "string", + "description": "Specifies the type of filter to apply, i.e 'CREDENTIAL_ID', 'NAME', 'USERNAME', 'EMAIL', 'PHONE_NUMBER', 'OIDC_TOKEN', 'WALLET_ACCOUNT_ADDRESS' or 'PUBLIC_KEY'" + }, + "filterValue": { + "type": "string", + "description": "The value of the filter to apply for the specified type. For example, a specific email or name string." + }, + "paginationOptions": { + "$ref": "#/definitions/v1Pagination", + "description": "Parameters used for cursor-based pagination." + } + }, + "required": ["organizationId"] + }, + "v1GetSubOrgIdsResponse": { + "type": "object", + "properties": { + "organizationIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of unique identifiers for the matching sub-organizations." + } + }, + "required": ["organizationIds"] + }, + "v1GetUserRequest": { + "type": "object", + "properties": { + "organizationId": { + "type": "string", + "description": "Unique identifier for a given organization." + }, + "userId": { + "type": "string", + "description": "Unique identifier for a given user." + } + }, + "required": ["organizationId", "userId"] + }, + "v1GetUserResponse": { + "type": "object", + "properties": { + "user": { + "$ref": "#/definitions/v1User", + "description": "Web and/or API user within your organization." + } + }, + "required": ["user"] + }, + "v1GetUsersRequest": { + "type": "object", + "properties": { + "organizationId": { + "type": "string", + "description": "Unique identifier for a given organization." + } + }, + "required": ["organizationId"] + }, + "v1GetUsersResponse": { + "type": "object", + "properties": { + "users": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1User" + }, + "description": "A list of users." + } + }, + "required": ["users"] + }, + "v1GetVerifiedSubOrgIdsRequest": { + "type": "object", + "properties": { + "organizationId": { + "type": "string", + "description": "Unique identifier for the parent organization. This is used to find sub-organizations within it." + }, + "filterType": { + "type": "string", + "description": "Specifies the type of filter to apply, i.e 'EMAIL', 'PHONE_NUMBER'." + }, + "filterValue": { + "type": "string", + "description": "The value of the filter to apply for the specified type. For example, a specific email or phone number string." + }, + "paginationOptions": { + "$ref": "#/definitions/v1Pagination", + "description": "Parameters used for cursor-based pagination." + } + }, + "required": ["organizationId"] + }, + "v1GetVerifiedSubOrgIdsResponse": { + "type": "object", + "properties": { + "organizationIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of unique identifiers for the matching sub-organizations." + } + }, + "required": ["organizationIds"] + }, + "v1GetWalletAccountRequest": { + "type": "object", + "properties": { + "organizationId": { + "type": "string", + "description": "Unique identifier for a given organization." + }, + "walletId": { + "type": "string", + "description": "Unique identifier for a given wallet." + }, + "address": { + "type": "string", + "description": "Address corresponding to a wallet account." + }, + "path": { + "type": "string", + "description": "Path corresponding to a wallet account." + } + }, + "required": ["organizationId", "walletId"] + }, + "v1GetWalletAccountResponse": { + "type": "object", + "properties": { + "account": { + "$ref": "#/definitions/v1WalletAccount", + "description": "The resulting wallet account." + } + }, + "required": ["account"] + }, + "v1GetWalletAccountsRequest": { + "type": "object", + "properties": { + "organizationId": { + "type": "string", + "description": "Unique identifier for a given organization." + }, + "walletId": { + "type": "string", + "description": "Unique identifier for a given wallet. If not provided, all accounts for the organization will be returned." + }, + "paginationOptions": { + "$ref": "#/definitions/v1Pagination", + "description": "Parameters used for cursor-based pagination." + } + }, + "required": ["organizationId"] + }, + "v1GetWalletAccountsResponse": { + "type": "object", + "properties": { + "accounts": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1WalletAccount" + }, + "description": "A list of accounts generated from a wallet that share a common seed." + } + }, + "required": ["accounts"] + }, + "v1GetWalletRequest": { + "type": "object", + "properties": { + "organizationId": { + "type": "string", + "description": "Unique identifier for a given organization." + }, + "walletId": { + "type": "string", + "description": "Unique identifier for a given wallet." + } + }, + "required": ["organizationId", "walletId"] + }, + "v1GetWalletResponse": { + "type": "object", + "properties": { + "wallet": { + "$ref": "#/definitions/v1Wallet", + "description": "A collection of deterministically generated cryptographic public / private key pairs that share a common seed." + } + }, + "required": ["wallet"] + }, + "v1GetWalletsRequest": { + "type": "object", + "properties": { + "organizationId": { + "type": "string", + "description": "Unique identifier for a given organization." + } + }, + "required": ["organizationId"] + }, + "v1GetWalletsResponse": { + "type": "object", + "properties": { + "wallets": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1Wallet" + }, + "description": "A list of wallets." + } + }, + "required": ["wallets"] + }, + "v1GetWhoamiRequest": { + "type": "object", + "properties": { + "organizationId": { + "type": "string", + "description": "Unique identifier for a given organization. If the request is being made by a WebAuthN user and their sub-organization ID is unknown, this can be the parent organization ID; using the sub-organization ID when possible is preferred due to performance reasons." + } + }, + "required": ["organizationId"] + }, + "v1GetWhoamiResponse": { + "type": "object", + "properties": { + "organizationId": { + "type": "string", + "description": "Unique identifier for a given organization." + }, + "organizationName": { + "type": "string", + "description": "Human-readable name for an organization." + }, + "userId": { + "type": "string", + "description": "Unique identifier for a given user." + }, + "username": { + "type": "string", + "description": "Human-readable name for a user." + } + }, + "required": ["organizationId", "organizationName", "userId", "username"] + }, + "v1HashFunction": { + "type": "string", + "enum": [ + "HASH_FUNCTION_NO_OP", + "HASH_FUNCTION_SHA256", + "HASH_FUNCTION_KECCAK256", + "HASH_FUNCTION_NOT_APPLICABLE" + ] + }, + "v1ImportPrivateKeyIntent": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "The ID of the User importing a Private Key." + }, + "privateKeyName": { + "type": "string", + "description": "Human-readable name for a Private Key." + }, + "encryptedBundle": { + "type": "string", + "description": "Bundle containing a raw private key encrypted to the enclave's target public key." + }, + "curve": { + "$ref": "#/definitions/v1Curve", + "description": "Cryptographic Curve used to generate a given Private Key." + }, + "addressFormats": { + "type": "array", + "items": { + "$ref": "#/definitions/v1AddressFormat" + }, + "description": "Cryptocurrency-specific formats for a derived address (e.g., Ethereum)." + } + }, + "required": [ + "userId", + "privateKeyName", + "encryptedBundle", + "curve", + "addressFormats" + ] + }, + "v1ImportPrivateKeyRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_IMPORT_PRIVATE_KEY"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1ImportPrivateKeyIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1ImportPrivateKeyResult": { + "type": "object", + "properties": { + "privateKeyId": { + "type": "string", + "description": "Unique identifier for a Private Key." + }, + "addresses": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/immutableactivityv1Address" + }, + "description": "A list of addresses." + } + }, + "required": ["privateKeyId", "addresses"] + }, + "v1ImportWalletIntent": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "The ID of the User importing a Wallet." + }, + "walletName": { + "type": "string", + "description": "Human-readable name for a Wallet." + }, + "encryptedBundle": { + "type": "string", + "description": "Bundle containing a wallet mnemonic encrypted to the enclave's target public key." + }, + "accounts": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1WalletAccountParams" + }, + "description": "A list of wallet Accounts." + } + }, + "required": ["userId", "walletName", "encryptedBundle", "accounts"] + }, + "v1ImportWalletRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_IMPORT_WALLET"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1ImportWalletIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1ImportWalletResult": { + "type": "object", + "properties": { + "walletId": { + "type": "string", + "description": "Unique identifier for a Wallet." + }, + "addresses": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of account addresses." + } + }, + "required": ["walletId", "addresses"] + }, + "v1InitFiatOnRampIntent": { + "type": "object", + "properties": { + "onrampProvider": { + "$ref": "#/definitions/v1FiatOnRampProvider", + "description": "Enum to specifiy which on-ramp provider to use" + }, + "walletAddress": { + "type": "string", + "description": "Destination wallet address for the buy transaction." + }, + "network": { + "$ref": "#/definitions/v1FiatOnRampBlockchainNetwork", + "description": "Blockchain network to be used for the transaction, e.g., bitcoin, ethereum. Maps to MoonPay's network or Coinbase's defaultNetwork." + }, + "cryptoCurrencyCode": { + "$ref": "#/definitions/v1FiatOnRampCryptoCurrency", + "description": "Code for the cryptocurrency to be purchased, e.g., btc, eth. Maps to MoonPay's currencyCode or Coinbase's defaultAsset." + }, + "fiatCurrencyCode": { + "$ref": "#/definitions/v1FiatOnRampCurrency", + "description": "Code for the fiat currency to be used in the transaction, e.g., USD, EUR." + }, + "fiatCurrencyAmount": { + "type": "string", + "description": "Specifies a preset fiat amount for the transaction, e.g., '100'. Must be greater than '20'. If not provided, the user will be prompted to enter an amount." + }, + "paymentMethod": { + "$ref": "#/definitions/v1FiatOnRampPaymentMethod", + "description": "Pre-selected payment method, e.g., CREDIT_DEBIT_CARD, APPLE_PAY. Validated against the chosen provider." + }, + "countryCode": { + "type": "string", + "description": "ISO 3166-1 two-digit country code for Coinbase representing the purchasing user’s country of residence, e.g., US, GB." + }, + "countrySubdivisionCode": { + "type": "string", + "description": "ISO 3166-2 two-digit country subdivision code for Coinbase representing the purchasing user’s subdivision of residence within their country, e.g. NY. Required if country_code=US." + }, + "sandboxMode": { + "type": "boolean", + "description": "Optional flag to indicate whether to use the sandbox mode to simulate transactions for the on-ramp provider. Default is false." + } + }, + "required": [ + "onrampProvider", + "walletAddress", + "network", + "cryptoCurrencyCode" + ] + }, + "v1InitFiatOnRampRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_INIT_FIAT_ON_RAMP"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1InitFiatOnRampIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1InitFiatOnRampResult": { + "type": "object", + "properties": { + "onRampUrl": { + "type": "string", + "description": "Unique URL for a given fiat on-ramp flow." + }, + "onRampTransactionId": { + "type": "string", + "description": "Unique identifier used to retrieve transaction statuses for a given fiat on-ramp flow." + } + }, + "required": ["onRampUrl", "onRampTransactionId"] + }, + "v1InitImportPrivateKeyIntent": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "The ID of the User importing a Private Key." + } + }, + "required": ["userId"] + }, + "v1InitImportPrivateKeyRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_INIT_IMPORT_PRIVATE_KEY"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1InitImportPrivateKeyIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1InitImportPrivateKeyResult": { + "type": "object", + "properties": { + "importBundle": { + "type": "string", + "description": "Import bundle containing a public key and signature to use for importing client data." + } + }, + "required": ["importBundle"] + }, + "v1InitImportWalletIntent": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "The ID of the User importing a Wallet." + } + }, + "required": ["userId"] + }, + "v1InitImportWalletRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_INIT_IMPORT_WALLET"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1InitImportWalletIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1InitImportWalletResult": { + "type": "object", + "properties": { + "importBundle": { + "type": "string", + "description": "Import bundle containing a public key and signature to use for importing client data." + } + }, + "required": ["importBundle"] + }, + "v1InitOtpAuthIntent": { + "type": "object", + "properties": { + "otpType": { + "type": "string", + "description": "Enum to specifiy whether to send OTP via SMS or email" + }, + "contact": { + "type": "string", + "description": "Email or phone number to send the OTP code to" + }, + "emailCustomization": { + "$ref": "#/definitions/v1EmailCustomizationParams", + "description": "Optional parameters for customizing emails. If not provided, the default email will be used." + }, + "smsCustomization": { + "$ref": "#/definitions/v1SmsCustomizationParams", + "description": "Optional parameters for customizing SMS message. If not provided, the default sms message will be used." + }, + "userIdentifier": { + "type": "string", + "description": "Optional client-generated user identifier to enable per-user rate limiting for SMS auth. We recommend using a hash of the client-side IP address." + }, + "sendFromEmailAddress": { + "type": "string", + "description": "Optional custom email address from which to send the OTP email" + }, + "sendFromEmailSenderName": { + "type": "string", + "description": "Optional custom sender name for use with sendFromEmailAddress; if left empty, will default to 'Notifications'" + }, + "replyToEmailAddress": { + "type": "string", + "description": "Optional custom email address to use as reply-to" + } + }, + "required": ["otpType", "contact"] + }, + "v1InitOtpAuthIntentV2": { + "type": "object", + "properties": { + "otpType": { + "type": "string", + "description": "Enum to specifiy whether to send OTP via SMS or email" + }, + "contact": { + "type": "string", + "description": "Email or phone number to send the OTP code to" + }, + "otpLength": { + "type": "integer", + "format": "int32", + "description": "Optional length of the OTP code. Default = 9" + }, + "emailCustomization": { + "$ref": "#/definitions/v1EmailCustomizationParams", + "description": "Optional parameters for customizing emails. If not provided, the default email will be used." + }, + "smsCustomization": { + "$ref": "#/definitions/v1SmsCustomizationParams", + "description": "Optional parameters for customizing SMS message. If not provided, the default sms message will be used." + }, + "userIdentifier": { + "type": "string", + "description": "Optional client-generated user identifier to enable per-user rate limiting for SMS auth. We recommend using a hash of the client-side IP address." + }, + "sendFromEmailAddress": { + "type": "string", + "description": "Optional custom email address from which to send the OTP email" + }, + "alphanumeric": { + "type": "boolean", + "description": "Optional flag to specify if the OTP code should be alphanumeric (Crockford’s Base32). Default = true" + }, + "sendFromEmailSenderName": { + "type": "string", + "description": "Optional custom sender name for use with sendFromEmailAddress; if left empty, will default to 'Notifications'" + }, + "replyToEmailAddress": { + "type": "string", + "description": "Optional custom email address to use as reply-to" + } + }, + "required": ["otpType", "contact"] + }, + "v1InitOtpAuthRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_INIT_OTP_AUTH_V2"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1InitOtpAuthIntentV2" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1InitOtpAuthResult": { + "type": "object", + "properties": { + "otpId": { + "type": "string", + "description": "Unique identifier for an OTP authentication" + } + }, + "required": ["otpId"] + }, + "v1InitOtpAuthResultV2": { + "type": "object", + "properties": { + "otpId": { + "type": "string", + "description": "Unique identifier for an OTP authentication" + } + }, + "required": ["otpId"] + }, + "v1InitOtpIntent": { + "type": "object", + "properties": { + "otpType": { + "type": "string", + "description": "Whether to send OTP via SMS or email. Possible values: OTP_TYPE_SMS, OTP_TYPE_EMAIL" + }, + "contact": { + "type": "string", + "description": "Email or phone number to send the OTP code to" + }, + "otpLength": { + "type": "integer", + "format": "int32", + "description": "Optional length of the OTP code. Default = 9" + }, + "emailCustomization": { + "$ref": "#/definitions/v1EmailCustomizationParams", + "description": "Optional parameters for customizing emails. If not provided, the default email will be used." + }, + "smsCustomization": { + "$ref": "#/definitions/v1SmsCustomizationParams", + "description": "Optional parameters for customizing SMS message. If not provided, the default sms message will be used." + }, + "userIdentifier": { + "type": "string", + "description": "Optional client-generated user identifier to enable per-user rate limiting for SMS auth. We recommend using a hash of the client-side IP address." + }, + "sendFromEmailAddress": { + "type": "string", + "description": "Optional custom email address from which to send the OTP email" + }, + "alphanumeric": { + "type": "boolean", + "description": "Optional flag to specify if the OTP code should be alphanumeric (Crockford’s Base32). Default = true" + }, + "sendFromEmailSenderName": { + "type": "string", + "description": "Optional custom sender name for use with sendFromEmailAddress; if left empty, will default to 'Notifications'" + }, + "expirationSeconds": { + "type": "string", + "description": "Expiration window (in seconds) indicating how long the OTP is valid for. If not provided, a default of 5 minutes will be used. Maximum value is 600 seconds (10 minutes)" + }, + "replyToEmailAddress": { + "type": "string", + "description": "Optional custom email address to use as reply-to" + } + }, + "required": ["otpType", "contact"] + }, + "v1InitOtpRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_INIT_OTP"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1InitOtpIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1InitOtpResult": { + "type": "object", + "properties": { + "otpId": { + "type": "string", + "description": "Unique identifier for an OTP authentication" + } + }, + "required": ["otpId"] + }, + "v1InitUserEmailRecoveryIntent": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "Email of the user starting recovery" + }, + "targetPublicKey": { + "type": "string", + "description": "Client-side public key generated by the user, to which the recovery bundle will be encrypted." + }, + "expirationSeconds": { + "type": "string", + "description": "Expiration window (in seconds) indicating how long the recovery credential is valid for. If not provided, a default of 15 minutes will be used." + }, + "emailCustomization": { + "$ref": "#/definitions/v1EmailCustomizationParams", + "description": "Optional parameters for customizing emails. If not provided, the default email will be used." + } + }, + "required": ["email", "targetPublicKey"] + }, + "v1InitUserEmailRecoveryRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_INIT_USER_EMAIL_RECOVERY"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1InitUserEmailRecoveryIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1InitUserEmailRecoveryResult": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "Unique identifier for the user being recovered." + } + }, + "required": ["userId"] + }, + "v1Intent": { + "type": "object", + "properties": { + "createOrganizationIntent": { + "$ref": "#/definitions/v1CreateOrganizationIntent" + }, + "createAuthenticatorsIntent": { + "$ref": "#/definitions/v1CreateAuthenticatorsIntent" + }, + "createUsersIntent": { + "$ref": "#/definitions/v1CreateUsersIntent" + }, + "createPrivateKeysIntent": { + "$ref": "#/definitions/v1CreatePrivateKeysIntent" + }, + "signRawPayloadIntent": { + "$ref": "#/definitions/v1SignRawPayloadIntent" + }, + "createInvitationsIntent": { + "$ref": "#/definitions/v1CreateInvitationsIntent" + }, + "acceptInvitationIntent": { + "$ref": "#/definitions/v1AcceptInvitationIntent" + }, + "createPolicyIntent": { + "$ref": "#/definitions/v1CreatePolicyIntent" + }, + "disablePrivateKeyIntent": { + "$ref": "#/definitions/v1DisablePrivateKeyIntent" + }, + "deleteUsersIntent": { + "$ref": "#/definitions/v1DeleteUsersIntent" + }, + "deleteAuthenticatorsIntent": { + "$ref": "#/definitions/v1DeleteAuthenticatorsIntent" + }, + "deleteInvitationIntent": { + "$ref": "#/definitions/v1DeleteInvitationIntent" + }, + "deleteOrganizationIntent": { + "$ref": "#/definitions/v1DeleteOrganizationIntent" + }, + "deletePolicyIntent": { + "$ref": "#/definitions/v1DeletePolicyIntent" + }, + "createUserTagIntent": { + "$ref": "#/definitions/v1CreateUserTagIntent" + }, + "deleteUserTagsIntent": { + "$ref": "#/definitions/v1DeleteUserTagsIntent" + }, + "signTransactionIntent": { + "$ref": "#/definitions/v1SignTransactionIntent" + }, + "createApiKeysIntent": { + "$ref": "#/definitions/v1CreateApiKeysIntent" + }, + "deleteApiKeysIntent": { + "$ref": "#/definitions/v1DeleteApiKeysIntent" + }, + "approveActivityIntent": { + "$ref": "#/definitions/v1ApproveActivityIntent" + }, + "rejectActivityIntent": { + "$ref": "#/definitions/v1RejectActivityIntent" + }, + "createPrivateKeyTagIntent": { + "$ref": "#/definitions/v1CreatePrivateKeyTagIntent" + }, + "deletePrivateKeyTagsIntent": { + "$ref": "#/definitions/v1DeletePrivateKeyTagsIntent" + }, + "createPolicyIntentV2": { + "$ref": "#/definitions/v1CreatePolicyIntentV2" + }, + "setPaymentMethodIntent": { + "$ref": "#/definitions/billingSetPaymentMethodIntent" + }, + "activateBillingTierIntent": { + "$ref": "#/definitions/billingActivateBillingTierIntent" + }, + "deletePaymentMethodIntent": { + "$ref": "#/definitions/billingDeletePaymentMethodIntent" + }, + "createPolicyIntentV3": { + "$ref": "#/definitions/v1CreatePolicyIntentV3" + }, + "createApiOnlyUsersIntent": { + "$ref": "#/definitions/v1CreateApiOnlyUsersIntent" + }, + "updateRootQuorumIntent": { + "$ref": "#/definitions/v1UpdateRootQuorumIntent" + }, + "updateUserTagIntent": { + "$ref": "#/definitions/v1UpdateUserTagIntent" + }, + "updatePrivateKeyTagIntent": { + "$ref": "#/definitions/v1UpdatePrivateKeyTagIntent" + }, + "createAuthenticatorsIntentV2": { + "$ref": "#/definitions/v1CreateAuthenticatorsIntentV2" + }, + "acceptInvitationIntentV2": { + "$ref": "#/definitions/v1AcceptInvitationIntentV2" + }, + "createOrganizationIntentV2": { + "$ref": "#/definitions/v1CreateOrganizationIntentV2" + }, + "createUsersIntentV2": { + "$ref": "#/definitions/v1CreateUsersIntentV2" + }, + "createSubOrganizationIntent": { + "$ref": "#/definitions/v1CreateSubOrganizationIntent" + }, + "createSubOrganizationIntentV2": { + "$ref": "#/definitions/v1CreateSubOrganizationIntentV2" + }, + "updateAllowedOriginsIntent": { + "$ref": "#/definitions/v1UpdateAllowedOriginsIntent" + }, + "createPrivateKeysIntentV2": { + "$ref": "#/definitions/v1CreatePrivateKeysIntentV2" + }, + "updateUserIntent": { + "$ref": "#/definitions/v1UpdateUserIntent" + }, + "updatePolicyIntent": { + "$ref": "#/definitions/v1UpdatePolicyIntent" + }, + "setPaymentMethodIntentV2": { + "$ref": "#/definitions/billingSetPaymentMethodIntentV2" + }, + "createSubOrganizationIntentV3": { + "$ref": "#/definitions/v1CreateSubOrganizationIntentV3" + }, + "createWalletIntent": { + "$ref": "#/definitions/v1CreateWalletIntent" + }, + "createWalletAccountsIntent": { + "$ref": "#/definitions/v1CreateWalletAccountsIntent" + }, + "initUserEmailRecoveryIntent": { + "$ref": "#/definitions/v1InitUserEmailRecoveryIntent" + }, + "recoverUserIntent": { + "$ref": "#/definitions/v1RecoverUserIntent" + }, + "setOrganizationFeatureIntent": { + "$ref": "#/definitions/v1SetOrganizationFeatureIntent" + }, + "removeOrganizationFeatureIntent": { + "$ref": "#/definitions/v1RemoveOrganizationFeatureIntent" + }, + "signRawPayloadIntentV2": { + "$ref": "#/definitions/v1SignRawPayloadIntentV2" + }, + "signTransactionIntentV2": { + "$ref": "#/definitions/v1SignTransactionIntentV2" + }, + "exportPrivateKeyIntent": { + "$ref": "#/definitions/v1ExportPrivateKeyIntent" + }, + "exportWalletIntent": { + "$ref": "#/definitions/v1ExportWalletIntent" + }, + "createSubOrganizationIntentV4": { + "$ref": "#/definitions/v1CreateSubOrganizationIntentV4" + }, + "emailAuthIntent": { + "$ref": "#/definitions/v1EmailAuthIntent" + }, + "exportWalletAccountIntent": { + "$ref": "#/definitions/v1ExportWalletAccountIntent" + }, + "initImportWalletIntent": { + "$ref": "#/definitions/v1InitImportWalletIntent" + }, + "importWalletIntent": { + "$ref": "#/definitions/v1ImportWalletIntent" + }, + "initImportPrivateKeyIntent": { + "$ref": "#/definitions/v1InitImportPrivateKeyIntent" + }, + "importPrivateKeyIntent": { + "$ref": "#/definitions/v1ImportPrivateKeyIntent" + }, + "createPoliciesIntent": { + "$ref": "#/definitions/v1CreatePoliciesIntent" + }, + "signRawPayloadsIntent": { + "$ref": "#/definitions/v1SignRawPayloadsIntent" + }, + "createReadOnlySessionIntent": { + "$ref": "#/definitions/v1CreateReadOnlySessionIntent" + }, + "createOauthProvidersIntent": { + "$ref": "#/definitions/v1CreateOauthProvidersIntent" + }, + "deleteOauthProvidersIntent": { + "$ref": "#/definitions/v1DeleteOauthProvidersIntent" + }, + "createSubOrganizationIntentV5": { + "$ref": "#/definitions/v1CreateSubOrganizationIntentV5" + }, + "oauthIntent": { + "$ref": "#/definitions/v1OauthIntent" + }, + "createApiKeysIntentV2": { + "$ref": "#/definitions/v1CreateApiKeysIntentV2" + }, + "createReadWriteSessionIntent": { + "$ref": "#/definitions/v1CreateReadWriteSessionIntent" + }, + "emailAuthIntentV2": { + "$ref": "#/definitions/v1EmailAuthIntentV2" + }, + "createSubOrganizationIntentV6": { + "$ref": "#/definitions/v1CreateSubOrganizationIntentV6" + }, + "deletePrivateKeysIntent": { + "$ref": "#/definitions/v1DeletePrivateKeysIntent" + }, + "deleteWalletsIntent": { + "$ref": "#/definitions/v1DeleteWalletsIntent" + }, + "createReadWriteSessionIntentV2": { + "$ref": "#/definitions/v1CreateReadWriteSessionIntentV2" + }, + "deleteSubOrganizationIntent": { + "$ref": "#/definitions/v1DeleteSubOrganizationIntent" + }, + "initOtpAuthIntent": { + "$ref": "#/definitions/v1InitOtpAuthIntent" + }, + "otpAuthIntent": { + "$ref": "#/definitions/v1OtpAuthIntent" + }, + "createSubOrganizationIntentV7": { + "$ref": "#/definitions/v1CreateSubOrganizationIntentV7" + }, + "updateWalletIntent": { + "$ref": "#/definitions/v1UpdateWalletIntent" + }, + "updatePolicyIntentV2": { + "$ref": "#/definitions/v1UpdatePolicyIntentV2" + }, + "createUsersIntentV3": { + "$ref": "#/definitions/v1CreateUsersIntentV3" + }, + "initOtpAuthIntentV2": { + "$ref": "#/definitions/v1InitOtpAuthIntentV2" + }, + "initOtpIntent": { + "$ref": "#/definitions/v1InitOtpIntent" + }, + "verifyOtpIntent": { + "$ref": "#/definitions/v1VerifyOtpIntent" + }, + "otpLoginIntent": { + "$ref": "#/definitions/v1OtpLoginIntent" + }, + "stampLoginIntent": { + "$ref": "#/definitions/v1StampLoginIntent" + }, + "oauthLoginIntent": { + "$ref": "#/definitions/v1OauthLoginIntent" + }, + "updateUserNameIntent": { + "$ref": "#/definitions/v1UpdateUserNameIntent" + }, + "updateUserEmailIntent": { + "$ref": "#/definitions/v1UpdateUserEmailIntent" + }, + "updateUserPhoneNumberIntent": { + "$ref": "#/definitions/v1UpdateUserPhoneNumberIntent" + }, + "initFiatOnRampIntent": { + "$ref": "#/definitions/v1InitFiatOnRampIntent" + }, + "createSmartContractInterfaceIntent": { + "$ref": "#/definitions/v1CreateSmartContractInterfaceIntent" + }, + "deleteSmartContractInterfaceIntent": { + "$ref": "#/definitions/v1DeleteSmartContractInterfaceIntent" + }, + "enableAuthProxyIntent": { + "$ref": "#/definitions/v1EnableAuthProxyIntent" + }, + "disableAuthProxyIntent": { + "$ref": "#/definitions/v1DisableAuthProxyIntent" + }, + "updateAuthProxyConfigIntent": { + "$ref": "#/definitions/v1UpdateAuthProxyConfigIntent" + } + } + }, + "v1Invitation": { + "type": "object", + "properties": { + "invitationId": { + "type": "string", + "description": "Unique identifier for a given Invitation object." + }, + "receiverUserName": { + "type": "string", + "description": "The name of the intended Invitation recipient." + }, + "receiverEmail": { + "type": "string", + "description": "The email address of the intended Invitation recipient." + }, + "receiverUserTags": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of tags assigned to the Invitation recipient." + }, + "accessType": { + "$ref": "#/definitions/v1AccessType", + "description": "The User's permissible access method(s)." + }, + "status": { + "$ref": "#/definitions/v1InvitationStatus", + "description": "The current processing status of a specified Invitation." + }, + "createdAt": { + "$ref": "#/definitions/externaldatav1Timestamp" + }, + "updatedAt": { + "$ref": "#/definitions/externaldatav1Timestamp" + }, + "senderUserId": { + "type": "string", + "description": "Unique identifier for the Sender of an Invitation." + } + }, + "required": [ + "invitationId", + "receiverUserName", + "receiverEmail", + "receiverUserTags", + "accessType", + "status", + "createdAt", + "updatedAt", + "senderUserId" + ] + }, + "v1InvitationParams": { + "type": "object", + "properties": { + "receiverUserName": { + "type": "string", + "description": "The name of the intended Invitation recipient." + }, + "receiverUserEmail": { + "type": "string", + "description": "The email address of the intended Invitation recipient." + }, + "receiverUserTags": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of tags assigned to the Invitation recipient. This field, if not needed, should be an empty array in your request body." + }, + "accessType": { + "$ref": "#/definitions/v1AccessType", + "description": "The User's permissible access method(s)." + }, + "senderUserId": { + "type": "string", + "description": "Unique identifier for the Sender of an Invitation." + } + }, + "required": [ + "receiverUserName", + "receiverUserEmail", + "receiverUserTags", + "accessType", + "senderUserId" + ] + }, + "v1InvitationStatus": { + "type": "string", + "enum": [ + "INVITATION_STATUS_CREATED", + "INVITATION_STATUS_ACCEPTED", + "INVITATION_STATUS_REVOKED" + ] + }, + "v1ListPrivateKeyTagsRequest": { + "type": "object", + "properties": { + "organizationId": { + "type": "string", + "description": "Unique identifier for a given organization." + } + }, + "required": ["organizationId"] + }, + "v1ListPrivateKeyTagsResponse": { + "type": "object", + "properties": { + "privateKeyTags": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/datav1Tag" + }, + "description": "A list of private key tags." + } + }, + "required": ["privateKeyTags"] + }, + "v1ListUserTagsRequest": { + "type": "object", + "properties": { + "organizationId": { + "type": "string", + "description": "Unique identifier for a given organization." + } + }, + "required": ["organizationId"] + }, + "v1ListUserTagsResponse": { + "type": "object", + "properties": { + "userTags": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/datav1Tag" + }, + "description": "A list of user tags." + } + }, + "required": ["userTags"] + }, + "v1MnemonicLanguage": { + "type": "string", + "enum": [ + "MNEMONIC_LANGUAGE_ENGLISH", + "MNEMONIC_LANGUAGE_SIMPLIFIED_CHINESE", + "MNEMONIC_LANGUAGE_TRADITIONAL_CHINESE", + "MNEMONIC_LANGUAGE_CZECH", + "MNEMONIC_LANGUAGE_FRENCH", + "MNEMONIC_LANGUAGE_ITALIAN", + "MNEMONIC_LANGUAGE_JAPANESE", + "MNEMONIC_LANGUAGE_KOREAN", + "MNEMONIC_LANGUAGE_SPANISH" + ] + }, + "v1NOOPCodegenAnchorResponse": { + "type": "object", + "properties": { + "stamp": { + "$ref": "#/definitions/v1WebAuthnStamp" + } + }, + "required": ["stamp"] + }, + "v1OauthIntent": { + "type": "object", + "properties": { + "oidcToken": { + "type": "string", + "description": "Base64 encoded OIDC token" + }, + "targetPublicKey": { + "type": "string", + "description": "Client-side public key generated by the user, to which the oauth bundle (credentials) will be encrypted." + }, + "apiKeyName": { + "type": "string", + "description": "Optional human-readable name for an API Key. If none provided, default to Oauth - \u003cTimestamp\u003e" + }, + "expirationSeconds": { + "type": "string", + "description": "Expiration window (in seconds) indicating how long the API key is valid for. If not provided, a default of 15 minutes will be used." + }, + "invalidateExisting": { + "type": "boolean", + "description": "Invalidate all other previously generated Oauth API keys" + } + }, + "required": ["oidcToken", "targetPublicKey"] + }, + "v1OauthLoginIntent": { + "type": "object", + "properties": { + "oidcToken": { + "type": "string", + "description": "Base64 encoded OIDC token" + }, + "publicKey": { + "type": "string", + "description": "Client-side public key generated by the user, which will be conditionally added to org data based on the validity of the oidc token associated with this request" + }, + "expirationSeconds": { + "type": "string", + "description": "Expiration window (in seconds) indicating how long the Session is valid for. If not provided, a default of 15 minutes will be used." + }, + "invalidateExisting": { + "type": "boolean", + "description": "Invalidate all other previously generated Login API keys" + } + }, + "required": ["oidcToken", "publicKey"] + }, + "v1OauthLoginRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_OAUTH_LOGIN"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1OauthLoginIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1OauthLoginResult": { + "type": "object", + "properties": { + "session": { + "type": "string", + "description": "Signed JWT containing an expiry, public key, session type, user id, and organization id" + } + }, + "required": ["session"] + }, + "v1OauthProvider": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Unique identifier for an OAuth Provider" + }, + "providerName": { + "type": "string", + "description": "Human-readable name to identify a Provider." + }, + "issuer": { + "type": "string", + "description": "The issuer of the token, typically a URL indicating the authentication server, e.g https://accounts.google.com" + }, + "audience": { + "type": "string", + "description": "Expected audience ('aud' attribute of the signed token) which represents the app ID" + }, + "subject": { + "type": "string", + "description": "Expected subject ('sub' attribute of the signed token) which represents the user ID" + }, + "createdAt": { + "$ref": "#/definitions/externaldatav1Timestamp" + }, + "updatedAt": { + "$ref": "#/definitions/externaldatav1Timestamp" + } + }, + "required": [ + "providerId", + "providerName", + "issuer", + "audience", + "subject", + "createdAt", + "updatedAt" + ] + }, + "v1OauthProviderParams": { + "type": "object", + "properties": { + "providerName": { + "type": "string", + "description": "Human-readable name to identify a Provider." + }, + "oidcToken": { + "type": "string", + "description": "Base64 encoded OIDC token" + } + }, + "required": ["providerName", "oidcToken"] + }, + "v1OauthRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_OAUTH"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1OauthIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1OauthResult": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "Unique identifier for the authenticating User." + }, + "apiKeyId": { + "type": "string", + "description": "Unique identifier for the created API key." + }, + "credentialBundle": { + "type": "string", + "description": "HPKE encrypted credential bundle" + } + }, + "required": ["userId", "apiKeyId", "credentialBundle"] + }, + "v1Operator": { + "type": "string", + "enum": [ + "OPERATOR_EQUAL", + "OPERATOR_MORE_THAN", + "OPERATOR_MORE_THAN_OR_EQUAL", + "OPERATOR_LESS_THAN", + "OPERATOR_LESS_THAN_OR_EQUAL", + "OPERATOR_CONTAINS", + "OPERATOR_NOT_EQUAL", + "OPERATOR_IN", + "OPERATOR_NOT_IN", + "OPERATOR_CONTAINS_ONE", + "OPERATOR_CONTAINS_ALL" + ] + }, + "v1OrganizationData": { + "type": "object", + "properties": { + "organizationId": { + "type": "string" + }, + "name": { + "type": "string" + }, + "users": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1User" + } + }, + "policies": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1Policy" + } + }, + "privateKeys": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1PrivateKey" + } + }, + "invitations": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1Invitation" + } + }, + "tags": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/datav1Tag" + } + }, + "rootQuorum": { + "$ref": "#/definitions/externaldatav1Quorum" + }, + "features": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1Feature" + } + }, + "wallets": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1Wallet" + } + }, + "smartContractInterfaceReferences": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1SmartContractInterfaceReference" + } + } + } + }, + "v1OtpAuthIntent": { + "type": "object", + "properties": { + "otpId": { + "type": "string", + "description": "ID representing the result of an init OTP activity." + }, + "otpCode": { + "type": "string", + "description": "OTP sent out to a user's contact (email or SMS)" + }, + "targetPublicKey": { + "type": "string", + "description": "Client-side public key generated by the user, to which the OTP bundle (credentials) will be encrypted." + }, + "apiKeyName": { + "type": "string", + "description": "Optional human-readable name for an API Key. If none provided, default to OTP Auth - \u003cTimestamp\u003e" + }, + "expirationSeconds": { + "type": "string", + "description": "Expiration window (in seconds) indicating how long the API key is valid for. If not provided, a default of 15 minutes will be used." + }, + "invalidateExisting": { + "type": "boolean", + "description": "Invalidate all other previously generated OTP Auth API keys" + } + }, + "required": ["otpId", "otpCode", "targetPublicKey"] + }, + "v1OtpAuthRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_OTP_AUTH"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1OtpAuthIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1OtpAuthResult": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "Unique identifier for the authenticating User." + }, + "apiKeyId": { + "type": "string", + "description": "Unique identifier for the created API key." + }, + "credentialBundle": { + "type": "string", + "description": "HPKE encrypted credential bundle" + } + }, + "required": ["userId"] + }, + "v1OtpLoginIntent": { + "type": "object", + "properties": { + "verificationToken": { + "type": "string", + "description": "Signed JWT containing a unique id, expiry, verification type, contact" + }, + "publicKey": { + "type": "string", + "description": "Client-side public key generated by the user, which will be conditionally added to org data based on the validity of the verification token" + }, + "expirationSeconds": { + "type": "string", + "description": "Expiration window (in seconds) indicating how long the Session is valid for. If not provided, a default of 15 minutes will be used." + }, + "invalidateExisting": { + "type": "boolean", + "description": "Invalidate all other previously generated Login API keys" + } + }, + "required": ["verificationToken", "publicKey"] + }, + "v1OtpLoginRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_OTP_LOGIN"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1OtpLoginIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1OtpLoginResult": { + "type": "object", + "properties": { + "session": { + "type": "string", + "description": "Signed JWT containing an expiry, public key, session type, user id, and organization id" + } + }, + "required": ["session"] + }, + "v1Outcome": { + "type": "string", + "enum": [ + "OUTCOME_ALLOW", + "OUTCOME_DENY_EXPLICIT", + "OUTCOME_DENY_IMPLICIT", + "OUTCOME_REQUIRES_CONSENSUS", + "OUTCOME_REJECTED", + "OUTCOME_ERROR" + ] + }, + "v1Pagination": { + "type": "object", + "properties": { + "limit": { + "type": "string", + "description": "A limit of the number of object to be returned, between 1 and 100. Defaults to 10." + }, + "before": { + "type": "string", + "description": "A pagination cursor. This is an object ID that enables you to fetch all objects before this ID." + }, + "after": { + "type": "string", + "description": "A pagination cursor. This is an object ID that enables you to fetch all objects after this ID." + } + } + }, + "v1PathFormat": { + "type": "string", + "enum": ["PATH_FORMAT_BIP32"] + }, + "v1PayloadEncoding": { + "type": "string", + "enum": [ + "PAYLOAD_ENCODING_HEXADECIMAL", + "PAYLOAD_ENCODING_TEXT_UTF8", + "PAYLOAD_ENCODING_EIP712" + ] + }, + "v1Policy": { + "type": "object", + "properties": { + "policyId": { + "type": "string", + "description": "Unique identifier for a given Policy." + }, + "policyName": { + "type": "string", + "description": "Human-readable name for a Policy." + }, + "effect": { + "$ref": "#/definitions/v1Effect", + "description": "The instruction to DENY or ALLOW a particular activity following policy selector(s)." + }, + "createdAt": { + "$ref": "#/definitions/externaldatav1Timestamp" + }, + "updatedAt": { + "$ref": "#/definitions/externaldatav1Timestamp" + }, + "notes": { + "type": "string", + "description": "Human-readable notes added by a User to describe a particular policy." + }, + "consensus": { + "type": "string", + "description": "A consensus expression that evalutes to true or false." + }, + "condition": { + "type": "string", + "description": "A condition expression that evalutes to true or false." + } + }, + "required": [ + "policyId", + "policyName", + "effect", + "createdAt", + "updatedAt", + "notes", + "consensus", + "condition" + ] + }, + "v1PrivateKey": { + "type": "object", + "properties": { + "privateKeyId": { + "type": "string", + "description": "Unique identifier for a given Private Key." + }, + "publicKey": { + "type": "string", + "description": "The public component of a cryptographic key pair used to sign messages and transactions." + }, + "privateKeyName": { + "type": "string", + "description": "Human-readable name for a Private Key." + }, + "curve": { + "$ref": "#/definitions/v1Curve", + "description": "Cryptographic Curve used to generate a given Private Key." + }, + "addresses": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/externaldatav1Address" + }, + "description": "Derived cryptocurrency addresses for a given Private Key." + }, + "privateKeyTags": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of Private Key Tag IDs." + }, + "createdAt": { + "$ref": "#/definitions/externaldatav1Timestamp" + }, + "updatedAt": { + "$ref": "#/definitions/externaldatav1Timestamp" + }, + "exported": { + "type": "boolean", + "description": "True when a given Private Key is exported, false otherwise." + }, + "imported": { + "type": "boolean", + "description": "True when a given Private Key is imported, false otherwise." + } + }, + "required": [ + "privateKeyId", + "publicKey", + "privateKeyName", + "curve", + "addresses", + "privateKeyTags", + "createdAt", + "updatedAt", + "exported", + "imported" + ] + }, + "v1PrivateKeyParams": { + "type": "object", + "properties": { + "privateKeyName": { + "type": "string", + "description": "Human-readable name for a Private Key." + }, + "curve": { + "$ref": "#/definitions/v1Curve", + "description": "Cryptographic Curve used to generate a given Private Key." + }, + "privateKeyTags": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of Private Key Tag IDs. This field, if not needed, should be an empty array in your request body." + }, + "addressFormats": { + "type": "array", + "items": { + "$ref": "#/definitions/v1AddressFormat" + }, + "description": "Cryptocurrency-specific formats for a derived address (e.g., Ethereum)." + } + }, + "required": [ + "privateKeyName", + "curve", + "privateKeyTags", + "addressFormats" + ] + }, + "v1PrivateKeyResult": { + "type": "object", + "properties": { + "privateKeyId": { + "type": "string" + }, + "addresses": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/immutableactivityv1Address" + } + } + } + }, + "v1PublicKeyCredentialWithAttestation": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": ["public-key"] + }, + "rawId": { + "type": "string" + }, + "authenticatorAttachment": { + "type": "string", + "enum": ["cross-platform", "platform"], + "x-nullable": true + }, + "response": { + "$ref": "#/definitions/v1AuthenticatorAttestationResponse" + }, + "clientExtensionResults": { + "$ref": "#/definitions/v1SimpleClientExtensionResults" + } + }, + "required": ["id", "type", "rawId", "response", "clientExtensionResults"] + }, + "v1RecoverUserIntent": { + "type": "object", + "properties": { + "authenticator": { + "$ref": "#/definitions/v1AuthenticatorParamsV2", + "description": "The new authenticator to register." + }, + "userId": { + "type": "string", + "description": "Unique identifier for the user performing recovery." + } + }, + "required": ["authenticator", "userId"] + }, + "v1RecoverUserRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_RECOVER_USER"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1RecoverUserIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1RecoverUserResult": { + "type": "object", + "properties": { + "authenticatorId": { + "type": "array", + "items": { + "type": "string" + }, + "description": "ID of the authenticator created." + } + }, + "required": ["authenticatorId"] + }, + "v1RejectActivityIntent": { + "type": "object", + "properties": { + "fingerprint": { + "type": "string", + "description": "An artifact verifying a User's action." + } + }, + "required": ["fingerprint"] + }, + "v1RejectActivityRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_REJECT_ACTIVITY"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1RejectActivityIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1RemoveOrganizationFeatureIntent": { + "type": "object", + "properties": { + "name": { + "$ref": "#/definitions/v1FeatureName", + "description": "Name of the feature to remove" + } + }, + "required": ["name"] + }, + "v1RemoveOrganizationFeatureRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_REMOVE_ORGANIZATION_FEATURE"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1RemoveOrganizationFeatureIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1RemoveOrganizationFeatureResult": { + "type": "object", + "properties": { + "features": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1Feature" + }, + "description": "Resulting list of organization features." + } + }, + "required": ["features"] + }, + "v1Result": { + "type": "object", + "properties": { + "createOrganizationResult": { + "$ref": "#/definitions/v1CreateOrganizationResult" + }, + "createAuthenticatorsResult": { + "$ref": "#/definitions/v1CreateAuthenticatorsResult" + }, + "createUsersResult": { + "$ref": "#/definitions/v1CreateUsersResult" + }, + "createPrivateKeysResult": { + "$ref": "#/definitions/v1CreatePrivateKeysResult" + }, + "createInvitationsResult": { + "$ref": "#/definitions/v1CreateInvitationsResult" + }, + "acceptInvitationResult": { + "$ref": "#/definitions/v1AcceptInvitationResult" + }, + "signRawPayloadResult": { + "$ref": "#/definitions/v1SignRawPayloadResult" + }, + "createPolicyResult": { + "$ref": "#/definitions/v1CreatePolicyResult" + }, + "disablePrivateKeyResult": { + "$ref": "#/definitions/v1DisablePrivateKeyResult" + }, + "deleteUsersResult": { + "$ref": "#/definitions/v1DeleteUsersResult" + }, + "deleteAuthenticatorsResult": { + "$ref": "#/definitions/v1DeleteAuthenticatorsResult" + }, + "deleteInvitationResult": { + "$ref": "#/definitions/v1DeleteInvitationResult" + }, + "deleteOrganizationResult": { + "$ref": "#/definitions/v1DeleteOrganizationResult" + }, + "deletePolicyResult": { + "$ref": "#/definitions/v1DeletePolicyResult" + }, + "createUserTagResult": { + "$ref": "#/definitions/v1CreateUserTagResult" + }, + "deleteUserTagsResult": { + "$ref": "#/definitions/v1DeleteUserTagsResult" + }, + "signTransactionResult": { + "$ref": "#/definitions/v1SignTransactionResult" + }, + "deleteApiKeysResult": { + "$ref": "#/definitions/v1DeleteApiKeysResult" + }, + "createApiKeysResult": { + "$ref": "#/definitions/v1CreateApiKeysResult" + }, + "createPrivateKeyTagResult": { + "$ref": "#/definitions/v1CreatePrivateKeyTagResult" + }, + "deletePrivateKeyTagsResult": { + "$ref": "#/definitions/v1DeletePrivateKeyTagsResult" + }, + "setPaymentMethodResult": { + "$ref": "#/definitions/billingSetPaymentMethodResult" + }, + "activateBillingTierResult": { + "$ref": "#/definitions/billingActivateBillingTierResult" + }, + "deletePaymentMethodResult": { + "$ref": "#/definitions/billingDeletePaymentMethodResult" + }, + "createApiOnlyUsersResult": { + "$ref": "#/definitions/v1CreateApiOnlyUsersResult" + }, + "updateRootQuorumResult": { + "$ref": "#/definitions/v1UpdateRootQuorumResult" + }, + "updateUserTagResult": { + "$ref": "#/definitions/v1UpdateUserTagResult" + }, + "updatePrivateKeyTagResult": { + "$ref": "#/definitions/v1UpdatePrivateKeyTagResult" + }, + "createSubOrganizationResult": { + "$ref": "#/definitions/v1CreateSubOrganizationResult" + }, + "updateAllowedOriginsResult": { + "$ref": "#/definitions/v1UpdateAllowedOriginsResult" + }, + "createPrivateKeysResultV2": { + "$ref": "#/definitions/v1CreatePrivateKeysResultV2" + }, + "updateUserResult": { + "$ref": "#/definitions/v1UpdateUserResult" + }, + "updatePolicyResult": { + "$ref": "#/definitions/v1UpdatePolicyResult" + }, + "createSubOrganizationResultV3": { + "$ref": "#/definitions/v1CreateSubOrganizationResultV3" + }, + "createWalletResult": { + "$ref": "#/definitions/v1CreateWalletResult" + }, + "createWalletAccountsResult": { + "$ref": "#/definitions/v1CreateWalletAccountsResult" + }, + "initUserEmailRecoveryResult": { + "$ref": "#/definitions/v1InitUserEmailRecoveryResult" + }, + "recoverUserResult": { + "$ref": "#/definitions/v1RecoverUserResult" + }, + "setOrganizationFeatureResult": { + "$ref": "#/definitions/v1SetOrganizationFeatureResult" + }, + "removeOrganizationFeatureResult": { + "$ref": "#/definitions/v1RemoveOrganizationFeatureResult" + }, + "exportPrivateKeyResult": { + "$ref": "#/definitions/v1ExportPrivateKeyResult" + }, + "exportWalletResult": { + "$ref": "#/definitions/v1ExportWalletResult" + }, + "createSubOrganizationResultV4": { + "$ref": "#/definitions/v1CreateSubOrganizationResultV4" + }, + "emailAuthResult": { + "$ref": "#/definitions/v1EmailAuthResult" + }, + "exportWalletAccountResult": { + "$ref": "#/definitions/v1ExportWalletAccountResult" + }, + "initImportWalletResult": { + "$ref": "#/definitions/v1InitImportWalletResult" + }, + "importWalletResult": { + "$ref": "#/definitions/v1ImportWalletResult" + }, + "initImportPrivateKeyResult": { + "$ref": "#/definitions/v1InitImportPrivateKeyResult" + }, + "importPrivateKeyResult": { + "$ref": "#/definitions/v1ImportPrivateKeyResult" + }, + "createPoliciesResult": { + "$ref": "#/definitions/v1CreatePoliciesResult" + }, + "signRawPayloadsResult": { + "$ref": "#/definitions/v1SignRawPayloadsResult" + }, + "createReadOnlySessionResult": { + "$ref": "#/definitions/v1CreateReadOnlySessionResult" + }, + "createOauthProvidersResult": { + "$ref": "#/definitions/v1CreateOauthProvidersResult" + }, + "deleteOauthProvidersResult": { + "$ref": "#/definitions/v1DeleteOauthProvidersResult" + }, + "createSubOrganizationResultV5": { + "$ref": "#/definitions/v1CreateSubOrganizationResultV5" + }, + "oauthResult": { + "$ref": "#/definitions/v1OauthResult" + }, + "createReadWriteSessionResult": { + "$ref": "#/definitions/v1CreateReadWriteSessionResult" + }, + "createSubOrganizationResultV6": { + "$ref": "#/definitions/v1CreateSubOrganizationResultV6" + }, + "deletePrivateKeysResult": { + "$ref": "#/definitions/v1DeletePrivateKeysResult" + }, + "deleteWalletsResult": { + "$ref": "#/definitions/v1DeleteWalletsResult" + }, + "createReadWriteSessionResultV2": { + "$ref": "#/definitions/v1CreateReadWriteSessionResultV2" + }, + "deleteSubOrganizationResult": { + "$ref": "#/definitions/v1DeleteSubOrganizationResult" + }, + "initOtpAuthResult": { + "$ref": "#/definitions/v1InitOtpAuthResult" + }, + "otpAuthResult": { + "$ref": "#/definitions/v1OtpAuthResult" + }, + "createSubOrganizationResultV7": { + "$ref": "#/definitions/v1CreateSubOrganizationResultV7" + }, + "updateWalletResult": { + "$ref": "#/definitions/v1UpdateWalletResult" + }, + "updatePolicyResultV2": { + "$ref": "#/definitions/v1UpdatePolicyResultV2" + }, + "initOtpAuthResultV2": { + "$ref": "#/definitions/v1InitOtpAuthResultV2" + }, + "initOtpResult": { + "$ref": "#/definitions/v1InitOtpResult" + }, + "verifyOtpResult": { + "$ref": "#/definitions/v1VerifyOtpResult" + }, + "otpLoginResult": { + "$ref": "#/definitions/v1OtpLoginResult" + }, + "stampLoginResult": { + "$ref": "#/definitions/v1StampLoginResult" + }, + "oauthLoginResult": { + "$ref": "#/definitions/v1OauthLoginResult" + }, + "updateUserNameResult": { + "$ref": "#/definitions/v1UpdateUserNameResult" + }, + "updateUserEmailResult": { + "$ref": "#/definitions/v1UpdateUserEmailResult" + }, + "updateUserPhoneNumberResult": { + "$ref": "#/definitions/v1UpdateUserPhoneNumberResult" + }, + "initFiatOnRampResult": { + "$ref": "#/definitions/v1InitFiatOnRampResult" + }, + "createSmartContractInterfaceResult": { + "$ref": "#/definitions/v1CreateSmartContractInterfaceResult" + }, + "deleteSmartContractInterfaceResult": { + "$ref": "#/definitions/v1DeleteSmartContractInterfaceResult" + }, + "enableAuthProxyResult": { + "$ref": "#/definitions/v1EnableAuthProxyResult" + }, + "disableAuthProxyResult": { + "$ref": "#/definitions/v1DisableAuthProxyResult" + }, + "updateAuthProxyConfigResult": { + "$ref": "#/definitions/v1UpdateAuthProxyConfigResult" + } + } + }, + "v1RootUserParams": { + "type": "object", + "properties": { + "userName": { + "type": "string", + "description": "Human-readable name for a User." + }, + "userEmail": { + "type": "string", + "description": "The user's email address." + }, + "apiKeys": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/apiApiKeyParams" + }, + "description": "A list of API Key parameters. This field, if not needed, should be an empty array in your request body." + }, + "authenticators": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1AuthenticatorParamsV2" + }, + "description": "A list of Authenticator parameters. This field, if not needed, should be an empty array in your request body." + } + }, + "required": ["userName", "apiKeys", "authenticators"] + }, + "v1RootUserParamsV2": { + "type": "object", + "properties": { + "userName": { + "type": "string", + "description": "Human-readable name for a User." + }, + "userEmail": { + "type": "string", + "description": "The user's email address." + }, + "apiKeys": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/apiApiKeyParams" + }, + "description": "A list of API Key parameters. This field, if not needed, should be an empty array in your request body." + }, + "authenticators": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1AuthenticatorParamsV2" + }, + "description": "A list of Authenticator parameters. This field, if not needed, should be an empty array in your request body." + }, + "oauthProviders": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1OauthProviderParams" + }, + "description": "A list of Oauth providers. This field, if not needed, should be an empty array in your request body." + } + }, + "required": ["userName", "apiKeys", "authenticators", "oauthProviders"] + }, + "v1RootUserParamsV3": { + "type": "object", + "properties": { + "userName": { + "type": "string", + "description": "Human-readable name for a User." + }, + "userEmail": { + "type": "string", + "description": "The user's email address." + }, + "apiKeys": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1ApiKeyParamsV2" + }, + "description": "A list of API Key parameters. This field, if not needed, should be an empty array in your request body." + }, + "authenticators": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1AuthenticatorParamsV2" + }, + "description": "A list of Authenticator parameters. This field, if not needed, should be an empty array in your request body." + }, + "oauthProviders": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1OauthProviderParams" + }, + "description": "A list of Oauth providers. This field, if not needed, should be an empty array in your request body." + } + }, + "required": ["userName", "apiKeys", "authenticators", "oauthProviders"] + }, + "v1RootUserParamsV4": { + "type": "object", + "properties": { + "userName": { + "type": "string", + "description": "Human-readable name for a User." + }, + "userEmail": { + "type": "string", + "description": "The user's email address." + }, + "userPhoneNumber": { + "type": "string", + "description": "The user's phone number in E.164 format e.g. +13214567890" + }, + "apiKeys": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1ApiKeyParamsV2" + }, + "description": "A list of API Key parameters. This field, if not needed, should be an empty array in your request body." + }, + "authenticators": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1AuthenticatorParamsV2" + }, + "description": "A list of Authenticator parameters. This field, if not needed, should be an empty array in your request body." + }, + "oauthProviders": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1OauthProviderParams" + }, + "description": "A list of Oauth providers. This field, if not needed, should be an empty array in your request body." + } + }, + "required": ["userName", "apiKeys", "authenticators", "oauthProviders"] + }, + "v1Selector": { + "type": "object", + "properties": { + "subject": { + "type": "string" + }, + "operator": { + "$ref": "#/definitions/v1Operator" + }, + "target": { + "type": "string" + } + } + }, + "v1SelectorV2": { + "type": "object", + "properties": { + "subject": { + "type": "string" + }, + "operator": { + "$ref": "#/definitions/v1Operator" + }, + "targets": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "v1SetOrganizationFeatureIntent": { + "type": "object", + "properties": { + "name": { + "$ref": "#/definitions/v1FeatureName", + "description": "Name of the feature to set" + }, + "value": { + "type": "string", + "description": "Optional value for the feature. Will override existing values if feature is already set." + } + }, + "required": ["name", "value"] + }, + "v1SetOrganizationFeatureRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_SET_ORGANIZATION_FEATURE"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1SetOrganizationFeatureIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1SetOrganizationFeatureResult": { + "type": "object", + "properties": { + "features": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1Feature" + }, + "description": "Resulting list of organization features." + } + }, + "required": ["features"] + }, + "v1SignRawPayloadIntent": { + "type": "object", + "properties": { + "privateKeyId": { + "type": "string", + "description": "Unique identifier for a given Private Key." + }, + "payload": { + "type": "string", + "description": "Raw unsigned payload to be signed." + }, + "encoding": { + "$ref": "#/definitions/v1PayloadEncoding", + "description": "Encoding of the `payload` string. Turnkey uses this information to convert `payload` into bytes with the correct decoder (e.g. hex, utf8)." + }, + "hashFunction": { + "$ref": "#/definitions/v1HashFunction", + "description": "Hash function to apply to payload bytes before signing. This field must be set to HASH_FUNCTION_NOT_APPLICABLE for EdDSA/ed25519 signature requests; configurable payload hashing is not supported by RFC 8032." + } + }, + "required": ["privateKeyId", "payload", "encoding", "hashFunction"] + }, + "v1SignRawPayloadIntentV2": { + "type": "object", + "properties": { + "signWith": { + "type": "string", + "description": "A Wallet account address, Private Key address, or Private Key identifier." + }, + "payload": { + "type": "string", + "description": "Raw unsigned payload to be signed." + }, + "encoding": { + "$ref": "#/definitions/v1PayloadEncoding", + "description": "Encoding of the `payload` string. Turnkey uses this information to convert `payload` into bytes with the correct decoder (e.g. hex, utf8)." + }, + "hashFunction": { + "$ref": "#/definitions/v1HashFunction", + "description": "Hash function to apply to payload bytes before signing. This field must be set to HASH_FUNCTION_NOT_APPLICABLE for EdDSA/ed25519 signature requests; configurable payload hashing is not supported by RFC 8032." + } + }, + "required": ["signWith", "payload", "encoding", "hashFunction"] + }, + "v1SignRawPayloadRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_SIGN_RAW_PAYLOAD_V2"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1SignRawPayloadIntentV2" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1SignRawPayloadResult": { + "type": "object", + "properties": { + "r": { + "type": "string", + "description": "Component of an ECSDA signature." + }, + "s": { + "type": "string", + "description": "Component of an ECSDA signature." + }, + "v": { + "type": "string", + "description": "Component of an ECSDA signature." + } + }, + "required": ["r", "s", "v"] + }, + "v1SignRawPayloadsIntent": { + "type": "object", + "properties": { + "signWith": { + "type": "string", + "description": "A Wallet account address, Private Key address, or Private Key identifier." + }, + "payloads": { + "type": "array", + "items": { + "type": "string" + }, + "description": "An array of raw unsigned payloads to be signed." + }, + "encoding": { + "$ref": "#/definitions/v1PayloadEncoding", + "description": "Encoding of the `payload` string. Turnkey uses this information to convert `payload` into bytes with the correct decoder (e.g. hex, utf8)." + }, + "hashFunction": { + "$ref": "#/definitions/v1HashFunction", + "description": "Hash function to apply to payload bytes before signing. This field must be set to HASH_FUNCTION_NOT_APPLICABLE for EdDSA/ed25519 signature requests; configurable payload hashing is not supported by RFC 8032." + } + }, + "required": ["signWith", "payloads", "encoding", "hashFunction"] + }, + "v1SignRawPayloadsRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_SIGN_RAW_PAYLOADS"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1SignRawPayloadsIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1SignRawPayloadsResult": { + "type": "object", + "properties": { + "signatures": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1SignRawPayloadResult" + } + } + } + }, + "v1SignTransactionIntent": { + "type": "object", + "properties": { + "privateKeyId": { + "type": "string", + "description": "Unique identifier for a given Private Key." + }, + "unsignedTransaction": { + "type": "string", + "description": "Raw unsigned transaction to be signed by a particular Private Key." + }, + "type": { + "$ref": "#/definitions/v1TransactionType" + } + }, + "required": ["privateKeyId", "unsignedTransaction", "type"] + }, + "v1SignTransactionIntentV2": { + "type": "object", + "properties": { + "signWith": { + "type": "string", + "description": "A Wallet account address, Private Key address, or Private Key identifier." + }, + "unsignedTransaction": { + "type": "string", + "description": "Raw unsigned transaction to be signed" + }, + "type": { + "$ref": "#/definitions/v1TransactionType" + } + }, + "required": ["signWith", "unsignedTransaction", "type"] + }, + "v1SignTransactionRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_SIGN_TRANSACTION_V2"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1SignTransactionIntentV2" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1SignTransactionResult": { + "type": "object", + "properties": { + "signedTransaction": { + "type": "string" + } + }, + "required": ["signedTransaction"] + }, + "v1SimpleClientExtensionResults": { + "type": "object", + "properties": { + "appid": { + "type": "boolean" + }, + "appidExclude": { + "type": "boolean" + }, + "credProps": { + "$ref": "#/definitions/v1CredPropsAuthenticationExtensionsClientOutputs" + } + } + }, + "v1SmartContractInterfaceReference": { + "type": "object", + "properties": { + "smartContractInterfaceId": { + "type": "string" + }, + "smartContractAddress": { + "type": "string" + }, + "digest": { + "type": "string" + } + } + }, + "v1SmartContractInterfaceType": { + "type": "string", + "enum": [ + "SMART_CONTRACT_INTERFACE_TYPE_ETHEREUM", + "SMART_CONTRACT_INTERFACE_TYPE_SOLANA" + ] + }, + "v1SmsCustomizationParams": { + "type": "object", + "properties": { + "template": { + "type": "string", + "description": "Template containing references to .OtpCode i.e Your OTP is {{.OtpCode}}" + } + } + }, + "v1StampLoginIntent": { + "type": "object", + "properties": { + "publicKey": { + "type": "string", + "description": "Client-side public key generated by the user, which will be conditionally added to org data based on the passkey stamp associated with this request" + }, + "expirationSeconds": { + "type": "string", + "description": "Expiration window (in seconds) indicating how long the Session is valid for. If not provided, a default of 15 minutes will be used." + }, + "invalidateExisting": { + "type": "boolean", + "description": "Invalidate all other previously generated Login API keys" + } + }, + "required": ["publicKey"] + }, + "v1StampLoginRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_STAMP_LOGIN"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1StampLoginIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1StampLoginResult": { + "type": "object", + "properties": { + "session": { + "type": "string", + "description": "Signed JWT containing an expiry, public key, session type, user id, and organization id" + } + }, + "required": ["session"] + }, + "v1TagType": { + "type": "string", + "enum": ["TAG_TYPE_USER", "TAG_TYPE_PRIVATE_KEY"] + }, + "v1TestRateLimitsRequest": { + "type": "object", + "properties": { + "organizationId": { + "type": "string", + "description": "Unique identifier for a given organization. If the request is being made by a WebAuthN user and their sub-organization ID is unknown, this can be the parent organization ID; using the sub-organization ID when possible is preferred due to performance reasons." + }, + "isSetLimit": { + "type": "boolean", + "description": "Whether or not to set a limit on this request." + }, + "limit": { + "type": "integer", + "format": "int64", + "description": "Rate limit to set for org, if is_set_limit is set to true." + } + }, + "required": ["organizationId", "isSetLimit", "limit"] + }, + "v1TestRateLimitsResponse": { + "type": "object" + }, + "v1TransactionType": { + "type": "string", + "enum": [ + "TRANSACTION_TYPE_ETHEREUM", + "TRANSACTION_TYPE_SOLANA", + "TRANSACTION_TYPE_TRON" + ] + }, + "v1UpdateAllowedOriginsIntent": { + "type": "object", + "properties": { + "allowedOrigins": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Additional origins requests are allowed from besides Turnkey origins" + } + }, + "required": ["allowedOrigins"] + }, + "v1UpdateAllowedOriginsResult": { + "type": "object" + }, + "v1UpdateAuthProxyConfigIntent": { + "type": "object", + "properties": { + "allowedOrigins": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Updated list of allowed origins for CORS." + }, + "allowedAuthMethods": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Updated list of allowed proxy authentication methods." + }, + "sendFromEmailAddress": { + "type": "string", + "description": "Custom 'from' address for auth-related emails." + }, + "replyToEmailAddress": { + "type": "string", + "description": "Custom reply-to address for auth-related emails." + }, + "emailAuthTemplateId": { + "type": "string", + "description": "Template ID for email-auth messages." + }, + "otpTemplateId": { + "type": "string", + "description": "Template ID for OTP SMS messages." + }, + "emailCustomizationParams": { + "$ref": "#/definitions/v1EmailCustomizationParams", + "description": "Overrides for auth-related email content." + }, + "smsCustomizationParams": { + "$ref": "#/definitions/v1SmsCustomizationParams", + "description": "Overrides for auth-related SMS content." + }, + "walletKitSettings": { + "$ref": "#/definitions/v1WalletKitSettingsParams", + "description": "Overrides for react wallet kit related settings." + }, + "otpExpirationSeconds": { + "type": "integer", + "format": "int32", + "description": "OTP code lifetime in seconds." + }, + "verificationTokenExpirationSeconds": { + "type": "integer", + "format": "int32", + "description": "Verification-token lifetime in seconds." + }, + "sessionExpirationSeconds": { + "type": "integer", + "format": "int32", + "description": "Session lifetime in seconds." + }, + "otpAlphanumeric": { + "type": "boolean", + "description": "Enable alphanumeric OTP codes." + }, + "otpLength": { + "type": "integer", + "format": "int32", + "description": "Desired OTP code length (6–9)." + } + } + }, + "v1UpdateAuthProxyConfigResult": { + "type": "object", + "properties": { + "configId": { + "type": "string", + "description": "Unique identifier for a given User. (representing the turnkey signer user id)" + } + } + }, + "v1UpdatePolicyIntent": { + "type": "object", + "properties": { + "policyId": { + "type": "string", + "description": "Unique identifier for a given Policy." + }, + "policyName": { + "type": "string", + "description": "Human-readable name for a Policy." + }, + "policyEffect": { + "$ref": "#/definitions/v1Effect", + "description": "The instruction to DENY or ALLOW an activity (optional)." + }, + "policyCondition": { + "type": "string", + "description": "The condition expression that triggers the Effect (optional)." + }, + "policyConsensus": { + "type": "string", + "description": "The consensus expression that triggers the Effect (optional)." + }, + "policyNotes": { + "type": "string", + "description": "Accompanying notes for a Policy (optional)." + } + }, + "required": ["policyId"] + }, + "v1UpdatePolicyIntentV2": { + "type": "object", + "properties": { + "policyId": { + "type": "string", + "description": "Unique identifier for a given Policy." + }, + "policyName": { + "type": "string", + "description": "Human-readable name for a Policy." + }, + "policyEffect": { + "$ref": "#/definitions/v1Effect", + "description": "The instruction to DENY or ALLOW an activity (optional)." + }, + "policyCondition": { + "type": "string", + "description": "The condition expression that triggers the Effect (optional)." + }, + "policyConsensus": { + "type": "string", + "description": "The consensus expression that triggers the Effect (optional)." + }, + "policyNotes": { + "type": "string", + "description": "Accompanying notes for a Policy (optional)." + } + }, + "required": ["policyId"] + }, + "v1UpdatePolicyRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_UPDATE_POLICY_V2"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1UpdatePolicyIntentV2" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1UpdatePolicyResult": { + "type": "object", + "properties": { + "policyId": { + "type": "string", + "description": "Unique identifier for a given Policy." + } + }, + "required": ["policyId"] + }, + "v1UpdatePolicyResultV2": { + "type": "object", + "properties": { + "policyId": { + "type": "string", + "description": "Unique identifier for a given Policy." + } + }, + "required": ["policyId"] + }, + "v1UpdatePrivateKeyTagIntent": { + "type": "object", + "properties": { + "privateKeyTagId": { + "type": "string", + "description": "Unique identifier for a given Private Key Tag." + }, + "newPrivateKeyTagName": { + "type": "string", + "description": "The new, human-readable name for the tag with the given ID." + }, + "addPrivateKeyIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of Private Keys IDs to add this tag to." + }, + "removePrivateKeyIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of Private Key IDs to remove this tag from." + } + }, + "required": ["privateKeyTagId", "addPrivateKeyIds", "removePrivateKeyIds"] + }, + "v1UpdatePrivateKeyTagRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_UPDATE_PRIVATE_KEY_TAG"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1UpdatePrivateKeyTagIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1UpdatePrivateKeyTagResult": { + "type": "object", + "properties": { + "privateKeyTagId": { + "type": "string", + "description": "Unique identifier for a given Private Key Tag." + } + }, + "required": ["privateKeyTagId"] + }, + "v1UpdateRootQuorumIntent": { + "type": "object", + "properties": { + "threshold": { + "type": "integer", + "format": "int32", + "description": "The threshold of unique approvals to reach quorum." + }, + "userIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "The unique identifiers of users who comprise the quorum set." + } + }, + "required": ["threshold", "userIds"] + }, + "v1UpdateRootQuorumRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_UPDATE_ROOT_QUORUM"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1UpdateRootQuorumIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1UpdateRootQuorumResult": { + "type": "object" + }, + "v1UpdateUserEmailIntent": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "Unique identifier for a given User." + }, + "userEmail": { + "type": "string", + "description": "The user's email address. Setting this to an empty string will remove the user's email." + }, + "verificationToken": { + "type": "string", + "description": "Signed JWT containing a unique id, expiry, verification type, contact" + } + }, + "required": ["userId", "userEmail"] + }, + "v1UpdateUserEmailRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_UPDATE_USER_EMAIL"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1UpdateUserEmailIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1UpdateUserEmailResult": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "Unique identifier of the User whose email was updated." + } + }, + "required": ["userId"] + }, + "v1UpdateUserIntent": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "Unique identifier for a given User." + }, + "userName": { + "type": "string", + "description": "Human-readable name for a User." + }, + "userEmail": { + "type": "string", + "description": "The user's email address." + }, + "userTagIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "An updated list of User Tags to apply to this User. This field, if not needed, should be an empty array in your request body." + }, + "userPhoneNumber": { + "type": "string", + "description": "The user's phone number in E.164 format e.g. +13214567890" + } + }, + "required": ["userId"] + }, + "v1UpdateUserNameIntent": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "Unique identifier for a given User." + }, + "userName": { + "type": "string", + "description": "Human-readable name for a User." + } + }, + "required": ["userId", "userName"] + }, + "v1UpdateUserNameRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_UPDATE_USER_NAME"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1UpdateUserNameIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1UpdateUserNameResult": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "Unique identifier of the User whose name was updated." + } + }, + "required": ["userId"] + }, + "v1UpdateUserPhoneNumberIntent": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "Unique identifier for a given User." + }, + "userPhoneNumber": { + "type": "string", + "description": "The user's phone number in E.164 format e.g. +13214567890. Setting this to an empty string will remove the user's phone number." + }, + "verificationToken": { + "type": "string", + "description": "Signed JWT containing a unique id, expiry, verification type, contact" + } + }, + "required": ["userId", "userPhoneNumber"] + }, + "v1UpdateUserPhoneNumberRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_UPDATE_USER_PHONE_NUMBER"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1UpdateUserPhoneNumberIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1UpdateUserPhoneNumberResult": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "Unique identifier of the User whose phone number was updated." + } + }, + "required": ["userId"] + }, + "v1UpdateUserRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_UPDATE_USER"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1UpdateUserIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1UpdateUserResult": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "A User ID." + } + }, + "required": ["userId"] + }, + "v1UpdateUserTagIntent": { + "type": "object", + "properties": { + "userTagId": { + "type": "string", + "description": "Unique identifier for a given User Tag." + }, + "newUserTagName": { + "type": "string", + "description": "The new, human-readable name for the tag with the given ID." + }, + "addUserIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of User IDs to add this tag to." + }, + "removeUserIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of User IDs to remove this tag from." + } + }, + "required": ["userTagId", "addUserIds", "removeUserIds"] + }, + "v1UpdateUserTagRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_UPDATE_USER_TAG"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1UpdateUserTagIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1UpdateUserTagResult": { + "type": "object", + "properties": { + "userTagId": { + "type": "string", + "description": "Unique identifier for a given User Tag." + } + }, + "required": ["userTagId"] + }, + "v1UpdateWalletIntent": { + "type": "object", + "properties": { + "walletId": { + "type": "string", + "description": "Unique identifier for a given Wallet." + }, + "walletName": { + "type": "string", + "description": "Human-readable name for a Wallet." + } + }, + "required": ["walletId"] + }, + "v1UpdateWalletRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_UPDATE_WALLET"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1UpdateWalletIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1UpdateWalletResult": { + "type": "object", + "properties": { + "walletId": { + "type": "string", + "description": "A Wallet ID." + } + }, + "required": ["walletId"] + }, + "v1User": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "Unique identifier for a given User." + }, + "userName": { + "type": "string", + "description": "Human-readable name for a User." + }, + "userEmail": { + "type": "string", + "description": "The user's email address." + }, + "userPhoneNumber": { + "type": "string", + "description": "The user's phone number in E.164 format e.g. +13214567890" + }, + "authenticators": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1Authenticator" + }, + "description": "A list of Authenticator parameters." + }, + "apiKeys": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1ApiKey" + }, + "description": "A list of API Key parameters. This field, if not needed, should be an empty array in your request body." + }, + "userTags": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of User Tag IDs." + }, + "oauthProviders": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1OauthProvider" + }, + "description": "A list of Oauth Providers." + }, + "createdAt": { + "$ref": "#/definitions/externaldatav1Timestamp" + }, + "updatedAt": { + "$ref": "#/definitions/externaldatav1Timestamp" + } + }, + "required": [ + "userId", + "userName", + "authenticators", + "apiKeys", + "userTags", + "oauthProviders", + "createdAt", + "updatedAt" + ] + }, + "v1UserParams": { + "type": "object", + "properties": { + "userName": { + "type": "string", + "description": "Human-readable name for a User." + }, + "userEmail": { + "type": "string", + "description": "The user's email address." + }, + "accessType": { + "$ref": "#/definitions/v1AccessType", + "description": "The User's permissible access method(s)." + }, + "apiKeys": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/apiApiKeyParams" + }, + "description": "A list of API Key parameters. This field, if not needed, should be an empty array in your request body." + }, + "authenticators": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1AuthenticatorParams" + }, + "description": "A list of Authenticator parameters. This field, if not needed, should be an empty array in your request body." + }, + "userTags": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of User Tag IDs. This field, if not needed, should be an empty array in your request body." + } + }, + "required": [ + "userName", + "accessType", + "apiKeys", + "authenticators", + "userTags" + ] + }, + "v1UserParamsV2": { + "type": "object", + "properties": { + "userName": { + "type": "string", + "description": "Human-readable name for a User." + }, + "userEmail": { + "type": "string", + "description": "The user's email address." + }, + "apiKeys": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/apiApiKeyParams" + }, + "description": "A list of API Key parameters. This field, if not needed, should be an empty array in your request body." + }, + "authenticators": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1AuthenticatorParamsV2" + }, + "description": "A list of Authenticator parameters. This field, if not needed, should be an empty array in your request body." + }, + "userTags": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of User Tag IDs. This field, if not needed, should be an empty array in your request body." + } + }, + "required": ["userName", "apiKeys", "authenticators", "userTags"] + }, + "v1UserParamsV3": { + "type": "object", + "properties": { + "userName": { + "type": "string", + "description": "Human-readable name for a User." + }, + "userEmail": { + "type": "string", + "description": "The user's email address." + }, + "userPhoneNumber": { + "type": "string", + "description": "The user's phone number in E.164 format e.g. +13214567890" + }, + "apiKeys": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1ApiKeyParamsV2" + }, + "description": "A list of API Key parameters. This field, if not needed, should be an empty array in your request body." + }, + "authenticators": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1AuthenticatorParamsV2" + }, + "description": "A list of Authenticator parameters. This field, if not needed, should be an empty array in your request body." + }, + "oauthProviders": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1OauthProviderParams" + }, + "description": "A list of Oauth providers. This field, if not needed, should be an empty array in your request body." + }, + "userTags": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of User Tag IDs. This field, if not needed, should be an empty array in your request body." + } + }, + "required": [ + "userName", + "apiKeys", + "authenticators", + "oauthProviders", + "userTags" + ] + }, + "v1VerifyOtpIntent": { + "type": "object", + "properties": { + "otpId": { + "type": "string", + "description": "ID representing the result of an init OTP activity." + }, + "otpCode": { + "type": "string", + "description": "OTP sent out to a user's contact (email or SMS)" + }, + "expirationSeconds": { + "type": "string", + "description": "Expiration window (in seconds) indicating how long the verification token is valid for. If not provided, a default of 1 hour will be used. Maximum value is 86400 seconds (24 hours)" + } + }, + "required": ["otpId", "otpCode"] + }, + "v1VerifyOtpRequest": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["ACTIVITY_TYPE_VERIFY_OTP"] + }, + "timestampMs": { + "type": "string", + "description": "Timestamp (in milliseconds) of the request, used to verify liveness of user requests." + }, + "organizationId": { + "type": "string", + "description": "Unique identifier for a given Organization." + }, + "parameters": { + "$ref": "#/definitions/v1VerifyOtpIntent" + } + }, + "required": ["type", "timestampMs", "organizationId", "parameters"] + }, + "v1VerifyOtpResult": { + "type": "object", + "properties": { + "verificationToken": { + "type": "string", + "description": "Signed JWT containing a unique id, expiry, verification type, contact. Verification status of a user is updated when the token is consumed (in OTP_LOGIN requests)" + } + }, + "required": ["verificationToken"] + }, + "v1Vote": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique identifier for a given Vote object." + }, + "userId": { + "type": "string", + "description": "Unique identifier for a given User." + }, + "user": { + "$ref": "#/definitions/v1User", + "description": "Web and/or API user within your Organization." + }, + "activityId": { + "type": "string", + "description": "Unique identifier for a given Activity object." + }, + "selection": { + "type": "string", + "enum": ["VOTE_SELECTION_APPROVED", "VOTE_SELECTION_REJECTED"] + }, + "message": { + "type": "string", + "description": "The raw message being signed within a Vote." + }, + "publicKey": { + "type": "string", + "description": "The public component of a cryptographic key pair used to sign messages and transactions." + }, + "signature": { + "type": "string", + "description": "The signature applied to a particular vote." + }, + "scheme": { + "type": "string", + "description": "Method used to produce a signature." + }, + "createdAt": { + "$ref": "#/definitions/externaldatav1Timestamp" + } + }, + "required": [ + "id", + "userId", + "user", + "activityId", + "selection", + "message", + "publicKey", + "signature", + "scheme", + "createdAt" + ] + }, + "v1Wallet": { + "type": "object", + "properties": { + "walletId": { + "type": "string", + "description": "Unique identifier for a given Wallet." + }, + "walletName": { + "type": "string", + "description": "Human-readable name for a Wallet." + }, + "createdAt": { + "$ref": "#/definitions/externaldatav1Timestamp" + }, + "updatedAt": { + "$ref": "#/definitions/externaldatav1Timestamp" + }, + "exported": { + "type": "boolean", + "description": "True when a given Wallet is exported, false otherwise." + }, + "imported": { + "type": "boolean", + "description": "True when a given Wallet is imported, false otherwise." + } + }, + "required": [ + "walletId", + "walletName", + "createdAt", + "updatedAt", + "exported", + "imported" + ] + }, + "v1WalletAccount": { + "type": "object", + "properties": { + "walletAccountId": { + "type": "string", + "description": "Unique identifier for a given Wallet Account." + }, + "organizationId": { + "type": "string", + "description": "The Organization the Account belongs to." + }, + "walletId": { + "type": "string", + "description": "The Wallet the Account was derived from." + }, + "curve": { + "$ref": "#/definitions/v1Curve", + "description": "Cryptographic curve used to generate the Account." + }, + "pathFormat": { + "$ref": "#/definitions/v1PathFormat", + "description": "Path format used to generate the Account." + }, + "path": { + "type": "string", + "description": "Path used to generate the Account." + }, + "addressFormat": { + "$ref": "#/definitions/v1AddressFormat", + "description": "Address format used to generate the Account." + }, + "address": { + "type": "string", + "description": "Address generated using the Wallet seed and Account parameters." + }, + "createdAt": { + "$ref": "#/definitions/externaldatav1Timestamp" + }, + "updatedAt": { + "$ref": "#/definitions/externaldatav1Timestamp" + }, + "publicKey": { + "type": "string", + "description": "The public component of this wallet account's underlying cryptographic key pair." + } + }, + "required": [ + "walletAccountId", + "organizationId", + "walletId", + "curve", + "pathFormat", + "path", + "addressFormat", + "address", + "createdAt", + "updatedAt" + ] + }, + "v1WalletAccountParams": { + "type": "object", + "properties": { + "curve": { + "$ref": "#/definitions/v1Curve", + "description": "Cryptographic curve used to generate a wallet Account." + }, + "pathFormat": { + "$ref": "#/definitions/v1PathFormat", + "description": "Path format used to generate a wallet Account." + }, + "path": { + "type": "string", + "description": "Path used to generate a wallet Account." + }, + "addressFormat": { + "$ref": "#/definitions/v1AddressFormat", + "description": "Address format used to generate a wallet Acccount." + } + }, + "required": ["curve", "pathFormat", "path", "addressFormat"] + }, + "v1WalletKitSettingsParams": { + "type": "object", + "properties": { + "enabledSocialProviders": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of enabled social login providers (e.g., 'apple', 'google', 'facebook')", + "title": "Enabled Social Providers" + } + } + }, + "v1WalletParams": { + "type": "object", + "properties": { + "walletName": { + "type": "string", + "description": "Human-readable name for a Wallet." + }, + "accounts": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/v1WalletAccountParams" + }, + "description": "A list of wallet Accounts. This field, if not needed, should be an empty array in your request body." + }, + "mnemonicLength": { + "type": "integer", + "format": "int32", + "description": "Length of mnemonic to generate the Wallet seed. Defaults to 12. Accepted values: 12, 15, 18, 21, 24." + } + }, + "required": ["walletName", "accounts"] + }, + "v1WalletResult": { + "type": "object", + "properties": { + "walletId": { + "type": "string" + }, + "addresses": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of account addresses." + } + }, + "required": ["walletId", "addresses"] + }, + "v1WebAuthnStamp": { + "type": "object", + "properties": { + "credentialId": { + "type": "string", + "description": "A base64 url encoded Unique identifier for a given credential." + }, + "clientDataJson": { + "type": "string", + "description": "A base64 encoded payload containing metadata about the signing context and the challenge." + }, + "authenticatorData": { + "type": "string", + "description": "A base64 encoded payload containing metadata about the authenticator." + }, + "signature": { + "type": "string", + "description": "The base64 url encoded signature bytes contained within the WebAuthn assertion response." + } + }, + "required": [ + "credentialId", + "clientDataJson", + "authenticatorData", + "signature" + ] + } + }, + "securityDefinitions": { + "ApiKeyAuth": { + "type": "apiKey", + "name": "X-Stamp", + "in": "header" + }, + "AuthenticatorAuth": { + "type": "apiKey", + "name": "X-Stamp-WebAuthn", + "in": "header" + } + }, + "security": [ + { + "ApiKeyAuth": [] + }, + { + "AuthenticatorAuth": [] + } + ], + "x-tagGroups": [ + { + "name": "ORGANIZATIONS", + "tags": ["Organizations", "Invitations", "Policies", "Features"] + }, + { + "name": "WALLETS AND PRIVATE KEYS", + "tags": ["Wallets", "Signing", "Private Keys", "Private Key Tags"] + }, + { + "name": "USERS", + "tags": ["Users", "User Tags", "User Recovery", "User Auth"] + }, + { + "name": "CREDENTIALS", + "tags": ["Authenticators", "API Keys", "Sessions"] + }, + { + "name": "ACTIVITIES", + "tags": ["Activities", "Consensus"] + } + ] +} diff --git a/packages/core/src/__inputs__/public_api.types.ts b/packages/core/src/__inputs__/public_api.types.ts new file mode 100644 index 000000000..b019915aa --- /dev/null +++ b/packages/core/src/__inputs__/public_api.types.ts @@ -0,0 +1,5413 @@ +/** + * This file was auto-generated by openapi-typescript. + * Do not make direct changes to the file. + */ + +export type paths = { + "/public/v1/query/get_activity": { + /** Get details about an Activity */ + post: operations["PublicApiService_GetActivity"]; + }; + "/public/v1/query/get_api_key": { + /** Get details about an API key */ + post: operations["PublicApiService_GetApiKey"]; + }; + "/public/v1/query/get_api_keys": { + /** Get details about API keys for a user */ + post: operations["PublicApiService_GetApiKeys"]; + }; + "/public/v1/query/get_attestation": { + /** Get the attestation document corresponding to an enclave. */ + post: operations["PublicApiService_GetAttestationDocument"]; + }; + "/public/v1/query/get_authenticator": { + /** Get details about an authenticator */ + post: operations["PublicApiService_GetAuthenticator"]; + }; + "/public/v1/query/get_authenticators": { + /** Get details about authenticators for a user */ + post: operations["PublicApiService_GetAuthenticators"]; + }; + "/public/v1/query/get_oauth_providers": { + /** Get details about Oauth providers for a user */ + post: operations["PublicApiService_GetOauthProviders"]; + }; + "/public/v1/query/get_organization": { + /** Get details about an Organization */ + post: operations["PublicApiService_GetOrganization"]; + }; + "/public/v1/query/get_organization_configs": { + /** Get quorum settings and features for an organization */ + post: operations["PublicApiService_GetOrganizationConfigs"]; + }; + "/public/v1/query/get_policy": { + /** Get details about a Policy */ + post: operations["PublicApiService_GetPolicy"]; + }; + "/public/v1/query/get_private_key": { + /** Get details about a Private Key */ + post: operations["PublicApiService_GetPrivateKey"]; + }; + "/public/v1/query/get_proxy_auth_config": { + /** Get the proxy-auth configuration (allowed origins, etc.) for an Organization */ + post: operations["PublicApiService_GetProxyAuthConfig"]; + }; + "/public/v1/query/get_smart_contract_interface": { + /** Get details about a Smart Contract Interface */ + post: operations["PublicApiService_GetSmartContractInterface"]; + }; + "/public/v1/query/get_user": { + /** Get details about a User */ + post: operations["PublicApiService_GetUser"]; + }; + "/public/v1/query/get_wallet": { + /** Get details about a Wallet */ + post: operations["PublicApiService_GetWallet"]; + }; + "/public/v1/query/get_wallet_account": { + /** Get a single wallet account */ + post: operations["PublicApiService_GetWalletAccount"]; + }; + "/public/v1/query/list_activities": { + /** List all Activities within an Organization */ + post: operations["PublicApiService_GetActivities"]; + }; + "/public/v1/query/list_policies": { + /** List all Policies within an Organization */ + post: operations["PublicApiService_GetPolicies"]; + }; + "/public/v1/query/list_private_key_tags": { + /** List all Private Key Tags within an Organization */ + post: operations["PublicApiService_ListPrivateKeyTags"]; + }; + "/public/v1/query/list_private_keys": { + /** List all Private Keys within an Organization */ + post: operations["PublicApiService_GetPrivateKeys"]; + }; + "/public/v1/query/list_smart_contract_interfaces": { + /** List all Smart Contract Interfaces within an Organization */ + post: operations["PublicApiService_GetSmartContractInterfaces"]; + }; + "/public/v1/query/list_suborgs": { + /** Get all suborg IDs associated given a parent org ID and an optional filter. */ + post: operations["PublicApiService_GetSubOrgIds"]; + }; + "/public/v1/query/list_user_tags": { + /** List all User Tags within an Organization */ + post: operations["PublicApiService_ListUserTags"]; + }; + "/public/v1/query/list_users": { + /** List all Users within an Organization */ + post: operations["PublicApiService_GetUsers"]; + }; + "/public/v1/query/list_verified_suborgs": { + /** Get all email or phone verified suborg IDs associated given a parent org ID. */ + post: operations["PublicApiService_GetVerifiedSubOrgIds"]; + }; + "/public/v1/query/list_wallet_accounts": { + /** List all Accounts within a Wallet */ + post: operations["PublicApiService_GetWalletAccounts"]; + }; + "/public/v1/query/list_wallets": { + /** List all Wallets within an Organization */ + post: operations["PublicApiService_GetWallets"]; + }; + "/public/v1/query/whoami": { + /** Get basic information about your current API or WebAuthN user and their organization. Affords Sub-Organization look ups via Parent Organization for WebAuthN or API key users. */ + post: operations["PublicApiService_GetWhoami"]; + }; + "/public/v1/submit/approve_activity": { + /** Approve an Activity */ + post: operations["PublicApiService_ApproveActivity"]; + }; + "/public/v1/submit/create_api_keys": { + /** Add api keys to an existing User */ + post: operations["PublicApiService_CreateApiKeys"]; + }; + "/public/v1/submit/create_api_only_users": { + /** Create API-only Users in an existing Organization */ + post: operations["PublicApiService_CreateApiOnlyUsers"]; + }; + "/public/v1/submit/create_authenticators": { + /** Create Authenticators to authenticate requests to Turnkey */ + post: operations["PublicApiService_CreateAuthenticators"]; + }; + "/public/v1/submit/create_invitations": { + /** Create Invitations to join an existing Organization */ + post: operations["PublicApiService_CreateInvitations"]; + }; + "/public/v1/submit/create_oauth_providers": { + /** Creates Oauth providers for a specified user - BETA */ + post: operations["PublicApiService_CreateOauthProviders"]; + }; + "/public/v1/submit/create_policies": { + /** Create new Policies */ + post: operations["PublicApiService_CreatePolicies"]; + }; + "/public/v1/submit/create_policy": { + /** Create a new Policy */ + post: operations["PublicApiService_CreatePolicy"]; + }; + "/public/v1/submit/create_private_key_tag": { + /** Create a private key tag and add it to private keys. */ + post: operations["PublicApiService_CreatePrivateKeyTag"]; + }; + "/public/v1/submit/create_private_keys": { + /** Create new Private Keys */ + post: operations["PublicApiService_CreatePrivateKeys"]; + }; + "/public/v1/submit/create_read_only_session": { + /** Create a read only session for a user (valid for 1 hour) */ + post: operations["PublicApiService_CreateReadOnlySession"]; + }; + "/public/v1/submit/create_read_write_session": { + /** Create a read write session for a user */ + post: operations["PublicApiService_CreateReadWriteSession"]; + }; + "/public/v1/submit/create_smart_contract_interface": { + /** Create an ABI/IDL in JSON */ + post: operations["PublicApiService_CreateSmartContractInterface"]; + }; + "/public/v1/submit/create_sub_organization": { + /** Create a new Sub-Organization */ + post: operations["PublicApiService_CreateSubOrganization"]; + }; + "/public/v1/submit/create_user_tag": { + /** Create a user tag and add it to users. */ + post: operations["PublicApiService_CreateUserTag"]; + }; + "/public/v1/submit/create_users": { + /** Create Users in an existing Organization */ + post: operations["PublicApiService_CreateUsers"]; + }; + "/public/v1/submit/create_wallet": { + /** Create a Wallet and derive addresses */ + post: operations["PublicApiService_CreateWallet"]; + }; + "/public/v1/submit/create_wallet_accounts": { + /** Derive additional addresses using an existing wallet */ + post: operations["PublicApiService_CreateWalletAccounts"]; + }; + "/public/v1/submit/delete_api_keys": { + /** Remove api keys from a User */ + post: operations["PublicApiService_DeleteApiKeys"]; + }; + "/public/v1/submit/delete_authenticators": { + /** Remove authenticators from a User */ + post: operations["PublicApiService_DeleteAuthenticators"]; + }; + "/public/v1/submit/delete_invitation": { + /** Delete an existing Invitation */ + post: operations["PublicApiService_DeleteInvitation"]; + }; + "/public/v1/submit/delete_oauth_providers": { + /** Removes Oauth providers for a specified user - BETA */ + post: operations["PublicApiService_DeleteOauthProviders"]; + }; + "/public/v1/submit/delete_policy": { + /** Delete an existing Policy */ + post: operations["PublicApiService_DeletePolicy"]; + }; + "/public/v1/submit/delete_private_key_tags": { + /** Delete Private Key Tags within an Organization */ + post: operations["PublicApiService_DeletePrivateKeyTags"]; + }; + "/public/v1/submit/delete_private_keys": { + /** Deletes private keys for an organization */ + post: operations["PublicApiService_DeletePrivateKeys"]; + }; + "/public/v1/submit/delete_smart_contract_interface": { + /** Delete a Smart Contract Interface */ + post: operations["PublicApiService_DeleteSmartContractInterface"]; + }; + "/public/v1/submit/delete_sub_organization": { + /** Deletes a sub organization */ + post: operations["PublicApiService_DeleteSubOrganization"]; + }; + "/public/v1/submit/delete_user_tags": { + /** Delete User Tags within an Organization */ + post: operations["PublicApiService_DeleteUserTags"]; + }; + "/public/v1/submit/delete_users": { + /** Delete Users within an Organization */ + post: operations["PublicApiService_DeleteUsers"]; + }; + "/public/v1/submit/delete_wallets": { + /** Deletes wallets for an organization */ + post: operations["PublicApiService_DeleteWallets"]; + }; + "/public/v1/submit/disable_user_initiated_auth": { + /** Disable User Initiated Auth */ + post: operations["PublicApiService_DisableUserInitiatedAuth"]; + }; + "/public/v1/submit/email_auth": { + /** Authenticate a user via Email */ + post: operations["PublicApiService_EmailAuth"]; + }; + "/public/v1/submit/enable_user_initiated_auth": { + /** Enable User Initiated Auth */ + post: operations["PublicApiService_EnableUserInitiatedAuth"]; + }; + "/public/v1/submit/export_private_key": { + /** Exports a Private Key */ + post: operations["PublicApiService_ExportPrivateKey"]; + }; + "/public/v1/submit/export_wallet": { + /** Exports a Wallet */ + post: operations["PublicApiService_ExportWallet"]; + }; + "/public/v1/submit/export_wallet_account": { + /** Exports a Wallet Account */ + post: operations["PublicApiService_ExportWalletAccount"]; + }; + "/public/v1/submit/import_private_key": { + /** Imports a private key */ + post: operations["PublicApiService_ImportPrivateKey"]; + }; + "/public/v1/submit/import_wallet": { + /** Imports a wallet */ + post: operations["PublicApiService_ImportWallet"]; + }; + "/public/v1/submit/init_fiat_on_ramp": { + /** Initiate a fiat on ramp flow */ + post: operations["PublicApiService_InitFiatOnRamp"]; + }; + "/public/v1/submit/init_import_private_key": { + /** Initializes a new private key import */ + post: operations["PublicApiService_InitImportPrivateKey"]; + }; + "/public/v1/submit/init_import_wallet": { + /** Initializes a new wallet import */ + post: operations["PublicApiService_InitImportWallet"]; + }; + "/public/v1/submit/init_otp": { + /** Initiate a Generic OTP activity */ + post: operations["PublicApiService_InitOtp"]; + }; + "/public/v1/submit/init_otp_auth": { + /** Initiate an OTP auth activity */ + post: operations["PublicApiService_InitOtpAuth"]; + }; + "/public/v1/submit/init_user_email_recovery": { + /** Initializes a new email recovery */ + post: operations["PublicApiService_InitUserEmailRecovery"]; + }; + "/public/v1/submit/oauth": { + /** Authenticate a user with an Oidc token (Oauth) - BETA */ + post: operations["PublicApiService_Oauth"]; + }; + "/public/v1/submit/oauth_login": { + /** Create an Oauth session for a user */ + post: operations["PublicApiService_OauthLogin"]; + }; + "/public/v1/submit/otp_auth": { + /** Authenticate a user with an OTP code sent via email or SMS */ + post: operations["PublicApiService_OtpAuth"]; + }; + "/public/v1/submit/otp_login": { + /** Create an OTP session for a user */ + post: operations["PublicApiService_OtpLogin"]; + }; + "/public/v1/submit/recover_user": { + /** Completes the process of recovering a user by adding an authenticator */ + post: operations["PublicApiService_RecoverUser"]; + }; + "/public/v1/submit/reject_activity": { + /** Reject an Activity */ + post: operations["PublicApiService_RejectActivity"]; + }; + "/public/v1/submit/remove_organization_feature": { + /** Removes an organization feature. This activity must be approved by the current root quorum. */ + post: operations["PublicApiService_RemoveOrganizationFeature"]; + }; + "/public/v1/submit/set_organization_feature": { + /** Sets an organization feature. This activity must be approved by the current root quorum. */ + post: operations["PublicApiService_SetOrganizationFeature"]; + }; + "/public/v1/submit/sign_raw_payload": { + /** Sign a raw payload */ + post: operations["PublicApiService_SignRawPayload"]; + }; + "/public/v1/submit/sign_raw_payloads": { + /** Sign multiple raw payloads with the same signing parameters */ + post: operations["PublicApiService_SignRawPayloads"]; + }; + "/public/v1/submit/sign_transaction": { + /** Sign a transaction */ + post: operations["PublicApiService_SignTransaction"]; + }; + "/public/v1/submit/stamp_login": { + /** Create a session for a user through stamping client side (api key, wallet client, or passkey client) */ + post: operations["PublicApiService_StampLogin"]; + }; + "/public/v1/submit/update_policy": { + /** Update an existing Policy */ + post: operations["PublicApiService_UpdatePolicy"]; + }; + "/public/v1/submit/update_private_key_tag": { + /** Update human-readable name or associated private keys. Note that this activity is atomic: all of the updates will succeed at once, or all of them will fail. */ + post: operations["PublicApiService_UpdatePrivateKeyTag"]; + }; + "/public/v1/submit/update_proxy_auth_config": { + /** Update the proxy-auth configuration (allowed origins, etc.) for an Organization */ + post: operations["PublicApiService_UpdateProxyAuthConfig"]; + }; + "/public/v1/submit/update_root_quorum": { + /** Set the threshold and members of the root quorum. This activity must be approved by the current root quorum. */ + post: operations["PublicApiService_UpdateRootQuorum"]; + }; + "/public/v1/submit/update_user": { + /** Update a User in an existing Organization */ + post: operations["PublicApiService_UpdateUser"]; + }; + "/public/v1/submit/update_user_email": { + /** Update a User's email in an existing Organization */ + post: operations["PublicApiService_UpdateUserEmail"]; + }; + "/public/v1/submit/update_user_name": { + /** Update a User's name in an existing Organization */ + post: operations["PublicApiService_UpdateUserName"]; + }; + "/public/v1/submit/update_user_phone_number": { + /** Update a User's phone number in an existing Organization */ + post: operations["PublicApiService_UpdateUserPhoneNumber"]; + }; + "/public/v1/submit/update_user_tag": { + /** Update human-readable name or associated users. Note that this activity is atomic: all of the updates will succeed at once, or all of them will fail. */ + post: operations["PublicApiService_UpdateUserTag"]; + }; + "/public/v1/submit/update_wallet": { + /** Update a wallet for an organization */ + post: operations["PublicApiService_UpdateWallet"]; + }; + "/public/v1/submit/verify_otp": { + /** Verify a Generic OTP */ + post: operations["PublicApiService_VerifyOtp"]; + }; + "/tkhq/api/v1/noop-codegen-anchor": { + post: operations["PublicApiService_NOOPCodegenAnchor"]; + }; + "/tkhq/api/v1/test_rate_limits": { + /** Set a rate local rate limit just on the current endpoint, for purposes of testing with Vivosuite */ + post: operations["PublicApiService_TestRateLimits"]; + }; +}; + +export type definitions = { + apiApiKeyParams: { + /** @description Human-readable name for an API Key. */ + apiKeyName: string; + /** @description The public component of a cryptographic key pair used to sign messages and transactions. */ + publicKey: string; + /** @description Optional window (in seconds) indicating how long the API Key should last. */ + expirationSeconds?: string; + }; + billingActivateBillingTierIntent: { + /** @description The product that the customer wants to subscribe to. */ + productId: string; + }; + billingActivateBillingTierResult: { + /** @description The id of the product being subscribed to. */ + productId: string; + }; + billingDeletePaymentMethodIntent: { + /** @description The payment method that the customer wants to remove. */ + paymentMethodId: string; + }; + billingDeletePaymentMethodResult: { + /** @description The payment method that was removed. */ + paymentMethodId: string; + }; + billingSetPaymentMethodIntent: { + /** @description The account number of the customer's credit card. */ + number: string; + /** @description The verification digits of the customer's credit card. */ + cvv: string; + /** @description The month that the credit card expires. */ + expiryMonth: string; + /** @description The year that the credit card expires. */ + expiryYear: string; + /** @description The email that will receive invoices for the credit card. */ + cardHolderEmail: string; + /** @description The name associated with the credit card. */ + cardHolderName: string; + }; + billingSetPaymentMethodIntentV2: { + /** @description The id of the payment method that was created clientside. */ + paymentMethodId: string; + /** @description The email that will receive invoices for the credit card. */ + cardHolderEmail: string; + /** @description The name associated with the credit card. */ + cardHolderName: string; + }; + billingSetPaymentMethodResult: { + /** @description The last four digits of the credit card added. */ + lastFour: string; + /** @description The name associated with the payment method. */ + cardHolderName: string; + /** @description The email address associated with the payment method. */ + cardHolderEmail: string; + }; + datav1Tag: { + /** @description Unique identifier for a given Tag. */ + tagId: string; + /** @description Human-readable name for a Tag. */ + tagName: string; + tagType: definitions["v1TagType"]; + createdAt: definitions["externaldatav1Timestamp"]; + updatedAt: definitions["externaldatav1Timestamp"]; + }; + externaldatav1Address: { + format?: definitions["v1AddressFormat"]; + address?: string; + }; + externaldatav1Credential: { + /** @description The public component of a cryptographic key pair used to sign messages and transactions. */ + publicKey: string; + type: definitions["v1CredentialType"]; + }; + externaldatav1Quorum: { + /** + * Format: int32 + * @description Count of unique approvals required to meet quorum. + */ + threshold: number; + /** @description Unique identifiers of quorum set members. */ + userIds: string[]; + }; + externaldatav1Timestamp: { + seconds: string; + nanos: string; + }; + immutableactivityv1Address: { + format?: definitions["v1AddressFormat"]; + address?: string; + }; + protobufAny: { + "@type"?: string; + } & { [key: string]: unknown }; + rpcStatus: { + /** Format: int32 */ + code?: number; + message?: string; + details?: definitions["protobufAny"][]; + }; + v1AcceptInvitationIntent: { + /** @description Unique identifier for a given Invitation object. */ + invitationId: string; + /** @description Unique identifier for a given User. */ + userId: string; + /** @description WebAuthN hardware devices that can be used to log in to the Turnkey web app. */ + authenticator: definitions["v1AuthenticatorParams"]; + }; + v1AcceptInvitationIntentV2: { + /** @description Unique identifier for a given Invitation object. */ + invitationId: string; + /** @description Unique identifier for a given User. */ + userId: string; + /** @description WebAuthN hardware devices that can be used to log in to the Turnkey web app. */ + authenticator: definitions["v1AuthenticatorParamsV2"]; + }; + v1AcceptInvitationResult: { + /** @description Unique identifier for a given Invitation. */ + invitationId: string; + /** @description Unique identifier for a given User. */ + userId: string; + }; + /** @enum {string} */ + v1AccessType: "ACCESS_TYPE_WEB" | "ACCESS_TYPE_API" | "ACCESS_TYPE_ALL"; + v1Activity: { + /** @description Unique identifier for a given Activity object. */ + id: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + /** @description The current processing status of a specified Activity. */ + status: definitions["v1ActivityStatus"]; + /** @description Type of Activity, such as Add User, or Sign Transaction. */ + type: definitions["v1ActivityType"]; + /** @description Intent object crafted by Turnkey based on the user request, used to assess the permissibility of an action. */ + intent: definitions["v1Intent"]; + /** @description Result of the intended action. */ + result: definitions["v1Result"]; + /** @description A list of objects representing a particular User's approval or rejection of a Consensus request, including all relevant metadata. */ + votes: definitions["v1Vote"][]; + /** @description An artifact verifying a User's action. */ + fingerprint: string; + canApprove: boolean; + canReject: boolean; + createdAt: definitions["externaldatav1Timestamp"]; + updatedAt: definitions["externaldatav1Timestamp"]; + /** @description Failure reason of the intended action. */ + failure?: definitions["rpcStatus"]; + }; + v1ActivityResponse: { + /** @description An action that can that can be taken within the Turnkey infrastructure. */ + activity: definitions["v1Activity"]; + }; + /** @enum {string} */ + v1ActivityStatus: + | "ACTIVITY_STATUS_CREATED" + | "ACTIVITY_STATUS_PENDING" + | "ACTIVITY_STATUS_COMPLETED" + | "ACTIVITY_STATUS_FAILED" + | "ACTIVITY_STATUS_CONSENSUS_NEEDED" + | "ACTIVITY_STATUS_REJECTED"; + /** @enum {string} */ + v1ActivityType: + | "ACTIVITY_TYPE_CREATE_API_KEYS" + | "ACTIVITY_TYPE_CREATE_USERS" + | "ACTIVITY_TYPE_CREATE_PRIVATE_KEYS" + | "ACTIVITY_TYPE_SIGN_RAW_PAYLOAD" + | "ACTIVITY_TYPE_CREATE_INVITATIONS" + | "ACTIVITY_TYPE_ACCEPT_INVITATION" + | "ACTIVITY_TYPE_CREATE_POLICY" + | "ACTIVITY_TYPE_DISABLE_PRIVATE_KEY" + | "ACTIVITY_TYPE_DELETE_USERS" + | "ACTIVITY_TYPE_DELETE_API_KEYS" + | "ACTIVITY_TYPE_DELETE_INVITATION" + | "ACTIVITY_TYPE_DELETE_ORGANIZATION" + | "ACTIVITY_TYPE_DELETE_POLICY" + | "ACTIVITY_TYPE_CREATE_USER_TAG" + | "ACTIVITY_TYPE_DELETE_USER_TAGS" + | "ACTIVITY_TYPE_CREATE_ORGANIZATION" + | "ACTIVITY_TYPE_SIGN_TRANSACTION" + | "ACTIVITY_TYPE_APPROVE_ACTIVITY" + | "ACTIVITY_TYPE_REJECT_ACTIVITY" + | "ACTIVITY_TYPE_DELETE_AUTHENTICATORS" + | "ACTIVITY_TYPE_CREATE_AUTHENTICATORS" + | "ACTIVITY_TYPE_CREATE_PRIVATE_KEY_TAG" + | "ACTIVITY_TYPE_DELETE_PRIVATE_KEY_TAGS" + | "ACTIVITY_TYPE_SET_PAYMENT_METHOD" + | "ACTIVITY_TYPE_ACTIVATE_BILLING_TIER" + | "ACTIVITY_TYPE_DELETE_PAYMENT_METHOD" + | "ACTIVITY_TYPE_CREATE_POLICY_V2" + | "ACTIVITY_TYPE_CREATE_POLICY_V3" + | "ACTIVITY_TYPE_CREATE_API_ONLY_USERS" + | "ACTIVITY_TYPE_UPDATE_ROOT_QUORUM" + | "ACTIVITY_TYPE_UPDATE_USER_TAG" + | "ACTIVITY_TYPE_UPDATE_PRIVATE_KEY_TAG" + | "ACTIVITY_TYPE_CREATE_AUTHENTICATORS_V2" + | "ACTIVITY_TYPE_CREATE_ORGANIZATION_V2" + | "ACTIVITY_TYPE_CREATE_USERS_V2" + | "ACTIVITY_TYPE_ACCEPT_INVITATION_V2" + | "ACTIVITY_TYPE_CREATE_SUB_ORGANIZATION" + | "ACTIVITY_TYPE_CREATE_SUB_ORGANIZATION_V2" + | "ACTIVITY_TYPE_UPDATE_ALLOWED_ORIGINS" + | "ACTIVITY_TYPE_CREATE_PRIVATE_KEYS_V2" + | "ACTIVITY_TYPE_UPDATE_USER" + | "ACTIVITY_TYPE_UPDATE_POLICY" + | "ACTIVITY_TYPE_SET_PAYMENT_METHOD_V2" + | "ACTIVITY_TYPE_CREATE_SUB_ORGANIZATION_V3" + | "ACTIVITY_TYPE_CREATE_WALLET" + | "ACTIVITY_TYPE_CREATE_WALLET_ACCOUNTS" + | "ACTIVITY_TYPE_INIT_USER_EMAIL_RECOVERY" + | "ACTIVITY_TYPE_RECOVER_USER" + | "ACTIVITY_TYPE_SET_ORGANIZATION_FEATURE" + | "ACTIVITY_TYPE_REMOVE_ORGANIZATION_FEATURE" + | "ACTIVITY_TYPE_SIGN_RAW_PAYLOAD_V2" + | "ACTIVITY_TYPE_SIGN_TRANSACTION_V2" + | "ACTIVITY_TYPE_EXPORT_PRIVATE_KEY" + | "ACTIVITY_TYPE_EXPORT_WALLET" + | "ACTIVITY_TYPE_CREATE_SUB_ORGANIZATION_V4" + | "ACTIVITY_TYPE_EMAIL_AUTH" + | "ACTIVITY_TYPE_EXPORT_WALLET_ACCOUNT" + | "ACTIVITY_TYPE_INIT_IMPORT_WALLET" + | "ACTIVITY_TYPE_IMPORT_WALLET" + | "ACTIVITY_TYPE_INIT_IMPORT_PRIVATE_KEY" + | "ACTIVITY_TYPE_IMPORT_PRIVATE_KEY" + | "ACTIVITY_TYPE_CREATE_POLICIES" + | "ACTIVITY_TYPE_SIGN_RAW_PAYLOADS" + | "ACTIVITY_TYPE_CREATE_READ_ONLY_SESSION" + | "ACTIVITY_TYPE_CREATE_OAUTH_PROVIDERS" + | "ACTIVITY_TYPE_DELETE_OAUTH_PROVIDERS" + | "ACTIVITY_TYPE_CREATE_SUB_ORGANIZATION_V5" + | "ACTIVITY_TYPE_OAUTH" + | "ACTIVITY_TYPE_CREATE_API_KEYS_V2" + | "ACTIVITY_TYPE_CREATE_READ_WRITE_SESSION" + | "ACTIVITY_TYPE_EMAIL_AUTH_V2" + | "ACTIVITY_TYPE_CREATE_SUB_ORGANIZATION_V6" + | "ACTIVITY_TYPE_DELETE_PRIVATE_KEYS" + | "ACTIVITY_TYPE_DELETE_WALLETS" + | "ACTIVITY_TYPE_CREATE_READ_WRITE_SESSION_V2" + | "ACTIVITY_TYPE_DELETE_SUB_ORGANIZATION" + | "ACTIVITY_TYPE_INIT_OTP_AUTH" + | "ACTIVITY_TYPE_OTP_AUTH" + | "ACTIVITY_TYPE_CREATE_SUB_ORGANIZATION_V7" + | "ACTIVITY_TYPE_UPDATE_WALLET" + | "ACTIVITY_TYPE_UPDATE_POLICY_V2" + | "ACTIVITY_TYPE_CREATE_USERS_V3" + | "ACTIVITY_TYPE_INIT_OTP_AUTH_V2" + | "ACTIVITY_TYPE_INIT_OTP" + | "ACTIVITY_TYPE_VERIFY_OTP" + | "ACTIVITY_TYPE_OTP_LOGIN" + | "ACTIVITY_TYPE_STAMP_LOGIN" + | "ACTIVITY_TYPE_OAUTH_LOGIN" + | "ACTIVITY_TYPE_UPDATE_USER_NAME" + | "ACTIVITY_TYPE_UPDATE_USER_EMAIL" + | "ACTIVITY_TYPE_UPDATE_USER_PHONE_NUMBER" + | "ACTIVITY_TYPE_INIT_FIAT_ON_RAMP" + | "ACTIVITY_TYPE_CREATE_SMART_CONTRACT_INTERFACE" + | "ACTIVITY_TYPE_DELETE_SMART_CONTRACT_INTERFACE" + | "ACTIVITY_TYPE_ENABLE_USER_INITIATED_AUTH" + | "ACTIVITY_TYPE_DISABLE_USER_INITIATED_AUTH" + | "ACTIVITY_TYPE_UPDATE_PROXY_AUTH_CONFIG"; + /** @enum {string} */ + v1AddressFormat: + | "ADDRESS_FORMAT_UNCOMPRESSED" + | "ADDRESS_FORMAT_COMPRESSED" + | "ADDRESS_FORMAT_ETHEREUM" + | "ADDRESS_FORMAT_SOLANA" + | "ADDRESS_FORMAT_COSMOS" + | "ADDRESS_FORMAT_TRON" + | "ADDRESS_FORMAT_SUI" + | "ADDRESS_FORMAT_APTOS" + | "ADDRESS_FORMAT_BITCOIN_MAINNET_P2PKH" + | "ADDRESS_FORMAT_BITCOIN_MAINNET_P2SH" + | "ADDRESS_FORMAT_BITCOIN_MAINNET_P2WPKH" + | "ADDRESS_FORMAT_BITCOIN_MAINNET_P2WSH" + | "ADDRESS_FORMAT_BITCOIN_MAINNET_P2TR" + | "ADDRESS_FORMAT_BITCOIN_TESTNET_P2PKH" + | "ADDRESS_FORMAT_BITCOIN_TESTNET_P2SH" + | "ADDRESS_FORMAT_BITCOIN_TESTNET_P2WPKH" + | "ADDRESS_FORMAT_BITCOIN_TESTNET_P2WSH" + | "ADDRESS_FORMAT_BITCOIN_TESTNET_P2TR" + | "ADDRESS_FORMAT_BITCOIN_SIGNET_P2PKH" + | "ADDRESS_FORMAT_BITCOIN_SIGNET_P2SH" + | "ADDRESS_FORMAT_BITCOIN_SIGNET_P2WPKH" + | "ADDRESS_FORMAT_BITCOIN_SIGNET_P2WSH" + | "ADDRESS_FORMAT_BITCOIN_SIGNET_P2TR" + | "ADDRESS_FORMAT_BITCOIN_REGTEST_P2PKH" + | "ADDRESS_FORMAT_BITCOIN_REGTEST_P2SH" + | "ADDRESS_FORMAT_BITCOIN_REGTEST_P2WPKH" + | "ADDRESS_FORMAT_BITCOIN_REGTEST_P2WSH" + | "ADDRESS_FORMAT_BITCOIN_REGTEST_P2TR" + | "ADDRESS_FORMAT_SEI" + | "ADDRESS_FORMAT_XLM" + | "ADDRESS_FORMAT_DOGE_MAINNET" + | "ADDRESS_FORMAT_DOGE_TESTNET" + | "ADDRESS_FORMAT_TON_V3R2" + | "ADDRESS_FORMAT_TON_V4R2" + | "ADDRESS_FORMAT_TON_V5R1" + | "ADDRESS_FORMAT_XRP"; + v1ApiKey: { + /** @description A User credential that can be used to authenticate to Turnkey. */ + credential: definitions["externaldatav1Credential"]; + /** @description Unique identifier for a given API Key. */ + apiKeyId: string; + /** @description Human-readable name for an API Key. */ + apiKeyName: string; + createdAt: definitions["externaldatav1Timestamp"]; + updatedAt: definitions["externaldatav1Timestamp"]; + /** + * Format: uint64 + * @description Optional window (in seconds) indicating how long the API Key should last. + */ + expirationSeconds?: string; + }; + /** @enum {string} */ + v1ApiKeyCurve: + | "API_KEY_CURVE_P256" + | "API_KEY_CURVE_SECP256K1" + | "API_KEY_CURVE_ED25519"; + v1ApiKeyParamsV2: { + /** @description Human-readable name for an API Key. */ + apiKeyName: string; + /** @description The public component of a cryptographic key pair used to sign messages and transactions. */ + publicKey: string; + /** @description The curve type to be used for processing API key signatures. */ + curveType: definitions["v1ApiKeyCurve"]; + /** @description Optional window (in seconds) indicating how long the API Key should last. */ + expirationSeconds?: string; + }; + v1ApiOnlyUserParams: { + /** @description The name of the new API-only User. */ + userName: string; + /** @description The email address for this API-only User (optional). */ + userEmail?: string; + /** @description A list of tags assigned to the new API-only User. This field, if not needed, should be an empty array in your request body. */ + userTags: string[]; + /** @description A list of API Key parameters. This field, if not needed, should be an empty array in your request body. */ + apiKeys: definitions["apiApiKeyParams"][]; + }; + v1ApproveActivityIntent: { + /** @description An artifact verifying a User's action. */ + fingerprint: string; + }; + v1ApproveActivityRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_APPROVE_ACTIVITY"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1ApproveActivityIntent"]; + }; + v1Attestation: { + /** @description The cbor encoded then base64 url encoded id of the credential. */ + credentialId: string; + /** @description A base64 url encoded payload containing metadata about the signing context and the challenge. */ + clientDataJson: string; + /** @description A base64 url encoded payload containing authenticator data and any attestation the webauthn provider chooses. */ + attestationObject: string; + /** @description The type of authenticator transports. */ + transports: definitions["v1AuthenticatorTransport"][]; + }; + v1Authenticator: { + /** @description Types of transports that may be used by an Authenticator (e.g., USB, NFC, BLE). */ + transports: definitions["v1AuthenticatorTransport"][]; + attestationType: string; + /** @description Identifier indicating the type of the Security Key. */ + aaguid: string; + /** @description Unique identifier for a WebAuthn credential. */ + credentialId: string; + /** @description The type of Authenticator device. */ + model: string; + /** @description A User credential that can be used to authenticate to Turnkey. */ + credential: definitions["externaldatav1Credential"]; + /** @description Unique identifier for a given Authenticator. */ + authenticatorId: string; + /** @description Human-readable name for an Authenticator. */ + authenticatorName: string; + createdAt: definitions["externaldatav1Timestamp"]; + updatedAt: definitions["externaldatav1Timestamp"]; + }; + v1AuthenticatorAttestationResponse: { + clientDataJson: string; + attestationObject: string; + transports?: definitions["v1AuthenticatorTransport"][]; + /** @enum {string} */ + authenticatorAttachment?: "cross-platform" | "platform" | null; + }; + v1AuthenticatorParams: { + /** @description Human-readable name for an Authenticator. */ + authenticatorName: string; + /** @description Unique identifier for a given User. */ + userId: string; + attestation: definitions["v1PublicKeyCredentialWithAttestation"]; + /** @description Challenge presented for authentication purposes. */ + challenge: string; + }; + v1AuthenticatorParamsV2: { + /** @description Human-readable name for an Authenticator. */ + authenticatorName: string; + /** @description Challenge presented for authentication purposes. */ + challenge: string; + /** @description The attestation that proves custody of the authenticator and provides metadata about it. */ + attestation: definitions["v1Attestation"]; + }; + /** @enum {string} */ + v1AuthenticatorTransport: + | "AUTHENTICATOR_TRANSPORT_BLE" + | "AUTHENTICATOR_TRANSPORT_INTERNAL" + | "AUTHENTICATOR_TRANSPORT_NFC" + | "AUTHENTICATOR_TRANSPORT_USB" + | "AUTHENTICATOR_TRANSPORT_HYBRID"; + v1Config: { + features?: definitions["v1Feature"][]; + quorum?: definitions["externaldatav1Quorum"]; + }; + v1CreateApiKeysIntent: { + /** @description A list of API Keys. */ + apiKeys: definitions["apiApiKeyParams"][]; + /** @description Unique identifier for a given User. */ + userId: string; + }; + v1CreateApiKeysIntentV2: { + /** @description A list of API Keys. */ + apiKeys: definitions["v1ApiKeyParamsV2"][]; + /** @description Unique identifier for a given User. */ + userId: string; + }; + v1CreateApiKeysRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_CREATE_API_KEYS_V2"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1CreateApiKeysIntentV2"]; + }; + v1CreateApiKeysResult: { + /** @description A list of API Key IDs. */ + apiKeyIds: string[]; + }; + v1CreateApiOnlyUsersIntent: { + /** @description A list of API-only Users to create. */ + apiOnlyUsers: definitions["v1ApiOnlyUserParams"][]; + }; + v1CreateApiOnlyUsersRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_CREATE_API_ONLY_USERS"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1CreateApiOnlyUsersIntent"]; + }; + v1CreateApiOnlyUsersResult: { + /** @description A list of API-only User IDs. */ + userIds: string[]; + }; + v1CreateAuthenticatorsIntent: { + /** @description A list of Authenticators. */ + authenticators: definitions["v1AuthenticatorParams"][]; + /** @description Unique identifier for a given User. */ + userId: string; + }; + v1CreateAuthenticatorsIntentV2: { + /** @description A list of Authenticators. */ + authenticators: definitions["v1AuthenticatorParamsV2"][]; + /** @description Unique identifier for a given User. */ + userId: string; + }; + v1CreateAuthenticatorsRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_CREATE_AUTHENTICATORS_V2"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1CreateAuthenticatorsIntentV2"]; + }; + v1CreateAuthenticatorsResult: { + /** @description A list of Authenticator IDs. */ + authenticatorIds: string[]; + }; + v1CreateInvitationsIntent: { + /** @description A list of Invitations. */ + invitations: definitions["v1InvitationParams"][]; + }; + v1CreateInvitationsRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_CREATE_INVITATIONS"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1CreateInvitationsIntent"]; + }; + v1CreateInvitationsResult: { + /** @description A list of Invitation IDs */ + invitationIds: string[]; + }; + v1CreateOauthProvidersIntent: { + /** @description The ID of the User to add an Oauth provider to */ + userId: string; + /** @description A list of Oauth providers. */ + oauthProviders: definitions["v1OauthProviderParams"][]; + }; + v1CreateOauthProvidersRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_CREATE_OAUTH_PROVIDERS"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1CreateOauthProvidersIntent"]; + }; + v1CreateOauthProvidersResult: { + /** @description A list of unique identifiers for Oauth Providers */ + providerIds: string[]; + }; + v1CreateOrganizationIntent: { + /** @description Human-readable name for an Organization. */ + organizationName: string; + /** @description The root user's email address. */ + rootEmail: string; + /** @description The root user's Authenticator. */ + rootAuthenticator: definitions["v1AuthenticatorParams"]; + /** @description Unique identifier for the root user object. */ + rootUserId?: string; + }; + v1CreateOrganizationIntentV2: { + /** @description Human-readable name for an Organization. */ + organizationName: string; + /** @description The root user's email address. */ + rootEmail: string; + /** @description The root user's Authenticator. */ + rootAuthenticator: definitions["v1AuthenticatorParamsV2"]; + /** @description Unique identifier for the root user object. */ + rootUserId?: string; + }; + v1CreateOrganizationResult: { + /** @description Unique identifier for a given Organization. */ + organizationId: string; + }; + v1CreatePoliciesIntent: { + /** @description An array of policy intents to be created. */ + policies: definitions["v1CreatePolicyIntentV3"][]; + }; + v1CreatePoliciesRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_CREATE_POLICIES"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1CreatePoliciesIntent"]; + }; + v1CreatePoliciesResult: { + /** @description A list of unique identifiers for the created policies. */ + policyIds: string[]; + }; + v1CreatePolicyIntent: { + /** @description Human-readable name for a Policy. */ + policyName: string; + /** @description A list of simple functions each including a subject, target and boolean. See Policy Engine Language section for additional details. */ + selectors: definitions["v1Selector"][]; + /** @description The instruction to DENY or ALLOW a particular activity following policy selector(s). */ + effect: definitions["v1Effect"]; + notes?: string; + }; + v1CreatePolicyIntentV2: { + /** @description Human-readable name for a Policy. */ + policyName: string; + /** @description A list of simple functions each including a subject, target and boolean. See Policy Engine Language section for additional details. */ + selectors: definitions["v1SelectorV2"][]; + /** @description Whether to ALLOW or DENY requests that match the condition and consensus requirements. */ + effect: definitions["v1Effect"]; + notes?: string; + }; + v1CreatePolicyIntentV3: { + /** @description Human-readable name for a Policy. */ + policyName: string; + /** @description The instruction to DENY or ALLOW an activity. */ + effect: definitions["v1Effect"]; + /** @description The condition expression that triggers the Effect */ + condition?: string; + /** @description The consensus expression that triggers the Effect */ + consensus?: string; + notes?: string; + }; + v1CreatePolicyRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_CREATE_POLICY_V3"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1CreatePolicyIntentV3"]; + }; + v1CreatePolicyResult: { + /** @description Unique identifier for a given Policy. */ + policyId: string; + }; + v1CreatePrivateKeyTagIntent: { + /** @description Human-readable name for a Private Key Tag. */ + privateKeyTagName: string; + /** @description A list of Private Key IDs. */ + privateKeyIds: string[]; + }; + v1CreatePrivateKeyTagRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_CREATE_PRIVATE_KEY_TAG"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1CreatePrivateKeyTagIntent"]; + }; + v1CreatePrivateKeyTagResult: { + /** @description Unique identifier for a given Private Key Tag. */ + privateKeyTagId: string; + /** @description A list of Private Key IDs. */ + privateKeyIds: string[]; + }; + v1CreatePrivateKeysIntent: { + /** @description A list of Private Keys. */ + privateKeys: definitions["v1PrivateKeyParams"][]; + }; + v1CreatePrivateKeysIntentV2: { + /** @description A list of Private Keys. */ + privateKeys: definitions["v1PrivateKeyParams"][]; + }; + v1CreatePrivateKeysRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_CREATE_PRIVATE_KEYS_V2"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1CreatePrivateKeysIntentV2"]; + }; + v1CreatePrivateKeysResult: { + /** @description A list of Private Key IDs. */ + privateKeyIds: string[]; + }; + v1CreatePrivateKeysResultV2: { + /** @description A list of Private Key IDs and addresses. */ + privateKeys: definitions["v1PrivateKeyResult"][]; + }; + v1CreateReadOnlySessionIntent: { [key: string]: unknown }; + v1CreateReadOnlySessionRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_CREATE_READ_ONLY_SESSION"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1CreateReadOnlySessionIntent"]; + }; + v1CreateReadOnlySessionResult: { + /** @description Unique identifier for a given Organization. If the request is being made by a user and their Sub-Organization ID is unknown, this can be the Parent Organization ID. However, using the Sub-Organization ID is preferred due to performance reasons. */ + organizationId: string; + /** @description Human-readable name for an Organization. */ + organizationName: string; + /** @description Unique identifier for a given User. */ + userId: string; + /** @description Human-readable name for a User. */ + username: string; + /** @description String representing a read only session */ + session: string; + /** + * Format: uint64 + * @description UTC timestamp in seconds representing the expiry time for the read only session. + */ + sessionExpiry: string; + }; + v1CreateReadWriteSessionIntent: { + /** @description Client-side public key generated by the user, to which the read write session bundle (credentials) will be encrypted. */ + targetPublicKey: string; + /** @description Email of the user to create a read write session for */ + email: string; + /** @description Optional human-readable name for an API Key. If none provided, default to Read Write Session - */ + apiKeyName?: string; + /** @description Expiration window (in seconds) indicating how long the API key is valid for. If not provided, a default of 15 minutes will be used. */ + expirationSeconds?: string; + }; + v1CreateReadWriteSessionIntentV2: { + /** @description Client-side public key generated by the user, to which the read write session bundle (credentials) will be encrypted. */ + targetPublicKey: string; + /** @description Unique identifier for a given User. */ + userId?: string; + /** @description Optional human-readable name for an API Key. If none provided, default to Read Write Session - */ + apiKeyName?: string; + /** @description Expiration window (in seconds) indicating how long the API key is valid for. If not provided, a default of 15 minutes will be used. */ + expirationSeconds?: string; + /** @description Invalidate all other previously generated ReadWriteSession API keys */ + invalidateExisting?: boolean; + }; + v1CreateReadWriteSessionRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_CREATE_READ_WRITE_SESSION_V2"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1CreateReadWriteSessionIntentV2"]; + }; + v1CreateReadWriteSessionResult: { + /** @description Unique identifier for a given Organization. If the request is being made by a user and their Sub-Organization ID is unknown, this can be the Parent Organization ID. However, using the Sub-Organization ID is preferred due to performance reasons. */ + organizationId: string; + /** @description Human-readable name for an Organization. */ + organizationName: string; + /** @description Unique identifier for a given User. */ + userId: string; + /** @description Human-readable name for a User. */ + username: string; + /** @description Unique identifier for the created API key. */ + apiKeyId: string; + /** @description HPKE encrypted credential bundle */ + credentialBundle: string; + }; + v1CreateReadWriteSessionResultV2: { + /** @description Unique identifier for a given Organization. If the request is being made by a user and their Sub-Organization ID is unknown, this can be the Parent Organization ID. However, using the Sub-Organization ID is preferred due to performance reasons. */ + organizationId: string; + /** @description Human-readable name for an Organization. */ + organizationName: string; + /** @description Unique identifier for a given User. */ + userId: string; + /** @description Human-readable name for a User. */ + username: string; + /** @description Unique identifier for the created API key. */ + apiKeyId: string; + /** @description HPKE encrypted credential bundle */ + credentialBundle: string; + }; + v1CreateSmartContractInterfaceIntent: { + /** @description Corresponding contract address or program ID */ + smartContractAddress: string; + /** @description ABI/IDL as a JSON string */ + smartContractInterface: string; + type: definitions["v1SmartContractInterfaceType"]; + /** @description Human-readable name for a Smart Contract Interface. */ + label?: string; + /** @description Notes for a Smart Contract Interface. */ + notes?: string; + }; + v1CreateSmartContractInterfaceRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_CREATE_SMART_CONTRACT_INTERFACE"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1CreateSmartContractInterfaceIntent"]; + }; + v1CreateSmartContractInterfaceResult: { + /** @description The ID of the created Smart Contract Interface. */ + smartContractInterfaceId: string; + }; + v1CreateSubOrganizationIntent: { + /** @description Name for this sub-organization */ + name: string; + /** @description Root User authenticator for this new sub-organization */ + rootAuthenticator: definitions["v1AuthenticatorParamsV2"]; + }; + v1CreateSubOrganizationIntentV2: { + /** @description Name for this sub-organization */ + subOrganizationName: string; + /** @description Root users to create within this sub-organization */ + rootUsers: definitions["v1RootUserParams"][]; + /** + * Format: int32 + * @description The threshold of unique approvals to reach root quorum. This value must be less than or equal to the number of root users + */ + rootQuorumThreshold: number; + }; + v1CreateSubOrganizationIntentV3: { + /** @description Name for this sub-organization */ + subOrganizationName: string; + /** @description Root users to create within this sub-organization */ + rootUsers: definitions["v1RootUserParams"][]; + /** + * Format: int32 + * @description The threshold of unique approvals to reach root quorum. This value must be less than or equal to the number of root users + */ + rootQuorumThreshold: number; + /** @description A list of Private Keys. */ + privateKeys: definitions["v1PrivateKeyParams"][]; + }; + v1CreateSubOrganizationIntentV4: { + /** @description Name for this sub-organization */ + subOrganizationName: string; + /** @description Root users to create within this sub-organization */ + rootUsers: definitions["v1RootUserParams"][]; + /** + * Format: int32 + * @description The threshold of unique approvals to reach root quorum. This value must be less than or equal to the number of root users + */ + rootQuorumThreshold: number; + /** @description The wallet to create for the sub-organization */ + wallet?: definitions["v1WalletParams"]; + /** @description Disable email recovery for the sub-organization */ + disableEmailRecovery?: boolean; + /** @description Disable email auth for the sub-organization */ + disableEmailAuth?: boolean; + }; + v1CreateSubOrganizationIntentV5: { + /** @description Name for this sub-organization */ + subOrganizationName: string; + /** @description Root users to create within this sub-organization */ + rootUsers: definitions["v1RootUserParamsV2"][]; + /** + * Format: int32 + * @description The threshold of unique approvals to reach root quorum. This value must be less than or equal to the number of root users + */ + rootQuorumThreshold: number; + /** @description The wallet to create for the sub-organization */ + wallet?: definitions["v1WalletParams"]; + /** @description Disable email recovery for the sub-organization */ + disableEmailRecovery?: boolean; + /** @description Disable email auth for the sub-organization */ + disableEmailAuth?: boolean; + }; + v1CreateSubOrganizationIntentV6: { + /** @description Name for this sub-organization */ + subOrganizationName: string; + /** @description Root users to create within this sub-organization */ + rootUsers: definitions["v1RootUserParamsV3"][]; + /** + * Format: int32 + * @description The threshold of unique approvals to reach root quorum. This value must be less than or equal to the number of root users + */ + rootQuorumThreshold: number; + /** @description The wallet to create for the sub-organization */ + wallet?: definitions["v1WalletParams"]; + /** @description Disable email recovery for the sub-organization */ + disableEmailRecovery?: boolean; + /** @description Disable email auth for the sub-organization */ + disableEmailAuth?: boolean; + }; + v1CreateSubOrganizationIntentV7: { + /** @description Name for this sub-organization */ + subOrganizationName: string; + /** @description Root users to create within this sub-organization */ + rootUsers: definitions["v1RootUserParamsV4"][]; + /** + * Format: int32 + * @description The threshold of unique approvals to reach root quorum. This value must be less than or equal to the number of root users + */ + rootQuorumThreshold: number; + /** @description The wallet to create for the sub-organization */ + wallet?: definitions["v1WalletParams"]; + /** @description Disable email recovery for the sub-organization */ + disableEmailRecovery?: boolean; + /** @description Disable email auth for the sub-organization */ + disableEmailAuth?: boolean; + /** @description Disable OTP SMS auth for the sub-organization */ + disableSmsAuth?: boolean; + /** @description Disable OTP email auth for the sub-organization */ + disableOtpEmailAuth?: boolean; + /** @description Signed JWT containing a unique id, expiry, verification type, contact */ + verificationToken?: string; + }; + v1CreateSubOrganizationRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_CREATE_SUB_ORGANIZATION_V7"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1CreateSubOrganizationIntentV7"]; + }; + v1CreateSubOrganizationResult: { + subOrganizationId: string; + rootUserIds?: string[]; + }; + v1CreateSubOrganizationResultV3: { + subOrganizationId: string; + /** @description A list of Private Key IDs and addresses. */ + privateKeys: definitions["v1PrivateKeyResult"][]; + rootUserIds?: string[]; + }; + v1CreateSubOrganizationResultV4: { + subOrganizationId: string; + wallet?: definitions["v1WalletResult"]; + rootUserIds?: string[]; + }; + v1CreateSubOrganizationResultV5: { + subOrganizationId: string; + wallet?: definitions["v1WalletResult"]; + rootUserIds?: string[]; + }; + v1CreateSubOrganizationResultV6: { + subOrganizationId: string; + wallet?: definitions["v1WalletResult"]; + rootUserIds?: string[]; + }; + v1CreateSubOrganizationResultV7: { + subOrganizationId: string; + wallet?: definitions["v1WalletResult"]; + rootUserIds?: string[]; + }; + v1CreateUserTagIntent: { + /** @description Human-readable name for a User Tag. */ + userTagName: string; + /** @description A list of User IDs. */ + userIds: string[]; + }; + v1CreateUserTagRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_CREATE_USER_TAG"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1CreateUserTagIntent"]; + }; + v1CreateUserTagResult: { + /** @description Unique identifier for a given User Tag. */ + userTagId: string; + /** @description A list of User IDs. */ + userIds: string[]; + }; + v1CreateUsersIntent: { + /** @description A list of Users. */ + users: definitions["v1UserParams"][]; + }; + v1CreateUsersIntentV2: { + /** @description A list of Users. */ + users: definitions["v1UserParamsV2"][]; + }; + v1CreateUsersIntentV3: { + /** @description A list of Users. */ + users: definitions["v1UserParamsV3"][]; + }; + v1CreateUsersRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_CREATE_USERS_V3"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1CreateUsersIntentV3"]; + }; + v1CreateUsersResult: { + /** @description A list of User IDs. */ + userIds: string[]; + }; + v1CreateWalletAccountsIntent: { + /** @description Unique identifier for a given Wallet. */ + walletId: string; + /** @description A list of wallet Accounts. */ + accounts: definitions["v1WalletAccountParams"][]; + }; + v1CreateWalletAccountsRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_CREATE_WALLET_ACCOUNTS"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1CreateWalletAccountsIntent"]; + }; + v1CreateWalletAccountsResult: { + /** @description A list of derived addresses. */ + addresses: string[]; + }; + v1CreateWalletIntent: { + /** @description Human-readable name for a Wallet. */ + walletName: string; + /** @description A list of wallet Accounts. This field, if not needed, should be an empty array in your request body. */ + accounts: definitions["v1WalletAccountParams"][]; + /** + * Format: int32 + * @description Length of mnemonic to generate the Wallet seed. Defaults to 12. Accepted values: 12, 15, 18, 21, 24. + */ + mnemonicLength?: number; + }; + v1CreateWalletRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_CREATE_WALLET"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1CreateWalletIntent"]; + }; + v1CreateWalletResult: { + /** @description Unique identifier for a Wallet. */ + walletId: string; + /** @description A list of account addresses. */ + addresses: string[]; + }; + v1CredPropsAuthenticationExtensionsClientOutputs: { + rk: boolean; + }; + /** @enum {string} */ + v1CredentialType: + | "CREDENTIAL_TYPE_WEBAUTHN_AUTHENTICATOR" + | "CREDENTIAL_TYPE_API_KEY_P256" + | "CREDENTIAL_TYPE_RECOVER_USER_KEY_P256" + | "CREDENTIAL_TYPE_API_KEY_SECP256K1" + | "CREDENTIAL_TYPE_EMAIL_AUTH_KEY_P256" + | "CREDENTIAL_TYPE_API_KEY_ED25519" + | "CREDENTIAL_TYPE_OTP_AUTH_KEY_P256" + | "CREDENTIAL_TYPE_READ_WRITE_SESSION_KEY_P256" + | "CREDENTIAL_TYPE_OAUTH_KEY_P256" + | "CREDENTIAL_TYPE_LOGIN"; + /** @enum {string} */ + v1Curve: "CURVE_SECP256K1" | "CURVE_ED25519"; + v1DeleteApiKeysIntent: { + /** @description Unique identifier for a given User. */ + userId: string; + /** @description A list of API Key IDs. */ + apiKeyIds: string[]; + }; + v1DeleteApiKeysRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_DELETE_API_KEYS"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1DeleteApiKeysIntent"]; + }; + v1DeleteApiKeysResult: { + /** @description A list of API Key IDs. */ + apiKeyIds: string[]; + }; + v1DeleteAuthenticatorsIntent: { + /** @description Unique identifier for a given User. */ + userId: string; + /** @description A list of Authenticator IDs. */ + authenticatorIds: string[]; + }; + v1DeleteAuthenticatorsRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_DELETE_AUTHENTICATORS"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1DeleteAuthenticatorsIntent"]; + }; + v1DeleteAuthenticatorsResult: { + /** @description Unique identifier for a given Authenticator. */ + authenticatorIds: string[]; + }; + v1DeleteInvitationIntent: { + /** @description Unique identifier for a given Invitation object. */ + invitationId: string; + }; + v1DeleteInvitationRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_DELETE_INVITATION"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1DeleteInvitationIntent"]; + }; + v1DeleteInvitationResult: { + /** @description Unique identifier for a given Invitation. */ + invitationId: string; + }; + v1DeleteOauthProvidersIntent: { + /** @description The ID of the User to remove an Oauth provider from */ + userId: string; + /** @description Unique identifier for a given Provider. */ + providerIds: string[]; + }; + v1DeleteOauthProvidersRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_DELETE_OAUTH_PROVIDERS"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1DeleteOauthProvidersIntent"]; + }; + v1DeleteOauthProvidersResult: { + /** @description A list of unique identifiers for Oauth Providers */ + providerIds: string[]; + }; + v1DeleteOrganizationIntent: { + /** @description Unique identifier for a given Organization. */ + organizationId: string; + }; + v1DeleteOrganizationResult: { + /** @description Unique identifier for a given Organization. */ + organizationId: string; + }; + v1DeletePolicyIntent: { + /** @description Unique identifier for a given Policy. */ + policyId: string; + }; + v1DeletePolicyRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_DELETE_POLICY"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1DeletePolicyIntent"]; + }; + v1DeletePolicyResult: { + /** @description Unique identifier for a given Policy. */ + policyId: string; + }; + v1DeletePrivateKeyTagsIntent: { + /** @description A list of Private Key Tag IDs. */ + privateKeyTagIds: string[]; + }; + v1DeletePrivateKeyTagsRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_DELETE_PRIVATE_KEY_TAGS"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1DeletePrivateKeyTagsIntent"]; + }; + v1DeletePrivateKeyTagsResult: { + /** @description A list of Private Key Tag IDs. */ + privateKeyTagIds: string[]; + /** @description A list of Private Key IDs. */ + privateKeyIds: string[]; + }; + v1DeletePrivateKeysIntent: { + /** @description List of unique identifiers for private keys within an organization */ + privateKeyIds: string[]; + /** @description Optional parameter for deleting the private keys, even if any have not been previously exported. If they have been exported, this field is ignored. */ + deleteWithoutExport?: boolean; + }; + v1DeletePrivateKeysRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_DELETE_PRIVATE_KEYS"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1DeletePrivateKeysIntent"]; + }; + v1DeletePrivateKeysResult: { + /** @description A list of private key unique identifiers that were removed */ + privateKeyIds: string[]; + }; + v1DeleteSmartContractInterfaceIntent: { + /** @description The ID of a Smart Contract Interface intended for deletion. */ + smartContractInterfaceId: string; + }; + v1DeleteSmartContractInterfaceRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_DELETE_SMART_CONTRACT_INTERFACE"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1DeleteSmartContractInterfaceIntent"]; + }; + v1DeleteSmartContractInterfaceResult: { + /** @description The ID of the deleted Smart Contract Interface. */ + smartContractInterfaceId: string; + }; + v1DeleteSubOrganizationIntent: { + /** @description Sub-organization deletion, by default, requires associated wallets and private keys to be exported for security reasons. Set this boolean to true to force sub-organization deletion even if some wallets or private keys within it have not been exported yet. Default: false. */ + deleteWithoutExport?: boolean; + }; + v1DeleteSubOrganizationRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_DELETE_SUB_ORGANIZATION"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1DeleteSubOrganizationIntent"]; + }; + v1DeleteSubOrganizationResult: { + /** @description Unique identifier of the sub organization that was removed */ + subOrganizationUuid: string; + }; + v1DeleteUserTagsIntent: { + /** @description A list of User Tag IDs. */ + userTagIds: string[]; + }; + v1DeleteUserTagsRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_DELETE_USER_TAGS"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1DeleteUserTagsIntent"]; + }; + v1DeleteUserTagsResult: { + /** @description A list of User Tag IDs. */ + userTagIds: string[]; + /** @description A list of User IDs. */ + userIds: string[]; + }; + v1DeleteUsersIntent: { + /** @description A list of User IDs. */ + userIds: string[]; + }; + v1DeleteUsersRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_DELETE_USERS"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1DeleteUsersIntent"]; + }; + v1DeleteUsersResult: { + /** @description A list of User IDs. */ + userIds: string[]; + }; + v1DeleteWalletsIntent: { + /** @description List of unique identifiers for wallets within an organization */ + walletIds: string[]; + /** @description Optional parameter for deleting the wallets, even if any have not been previously exported. If they have been exported, this field is ignored. */ + deleteWithoutExport?: boolean; + }; + v1DeleteWalletsRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_DELETE_WALLETS"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1DeleteWalletsIntent"]; + }; + v1DeleteWalletsResult: { + /** @description A list of wallet unique identifiers that were removed */ + walletIds: string[]; + }; + v1DisablePrivateKeyIntent: { + /** @description Unique identifier for a given Private Key. */ + privateKeyId: string; + }; + v1DisablePrivateKeyResult: { + /** @description Unique identifier for a given Private Key. */ + privateKeyId: string; + }; + v1DisableUserInitiatedAuthIntent: { + /** @description Unique identifier for a given User. (representing the turnkey signer user id) */ + userId?: string; + /** @description Unique identifier for a given Policy. (representing the turnkey signer associated policy) */ + policyId?: string; + }; + v1DisableUserInitiatedAuthRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_DISABLE_USER_INITIATED_AUTH"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1DisableUserInitiatedAuthIntent"]; + }; + v1DisableUserInitiatedAuthResult: { [key: string]: unknown }; + /** @enum {string} */ + v1Effect: "EFFECT_ALLOW" | "EFFECT_DENY"; + v1EmailAuthIntent: { + /** @description Email of the authenticating user. */ + email: string; + /** @description Client-side public key generated by the user, to which the email auth bundle (credentials) will be encrypted. */ + targetPublicKey: string; + /** @description Optional human-readable name for an API Key. If none provided, default to Email Auth - */ + apiKeyName?: string; + /** @description Expiration window (in seconds) indicating how long the API key is valid for. If not provided, a default of 15 minutes will be used. */ + expirationSeconds?: string; + /** @description Optional parameters for customizing emails. If not provided, the default email will be used. */ + emailCustomization?: definitions["v1EmailCustomizationParams"]; + /** @description Invalidate all other previously generated Email Auth API keys */ + invalidateExisting?: boolean; + /** @description Optional custom email address from which to send the email */ + sendFromEmailAddress?: string; + /** @description Optional custom sender name for use with sendFromEmailAddress; if left empty, will default to 'Notifications' */ + sendFromEmailSenderName?: string; + /** @description Optional custom email address to use as reply-to */ + replyToEmailAddress?: string; + }; + v1EmailAuthIntentV2: { + /** @description Email of the authenticating user. */ + email: string; + /** @description Client-side public key generated by the user, to which the email auth bundle (credentials) will be encrypted. */ + targetPublicKey: string; + /** @description Optional human-readable name for an API Key. If none provided, default to Email Auth - */ + apiKeyName?: string; + /** @description Expiration window (in seconds) indicating how long the API key is valid for. If not provided, a default of 15 minutes will be used. */ + expirationSeconds?: string; + /** @description Optional parameters for customizing emails. If not provided, the default email will be used. */ + emailCustomization?: definitions["v1EmailCustomizationParams"]; + /** @description Invalidate all other previously generated Email Auth API keys */ + invalidateExisting?: boolean; + /** @description Optional custom email address from which to send the email */ + sendFromEmailAddress?: string; + /** @description Optional custom sender name for use with sendFromEmailAddress; if left empty, will default to 'Notifications' */ + sendFromEmailSenderName?: string; + /** @description Optional custom email address to use as reply-to */ + replyToEmailAddress?: string; + }; + v1EmailAuthRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_EMAIL_AUTH_V2"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1EmailAuthIntentV2"]; + }; + v1EmailAuthResult: { + /** @description Unique identifier for the authenticating User. */ + userId: string; + /** @description Unique identifier for the created API key. */ + apiKeyId: string; + }; + v1EmailCustomizationParams: { + /** @description The name of the application. */ + appName?: string; + /** @description A URL pointing to a logo in PNG format. Note this logo will be resized to fit into 340px x 124px. */ + logoUrl?: string; + /** @description A template for the URL to be used in a magic link button, e.g. `https://dapp.xyz/%s`. The auth bundle will be interpolated into the `%s`. */ + magicLinkTemplate?: string; + /** @description JSON object containing key/value pairs to be used with custom templates. */ + templateVariables?: string; + /** @description Unique identifier for a given Email Template. If not specified, the default is the most recent Email Template. */ + templateId?: string; + }; + v1EnableUserInitiatedAuthIntent: { [key: string]: unknown }; + v1EnableUserInitiatedAuthRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_ENABLE_USER_INITIATED_AUTH"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1EnableUserInitiatedAuthIntent"]; + }; + v1EnableUserInitiatedAuthResult: { + /** @description A User ID. */ + userId: string; + /** @description A Policy ID. */ + policyId: string; + }; + v1EwkSettingsParams: { + /** @description Enable Sign in with Apple */ + appleEnabled?: boolean; + /** @description Enable Sign in with Google */ + googleEnabled?: boolean; + /** @description Enable Sign in with Facebook */ + facebookEnabled?: boolean; + /** @description Whether to open OAuth providers in-page instead of a popup */ + openOauthInPage?: boolean; + }; + v1ExportPrivateKeyIntent: { + /** @description Unique identifier for a given Private Key. */ + privateKeyId: string; + /** @description Client-side public key generated by the user, to which the export bundle will be encrypted. */ + targetPublicKey: string; + }; + v1ExportPrivateKeyRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_EXPORT_PRIVATE_KEY"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1ExportPrivateKeyIntent"]; + }; + v1ExportPrivateKeyResult: { + /** @description Unique identifier for a given Private Key. */ + privateKeyId: string; + /** @description Export bundle containing a private key encrypted to the client's target public key. */ + exportBundle: string; + }; + v1ExportWalletAccountIntent: { + /** @description Address to identify Wallet Account. */ + address: string; + /** @description Client-side public key generated by the user, to which the export bundle will be encrypted. */ + targetPublicKey: string; + }; + v1ExportWalletAccountRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_EXPORT_WALLET_ACCOUNT"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1ExportWalletAccountIntent"]; + }; + v1ExportWalletAccountResult: { + /** @description Address to identify Wallet Account. */ + address: string; + /** @description Export bundle containing a private key encrypted by the client's target public key. */ + exportBundle: string; + }; + v1ExportWalletIntent: { + /** @description Unique identifier for a given Wallet. */ + walletId: string; + /** @description Client-side public key generated by the user, to which the export bundle will be encrypted. */ + targetPublicKey: string; + /** @description The language of the mnemonic to export. Defaults to English. */ + language?: definitions["v1MnemonicLanguage"]; + }; + v1ExportWalletRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_EXPORT_WALLET"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1ExportWalletIntent"]; + }; + v1ExportWalletResult: { + /** @description Unique identifier for a given Wallet. */ + walletId: string; + /** @description Export bundle containing a wallet mnemonic + optional newline passphrase encrypted by the client's target public key. */ + exportBundle: string; + }; + v1Feature: { + name?: definitions["v1FeatureName"]; + value?: string; + }; + /** @enum {string} */ + v1FeatureName: + | "FEATURE_NAME_ROOT_USER_EMAIL_RECOVERY" + | "FEATURE_NAME_WEBAUTHN_ORIGINS" + | "FEATURE_NAME_EMAIL_AUTH" + | "FEATURE_NAME_EMAIL_RECOVERY" + | "FEATURE_NAME_WEBHOOK" + | "FEATURE_NAME_SMS_AUTH" + | "FEATURE_NAME_OTP_EMAIL_AUTH"; + /** @enum {string} */ + v1FiatOnRampBlockchainNetwork: + | "FIAT_ON_RAMP_BLOCKCHAIN_NETWORK_BITCOIN" + | "FIAT_ON_RAMP_BLOCKCHAIN_NETWORK_ETHEREUM" + | "FIAT_ON_RAMP_BLOCKCHAIN_NETWORK_SOLANA" + | "FIAT_ON_RAMP_BLOCKCHAIN_NETWORK_BASE"; + /** @enum {string} */ + v1FiatOnRampCryptoCurrency: + | "FIAT_ON_RAMP_CRYPTO_CURRENCY_BTC" + | "FIAT_ON_RAMP_CRYPTO_CURRENCY_ETH" + | "FIAT_ON_RAMP_CRYPTO_CURRENCY_SOL" + | "FIAT_ON_RAMP_CRYPTO_CURRENCY_USDC"; + /** @enum {string} */ + v1FiatOnRampCurrency: + | "FIAT_ON_RAMP_CURRENCY_AUD" + | "FIAT_ON_RAMP_CURRENCY_BGN" + | "FIAT_ON_RAMP_CURRENCY_BRL" + | "FIAT_ON_RAMP_CURRENCY_CAD" + | "FIAT_ON_RAMP_CURRENCY_CHF" + | "FIAT_ON_RAMP_CURRENCY_COP" + | "FIAT_ON_RAMP_CURRENCY_CZK" + | "FIAT_ON_RAMP_CURRENCY_DKK" + | "FIAT_ON_RAMP_CURRENCY_DOP" + | "FIAT_ON_RAMP_CURRENCY_EGP" + | "FIAT_ON_RAMP_CURRENCY_EUR" + | "FIAT_ON_RAMP_CURRENCY_GBP" + | "FIAT_ON_RAMP_CURRENCY_HKD" + | "FIAT_ON_RAMP_CURRENCY_IDR" + | "FIAT_ON_RAMP_CURRENCY_ILS" + | "FIAT_ON_RAMP_CURRENCY_JOD" + | "FIAT_ON_RAMP_CURRENCY_KES" + | "FIAT_ON_RAMP_CURRENCY_KWD" + | "FIAT_ON_RAMP_CURRENCY_LKR" + | "FIAT_ON_RAMP_CURRENCY_MXN" + | "FIAT_ON_RAMP_CURRENCY_NGN" + | "FIAT_ON_RAMP_CURRENCY_NOK" + | "FIAT_ON_RAMP_CURRENCY_NZD" + | "FIAT_ON_RAMP_CURRENCY_OMR" + | "FIAT_ON_RAMP_CURRENCY_PEN" + | "FIAT_ON_RAMP_CURRENCY_PLN" + | "FIAT_ON_RAMP_CURRENCY_RON" + | "FIAT_ON_RAMP_CURRENCY_SEK" + | "FIAT_ON_RAMP_CURRENCY_THB" + | "FIAT_ON_RAMP_CURRENCY_TRY" + | "FIAT_ON_RAMP_CURRENCY_TWD" + | "FIAT_ON_RAMP_CURRENCY_USD" + | "FIAT_ON_RAMP_CURRENCY_VND" + | "FIAT_ON_RAMP_CURRENCY_ZAR"; + /** @enum {string} */ + v1FiatOnRampPaymentMethod: + | "FIAT_ON_RAMP_PAYMENT_METHOD_CREDIT_DEBIT_CARD" + | "FIAT_ON_RAMP_PAYMENT_METHOD_APPLE_PAY" + | "FIAT_ON_RAMP_PAYMENT_METHOD_GBP_BANK_TRANSFER" + | "FIAT_ON_RAMP_PAYMENT_METHOD_GBP_OPEN_BANKING_PAYMENT" + | "FIAT_ON_RAMP_PAYMENT_METHOD_GOOGLE_PAY" + | "FIAT_ON_RAMP_PAYMENT_METHOD_SEPA_BANK_TRANSFER" + | "FIAT_ON_RAMP_PAYMENT_METHOD_PIX_INSTANT_PAYMENT" + | "FIAT_ON_RAMP_PAYMENT_METHOD_PAYPAL" + | "FIAT_ON_RAMP_PAYMENT_METHOD_VENMO" + | "FIAT_ON_RAMP_PAYMENT_METHOD_MOONPAY_BALANCE" + | "FIAT_ON_RAMP_PAYMENT_METHOD_CRYPTO_ACCOUNT" + | "FIAT_ON_RAMP_PAYMENT_METHOD_FIAT_WALLET" + | "FIAT_ON_RAMP_PAYMENT_METHOD_ACH_BANK_ACCOUNT"; + /** @enum {string} */ + v1FiatOnRampProvider: + | "FIAT_ON_RAMP_PROVIDER_COINBASE" + | "FIAT_ON_RAMP_PROVIDER_MOONPAY"; + v1GetActivitiesRequest: { + /** @description Unique identifier for a given Organization. */ + organizationId: string; + /** @description Array of Activity Statuses filtering which Activities will be listed in the response. */ + filterByStatus?: definitions["v1ActivityStatus"][]; + /** @description Parameters used for cursor-based pagination. */ + paginationOptions?: definitions["v1Pagination"]; + /** @description Array of Activity Types filtering which Activities will be listed in the response. */ + filterByType?: definitions["v1ActivityType"][]; + }; + v1GetActivitiesResponse: { + /** @description A list of Activities. */ + activities: definitions["v1Activity"][]; + }; + v1GetActivityRequest: { + /** @description Unique identifier for a given Organization. */ + organizationId: string; + /** @description Unique identifier for a given Activity object. */ + activityId: string; + }; + v1GetApiKeyRequest: { + /** @description Unique identifier for a given Organization. */ + organizationId: string; + /** @description Unique identifier for a given API key. */ + apiKeyId: string; + }; + v1GetApiKeyResponse: { + /** @description An API key. */ + apiKey: definitions["v1ApiKey"]; + }; + v1GetApiKeysRequest: { + /** @description Unique identifier for a given Organization. */ + organizationId: string; + /** @description Unique identifier for a given User. */ + userId?: string; + }; + v1GetApiKeysResponse: { + /** @description A list of API keys. */ + apiKeys: definitions["v1ApiKey"][]; + }; + v1GetAttestationDocumentRequest: { + /** @description Unique identifier for a given Organization. */ + organizationId: string; + /** @description The enclave type, one of: ump, notarizer, signer, evm-parser */ + enclaveType: string; + }; + v1GetAttestationDocumentResponse: { + /** + * Format: byte + * @description Raw (CBOR-encoded) attestation document + */ + attestationDocument: string; + }; + v1GetAuthenticatorRequest: { + /** @description Unique identifier for a given Organization. */ + organizationId: string; + /** @description Unique identifier for a given Authenticator. */ + authenticatorId: string; + }; + v1GetAuthenticatorResponse: { + /** @description An authenticator. */ + authenticator: definitions["v1Authenticator"]; + }; + v1GetAuthenticatorsRequest: { + /** @description Unique identifier for a given Organization. */ + organizationId: string; + /** @description Unique identifier for a given User. */ + userId: string; + }; + v1GetAuthenticatorsResponse: { + /** @description A list of authenticators. */ + authenticators: definitions["v1Authenticator"][]; + }; + v1GetOauthProvidersRequest: { + /** @description Unique identifier for a given Organization. */ + organizationId: string; + /** @description Unique identifier for a given User. */ + userId?: string; + }; + v1GetOauthProvidersResponse: { + /** @description A list of Oauth Providers */ + oauthProviders: definitions["v1OauthProvider"][]; + }; + v1GetOrganizationConfigsRequest: { + /** @description Unique identifier for a given Organization. */ + organizationId: string; + }; + v1GetOrganizationConfigsResponse: { + /** @description Organization configs including quorum settings and organization features */ + configs: definitions["v1Config"]; + }; + v1GetOrganizationRequest: { + /** @description Unique identifier for a given Organization. */ + organizationId: string; + }; + v1GetOrganizationResponse: { + /** @description Object representing the full current and deleted / disabled collection of Users, Policies, Private Keys, and Invitations attributable to a particular Organization. */ + organizationData: definitions["v1OrganizationData"]; + }; + v1GetPoliciesRequest: { + /** @description Unique identifier for a given Organization. */ + organizationId: string; + }; + v1GetPoliciesResponse: { + /** @description A list of Policies. */ + policies: definitions["v1Policy"][]; + }; + v1GetPolicyRequest: { + /** @description Unique identifier for a given Organization. */ + organizationId: string; + /** @description Unique identifier for a given Policy. */ + policyId: string; + }; + v1GetPolicyResponse: { + /** @description Object that codifies rules defining the actions that are permissible within an Organization. */ + policy: definitions["v1Policy"]; + }; + v1GetPrivateKeyRequest: { + /** @description Unique identifier for a given Organization. */ + organizationId: string; + /** @description Unique identifier for a given Private Key. */ + privateKeyId: string; + }; + v1GetPrivateKeyResponse: { + /** @description Cryptographic public/private key pair that can be used for cryptocurrency needs or more generalized encryption. */ + privateKey: definitions["v1PrivateKey"]; + }; + v1GetPrivateKeysRequest: { + /** @description Unique identifier for a given Organization. */ + organizationId: string; + }; + v1GetPrivateKeysResponse: { + /** @description A list of Private Keys. */ + privateKeys: definitions["v1PrivateKey"][]; + }; + v1GetProxyAuthConfigRequest: { + /** @description Unique identifier for a given Organization. */ + organizationId: string; + }; + v1GetProxyAuthConfigResponse: { + /** @description Proxy authentication configuration (e.g., allowed origins). */ + proxyAuthConfig: definitions["v1ProxyAuthConfig"]; + }; + v1GetSmartContractInterfaceRequest: { + /** @description Unique identifier for a given Organization. */ + organizationId: string; + /** @description Unique identifier for a given Smart Contract Interface. */ + smartContractInterfaceId: string; + }; + v1GetSmartContractInterfaceResponse: { + /** @description Object to be used in conjunction with Policies to guard transaction signing. */ + smartContractInterface: definitions["v1SmartContractInterface"]; + }; + v1GetSmartContractInterfacesRequest: { + /** @description Unique identifier for a given Organization. */ + organizationId: string; + }; + v1GetSmartContractInterfacesResponse: { + /** @description A list of Smart Contract Interfaces. */ + smartContractInterfaces: definitions["v1SmartContractInterface"][]; + }; + v1GetSubOrgIdsRequest: { + /** @description Unique identifier for the parent Organization. This is used to find sub-organizations within it. */ + organizationId: string; + /** @description Specifies the type of filter to apply, i.e 'CREDENTIAL_ID', 'NAME', 'USERNAME', 'EMAIL', 'PHONE_NUMBER', 'OIDC_TOKEN' or 'PUBLIC_KEY' */ + filterType?: string; + /** @description The value of the filter to apply for the specified type. For example, a specific email or name string. */ + filterValue?: string; + /** @description Parameters used for cursor-based pagination. */ + paginationOptions?: definitions["v1Pagination"]; + }; + v1GetSubOrgIdsResponse: { + /** @description List of unique identifiers for the matching sub-organizations. */ + organizationIds: string[]; + }; + v1GetUserRequest: { + /** @description Unique identifier for a given Organization. */ + organizationId: string; + /** @description Unique identifier for a given User. */ + userId: string; + }; + v1GetUserResponse: { + /** @description Web and/or API user within your Organization. */ + user: definitions["v1User"]; + }; + v1GetUsersRequest: { + /** @description Unique identifier for a given Organization. */ + organizationId: string; + }; + v1GetUsersResponse: { + /** @description A list of Users. */ + users: definitions["v1User"][]; + }; + v1GetVerifiedSubOrgIdsRequest: { + /** @description Unique identifier for the parent Organization. This is used to find sub-organizations within it. */ + organizationId: string; + /** @description Specifies the type of filter to apply, i.e 'EMAIL', 'PHONE_NUMBER' */ + filterType?: string; + /** @description The value of the filter to apply for the specified type. For example, a specific email or phone number string. */ + filterValue?: string; + /** @description Parameters used for cursor-based pagination. */ + paginationOptions?: definitions["v1Pagination"]; + }; + v1GetVerifiedSubOrgIdsResponse: { + /** @description List of unique identifiers for the matching sub-organizations. */ + organizationIds: string[]; + }; + v1GetWalletAccountRequest: { + /** @description Unique identifier for a given Organization. */ + organizationId: string; + /** @description Unique identifier for a given Wallet. */ + walletId: string; + /** @description Address corresponding to a Wallet Account. */ + address?: string; + /** @description Path corresponding to a Wallet Account. */ + path?: string; + }; + v1GetWalletAccountResponse: { + /** @description The resulting Wallet Account. */ + account: definitions["v1WalletAccount"]; + }; + v1GetWalletAccountsRequest: { + /** @description Unique identifier for a given Organization. */ + organizationId: string; + /** @description Unique identifier for a given Wallet. */ + walletId: string; + /** @description Parameters used for cursor-based pagination. */ + paginationOptions?: definitions["v1Pagination"]; + }; + v1GetWalletAccountsResponse: { + /** @description A list of Accounts generated from a Wallet that share a common seed. */ + accounts: definitions["v1WalletAccount"][]; + }; + v1GetWalletRequest: { + /** @description Unique identifier for a given Organization. */ + organizationId: string; + /** @description Unique identifier for a given Wallet. */ + walletId: string; + }; + v1GetWalletResponse: { + /** @description A collection of deterministically generated cryptographic public / private key pairs that share a common seed */ + wallet: definitions["v1Wallet"]; + }; + v1GetWalletsRequest: { + /** @description Unique identifier for a given Organization. */ + organizationId: string; + }; + v1GetWalletsResponse: { + /** @description A list of Wallets. */ + wallets: definitions["v1Wallet"][]; + }; + v1GetWhoamiRequest: { + /** @description Unique identifier for a given Organization. If the request is being made by a WebAuthN user and their Sub-Organization ID is unknown, this can be the Parent Organization ID; using the Sub-Organization ID when possible is preferred due to performance reasons. */ + organizationId: string; + }; + v1GetWhoamiResponse: { + /** @description Unique identifier for a given Organization. */ + organizationId: string; + /** @description Human-readable name for an Organization. */ + organizationName: string; + /** @description Unique identifier for a given User. */ + userId: string; + /** @description Human-readable name for a User. */ + username: string; + }; + /** @enum {string} */ + v1HashFunction: + | "HASH_FUNCTION_NO_OP" + | "HASH_FUNCTION_SHA256" + | "HASH_FUNCTION_KECCAK256" + | "HASH_FUNCTION_NOT_APPLICABLE"; + v1ImportPrivateKeyIntent: { + /** @description The ID of the User importing a Private Key. */ + userId: string; + /** @description Human-readable name for a Private Key. */ + privateKeyName: string; + /** @description Bundle containing a raw private key encrypted to the enclave's target public key. */ + encryptedBundle: string; + /** @description Cryptographic Curve used to generate a given Private Key. */ + curve: definitions["v1Curve"]; + /** @description Cryptocurrency-specific formats for a derived address (e.g., Ethereum). */ + addressFormats: definitions["v1AddressFormat"][]; + }; + v1ImportPrivateKeyRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_IMPORT_PRIVATE_KEY"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1ImportPrivateKeyIntent"]; + }; + v1ImportPrivateKeyResult: { + /** @description Unique identifier for a Private Key. */ + privateKeyId: string; + /** @description A list of addresses. */ + addresses: definitions["immutableactivityv1Address"][]; + }; + v1ImportWalletIntent: { + /** @description The ID of the User importing a Wallet. */ + userId: string; + /** @description Human-readable name for a Wallet. */ + walletName: string; + /** @description Bundle containing a wallet mnemonic encrypted to the enclave's target public key. */ + encryptedBundle: string; + /** @description A list of wallet Accounts. */ + accounts: definitions["v1WalletAccountParams"][]; + }; + v1ImportWalletRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_IMPORT_WALLET"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1ImportWalletIntent"]; + }; + v1ImportWalletResult: { + /** @description Unique identifier for a Wallet. */ + walletId: string; + /** @description A list of account addresses. */ + addresses: string[]; + }; + v1InitFiatOnRampIntent: { + /** @description Enum to specifiy which on-ramp provider to use */ + onrampProvider: definitions["v1FiatOnRampProvider"]; + /** @description Destination wallet address for the buy transaction. */ + walletAddress: string; + /** @description Blockchain network to be used for the transaction, e.g., bitcoin, ethereum. Maps to MoonPay's network or Coinbase's defaultNetwork. */ + network: definitions["v1FiatOnRampBlockchainNetwork"]; + /** @description Code for the cryptocurrency to be purchased, e.g., btc, eth. Maps to MoonPay's currencyCode or Coinbase's defaultAsset. */ + cryptoCurrencyCode: definitions["v1FiatOnRampCryptoCurrency"]; + /** @description Code for the fiat currency to be used in the transaction, e.g., USD, EUR. */ + fiatCurrencyCode?: definitions["v1FiatOnRampCurrency"]; + /** @description Specifies a preset fiat amount for the transaction, e.g., '100'. Must be greater than '20'. If not provided, the user will be prompted to enter an amount. */ + fiatCurrencyAmount?: string; + /** @description Pre-selected payment method, e.g., CREDIT_DEBIT_CARD, APPLE_PAY. Validated against the chosen provider. */ + paymentMethod?: definitions["v1FiatOnRampPaymentMethod"]; + /** @description ISO 3166-1 two-digit country code for Coinbase representing the purchasing user’s country of residence, e.g., US, GB. */ + countryCode?: string; + /** @description ISO 3166-2 two-digit country subdivision code for Coinbase representing the purchasing user’s subdivision of residence within their country, e.g. NY. Required if country_code=US. */ + countrySubdivisionCode?: string; + }; + v1InitFiatOnRampRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_INIT_FIAT_ON_RAMP"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1InitFiatOnRampIntent"]; + }; + v1InitFiatOnRampResult: { + /** @description Unique URL for a given fiat on-ramp flow. */ + onRampUrl: string; + /** @description Unique identifier used to retrieve transaction statuses for a given fiat on-ramp flow. */ + onRampTransactionId: string; + }; + v1InitImportPrivateKeyIntent: { + /** @description The ID of the User importing a Private Key. */ + userId: string; + }; + v1InitImportPrivateKeyRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_INIT_IMPORT_PRIVATE_KEY"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1InitImportPrivateKeyIntent"]; + }; + v1InitImportPrivateKeyResult: { + /** @description Import bundle containing a public key and signature to use for importing client data. */ + importBundle: string; + }; + v1InitImportWalletIntent: { + /** @description The ID of the User importing a Wallet. */ + userId: string; + }; + v1InitImportWalletRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_INIT_IMPORT_WALLET"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1InitImportWalletIntent"]; + }; + v1InitImportWalletResult: { + /** @description Import bundle containing a public key and signature to use for importing client data. */ + importBundle: string; + }; + v1InitOtpAuthIntent: { + /** @description Enum to specifiy whether to send OTP via SMS or email */ + otpType: string; + /** @description Email or phone number to send the OTP code to */ + contact: string; + /** @description Optional parameters for customizing emails. If not provided, the default email will be used. */ + emailCustomization?: definitions["v1EmailCustomizationParams"]; + /** @description Optional parameters for customizing SMS message. If not provided, the default sms message will be used. */ + smsCustomization?: definitions["v1SmsCustomizationParams"]; + /** @description Optional client-generated user identifier to enable per-user rate limiting for SMS auth. We recommend using a hash of the client-side IP address. */ + userIdentifier?: string; + /** @description Optional custom email address from which to send the OTP email */ + sendFromEmailAddress?: string; + /** @description Optional custom sender name for use with sendFromEmailAddress; if left empty, will default to 'Notifications' */ + sendFromEmailSenderName?: string; + /** @description Optional custom email address to use as reply-to */ + replyToEmailAddress?: string; + }; + v1InitOtpAuthIntentV2: { + /** @description Enum to specifiy whether to send OTP via SMS or email */ + otpType: string; + /** @description Email or phone number to send the OTP code to */ + contact: string; + /** + * Format: int32 + * @description Optional length of the OTP code. Default = 9 + */ + otpLength?: number; + /** @description Optional parameters for customizing emails. If not provided, the default email will be used. */ + emailCustomization?: definitions["v1EmailCustomizationParams"]; + /** @description Optional parameters for customizing SMS message. If not provided, the default sms message will be used. */ + smsCustomization?: definitions["v1SmsCustomizationParams"]; + /** @description Optional client-generated user identifier to enable per-user rate limiting for SMS auth. We recommend using a hash of the client-side IP address. */ + userIdentifier?: string; + /** @description Optional custom email address from which to send the OTP email */ + sendFromEmailAddress?: string; + /** @description Optional flag to specify if the OTP code should be alphanumeric (Crockford’s Base32). Default = true */ + alphanumeric?: boolean; + /** @description Optional custom sender name for use with sendFromEmailAddress; if left empty, will default to 'Notifications' */ + sendFromEmailSenderName?: string; + /** @description Optional custom email address to use as reply-to */ + replyToEmailAddress?: string; + }; + v1InitOtpAuthRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_INIT_OTP_AUTH_V2"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1InitOtpAuthIntentV2"]; + }; + v1InitOtpAuthResult: { + /** @description Unique identifier for an OTP authentication */ + otpId: string; + }; + v1InitOtpAuthResultV2: { + /** @description Unique identifier for an OTP authentication */ + otpId: string; + }; + v1InitOtpIntent: { + /** @description Whether to send OTP via SMS or email. Possible values: OTP_TYPE_SMS, OTP_TYPE_EMAIL */ + otpType: string; + /** @description Email or phone number to send the OTP code to */ + contact: string; + /** + * Format: int32 + * @description Optional length of the OTP code. Default = 9 + */ + otpLength?: number; + /** @description Optional parameters for customizing emails. If not provided, the default email will be used. */ + emailCustomization?: definitions["v1EmailCustomizationParams"]; + /** @description Optional parameters for customizing SMS message. If not provided, the default sms message will be used. */ + smsCustomization?: definitions["v1SmsCustomizationParams"]; + /** @description Optional client-generated user identifier to enable per-user rate limiting for SMS auth. We recommend using a hash of the client-side IP address. */ + userIdentifier?: string; + /** @description Optional custom email address from which to send the OTP email */ + sendFromEmailAddress?: string; + /** @description Optional flag to specify if the OTP code should be alphanumeric (Crockford’s Base32). Default = true */ + alphanumeric?: boolean; + /** @description Optional custom sender name for use with sendFromEmailAddress; if left empty, will default to 'Notifications' */ + sendFromEmailSenderName?: string; + /** @description Expiration window (in seconds) indicating how long the OTP is valid for. If not provided, a default of 5 minutes will be used. Maximum value is 600 seconds (10 minutes) */ + expirationSeconds?: string; + /** @description Optional custom email address to use as reply-to */ + replyToEmailAddress?: string; + }; + v1InitOtpRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_INIT_OTP"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1InitOtpIntent"]; + }; + v1InitOtpResult: { + /** @description Unique identifier for an OTP authentication */ + otpId: string; + }; + v1InitUserEmailRecoveryIntent: { + /** @description Email of the user starting recovery */ + email: string; + /** @description Client-side public key generated by the user, to which the recovery bundle will be encrypted. */ + targetPublicKey: string; + /** @description Expiration window (in seconds) indicating how long the recovery credential is valid for. If not provided, a default of 15 minutes will be used. */ + expirationSeconds?: string; + /** @description Optional parameters for customizing emails. If not provided, the default email will be used. */ + emailCustomization?: definitions["v1EmailCustomizationParams"]; + }; + v1InitUserEmailRecoveryRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_INIT_USER_EMAIL_RECOVERY"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1InitUserEmailRecoveryIntent"]; + }; + v1InitUserEmailRecoveryResult: { + /** @description Unique identifier for the user being recovered. */ + userId: string; + }; + v1Intent: { + createOrganizationIntent?: definitions["v1CreateOrganizationIntent"]; + createAuthenticatorsIntent?: definitions["v1CreateAuthenticatorsIntent"]; + createUsersIntent?: definitions["v1CreateUsersIntent"]; + createPrivateKeysIntent?: definitions["v1CreatePrivateKeysIntent"]; + signRawPayloadIntent?: definitions["v1SignRawPayloadIntent"]; + createInvitationsIntent?: definitions["v1CreateInvitationsIntent"]; + acceptInvitationIntent?: definitions["v1AcceptInvitationIntent"]; + createPolicyIntent?: definitions["v1CreatePolicyIntent"]; + disablePrivateKeyIntent?: definitions["v1DisablePrivateKeyIntent"]; + deleteUsersIntent?: definitions["v1DeleteUsersIntent"]; + deleteAuthenticatorsIntent?: definitions["v1DeleteAuthenticatorsIntent"]; + deleteInvitationIntent?: definitions["v1DeleteInvitationIntent"]; + deleteOrganizationIntent?: definitions["v1DeleteOrganizationIntent"]; + deletePolicyIntent?: definitions["v1DeletePolicyIntent"]; + createUserTagIntent?: definitions["v1CreateUserTagIntent"]; + deleteUserTagsIntent?: definitions["v1DeleteUserTagsIntent"]; + signTransactionIntent?: definitions["v1SignTransactionIntent"]; + createApiKeysIntent?: definitions["v1CreateApiKeysIntent"]; + deleteApiKeysIntent?: definitions["v1DeleteApiKeysIntent"]; + approveActivityIntent?: definitions["v1ApproveActivityIntent"]; + rejectActivityIntent?: definitions["v1RejectActivityIntent"]; + createPrivateKeyTagIntent?: definitions["v1CreatePrivateKeyTagIntent"]; + deletePrivateKeyTagsIntent?: definitions["v1DeletePrivateKeyTagsIntent"]; + createPolicyIntentV2?: definitions["v1CreatePolicyIntentV2"]; + setPaymentMethodIntent?: definitions["billingSetPaymentMethodIntent"]; + activateBillingTierIntent?: definitions["billingActivateBillingTierIntent"]; + deletePaymentMethodIntent?: definitions["billingDeletePaymentMethodIntent"]; + createPolicyIntentV3?: definitions["v1CreatePolicyIntentV3"]; + createApiOnlyUsersIntent?: definitions["v1CreateApiOnlyUsersIntent"]; + updateRootQuorumIntent?: definitions["v1UpdateRootQuorumIntent"]; + updateUserTagIntent?: definitions["v1UpdateUserTagIntent"]; + updatePrivateKeyTagIntent?: definitions["v1UpdatePrivateKeyTagIntent"]; + createAuthenticatorsIntentV2?: definitions["v1CreateAuthenticatorsIntentV2"]; + acceptInvitationIntentV2?: definitions["v1AcceptInvitationIntentV2"]; + createOrganizationIntentV2?: definitions["v1CreateOrganizationIntentV2"]; + createUsersIntentV2?: definitions["v1CreateUsersIntentV2"]; + createSubOrganizationIntent?: definitions["v1CreateSubOrganizationIntent"]; + createSubOrganizationIntentV2?: definitions["v1CreateSubOrganizationIntentV2"]; + updateAllowedOriginsIntent?: definitions["v1UpdateAllowedOriginsIntent"]; + createPrivateKeysIntentV2?: definitions["v1CreatePrivateKeysIntentV2"]; + updateUserIntent?: definitions["v1UpdateUserIntent"]; + updatePolicyIntent?: definitions["v1UpdatePolicyIntent"]; + setPaymentMethodIntentV2?: definitions["billingSetPaymentMethodIntentV2"]; + createSubOrganizationIntentV3?: definitions["v1CreateSubOrganizationIntentV3"]; + createWalletIntent?: definitions["v1CreateWalletIntent"]; + createWalletAccountsIntent?: definitions["v1CreateWalletAccountsIntent"]; + initUserEmailRecoveryIntent?: definitions["v1InitUserEmailRecoveryIntent"]; + recoverUserIntent?: definitions["v1RecoverUserIntent"]; + setOrganizationFeatureIntent?: definitions["v1SetOrganizationFeatureIntent"]; + removeOrganizationFeatureIntent?: definitions["v1RemoveOrganizationFeatureIntent"]; + signRawPayloadIntentV2?: definitions["v1SignRawPayloadIntentV2"]; + signTransactionIntentV2?: definitions["v1SignTransactionIntentV2"]; + exportPrivateKeyIntent?: definitions["v1ExportPrivateKeyIntent"]; + exportWalletIntent?: definitions["v1ExportWalletIntent"]; + createSubOrganizationIntentV4?: definitions["v1CreateSubOrganizationIntentV4"]; + emailAuthIntent?: definitions["v1EmailAuthIntent"]; + exportWalletAccountIntent?: definitions["v1ExportWalletAccountIntent"]; + initImportWalletIntent?: definitions["v1InitImportWalletIntent"]; + importWalletIntent?: definitions["v1ImportWalletIntent"]; + initImportPrivateKeyIntent?: definitions["v1InitImportPrivateKeyIntent"]; + importPrivateKeyIntent?: definitions["v1ImportPrivateKeyIntent"]; + createPoliciesIntent?: definitions["v1CreatePoliciesIntent"]; + signRawPayloadsIntent?: definitions["v1SignRawPayloadsIntent"]; + createReadOnlySessionIntent?: definitions["v1CreateReadOnlySessionIntent"]; + createOauthProvidersIntent?: definitions["v1CreateOauthProvidersIntent"]; + deleteOauthProvidersIntent?: definitions["v1DeleteOauthProvidersIntent"]; + createSubOrganizationIntentV5?: definitions["v1CreateSubOrganizationIntentV5"]; + oauthIntent?: definitions["v1OauthIntent"]; + createApiKeysIntentV2?: definitions["v1CreateApiKeysIntentV2"]; + createReadWriteSessionIntent?: definitions["v1CreateReadWriteSessionIntent"]; + emailAuthIntentV2?: definitions["v1EmailAuthIntentV2"]; + createSubOrganizationIntentV6?: definitions["v1CreateSubOrganizationIntentV6"]; + deletePrivateKeysIntent?: definitions["v1DeletePrivateKeysIntent"]; + deleteWalletsIntent?: definitions["v1DeleteWalletsIntent"]; + createReadWriteSessionIntentV2?: definitions["v1CreateReadWriteSessionIntentV2"]; + deleteSubOrganizationIntent?: definitions["v1DeleteSubOrganizationIntent"]; + initOtpAuthIntent?: definitions["v1InitOtpAuthIntent"]; + otpAuthIntent?: definitions["v1OtpAuthIntent"]; + createSubOrganizationIntentV7?: definitions["v1CreateSubOrganizationIntentV7"]; + updateWalletIntent?: definitions["v1UpdateWalletIntent"]; + updatePolicyIntentV2?: definitions["v1UpdatePolicyIntentV2"]; + createUsersIntentV3?: definitions["v1CreateUsersIntentV3"]; + initOtpAuthIntentV2?: definitions["v1InitOtpAuthIntentV2"]; + initOtpIntent?: definitions["v1InitOtpIntent"]; + verifyOtpIntent?: definitions["v1VerifyOtpIntent"]; + otpLoginIntent?: definitions["v1OtpLoginIntent"]; + stampLoginIntent?: definitions["v1StampLoginIntent"]; + oauthLoginIntent?: definitions["v1OauthLoginIntent"]; + updateUserNameIntent?: definitions["v1UpdateUserNameIntent"]; + updateUserEmailIntent?: definitions["v1UpdateUserEmailIntent"]; + updateUserPhoneNumberIntent?: definitions["v1UpdateUserPhoneNumberIntent"]; + initFiatOnRampIntent?: definitions["v1InitFiatOnRampIntent"]; + createSmartContractInterfaceIntent?: definitions["v1CreateSmartContractInterfaceIntent"]; + deleteSmartContractInterfaceIntent?: definitions["v1DeleteSmartContractInterfaceIntent"]; + enableUserInitiatedAuthIntent?: definitions["v1EnableUserInitiatedAuthIntent"]; + disableUserInitiatedAuthIntent?: definitions["v1DisableUserInitiatedAuthIntent"]; + updateProxyAuthConfigIntent?: definitions["v1UpdateProxyAuthConfigIntent"]; + }; + v1Invitation: { + /** @description Unique identifier for a given Invitation object. */ + invitationId: string; + /** @description The name of the intended Invitation recipient. */ + receiverUserName: string; + /** @description The email address of the intended Invitation recipient. */ + receiverEmail: string; + /** @description A list of tags assigned to the Invitation recipient. */ + receiverUserTags: string[]; + /** @description The User's permissible access method(s). */ + accessType: definitions["v1AccessType"]; + /** @description The current processing status of a specified Invitation. */ + status: definitions["v1InvitationStatus"]; + createdAt: definitions["externaldatav1Timestamp"]; + updatedAt: definitions["externaldatav1Timestamp"]; + /** @description Unique identifier for the Sender of an Invitation. */ + senderUserId: string; + }; + v1InvitationParams: { + /** @description The name of the intended Invitation recipient. */ + receiverUserName: string; + /** @description The email address of the intended Invitation recipient. */ + receiverUserEmail: string; + /** @description A list of tags assigned to the Invitation recipient. This field, if not needed, should be an empty array in your request body. */ + receiverUserTags: string[]; + /** @description The User's permissible access method(s). */ + accessType: definitions["v1AccessType"]; + /** @description Unique identifier for the Sender of an Invitation. */ + senderUserId: string; + }; + /** @enum {string} */ + v1InvitationStatus: + | "INVITATION_STATUS_CREATED" + | "INVITATION_STATUS_ACCEPTED" + | "INVITATION_STATUS_REVOKED"; + v1ListPrivateKeyTagsRequest: { + /** @description Unique identifier for a given Organization. */ + organizationId: string; + }; + v1ListPrivateKeyTagsResponse: { + /** @description A list of Private Key Tags */ + privateKeyTags: definitions["datav1Tag"][]; + }; + v1ListUserTagsRequest: { + /** @description Unique identifier for a given Organization. */ + organizationId: string; + }; + v1ListUserTagsResponse: { + /** @description A list of User Tags */ + userTags: definitions["datav1Tag"][]; + }; + /** @enum {string} */ + v1MnemonicLanguage: + | "MNEMONIC_LANGUAGE_ENGLISH" + | "MNEMONIC_LANGUAGE_SIMPLIFIED_CHINESE" + | "MNEMONIC_LANGUAGE_TRADITIONAL_CHINESE" + | "MNEMONIC_LANGUAGE_CZECH" + | "MNEMONIC_LANGUAGE_FRENCH" + | "MNEMONIC_LANGUAGE_ITALIAN" + | "MNEMONIC_LANGUAGE_JAPANESE" + | "MNEMONIC_LANGUAGE_KOREAN" + | "MNEMONIC_LANGUAGE_SPANISH"; + v1NOOPCodegenAnchorResponse: { + stamp: definitions["v1WebAuthnStamp"]; + }; + v1OauthIntent: { + /** @description Base64 encoded OIDC token */ + oidcToken: string; + /** @description Client-side public key generated by the user, to which the oauth bundle (credentials) will be encrypted. */ + targetPublicKey: string; + /** @description Optional human-readable name for an API Key. If none provided, default to Oauth - */ + apiKeyName?: string; + /** @description Expiration window (in seconds) indicating how long the API key is valid for. If not provided, a default of 15 minutes will be used. */ + expirationSeconds?: string; + /** @description Invalidate all other previously generated Oauth API keys */ + invalidateExisting?: boolean; + }; + v1OauthLoginIntent: { + /** @description Base64 encoded OIDC token */ + oidcToken: string; + /** @description Client-side public key generated by the user, which will be conditionally added to org data based on the validity of the oidc token associated with this request */ + publicKey: string; + /** @description Expiration window (in seconds) indicating how long the Session is valid for. If not provided, a default of 15 minutes will be used. */ + expirationSeconds?: string; + /** @description Invalidate all other previously generated Login API keys */ + invalidateExisting?: boolean; + }; + v1OauthLoginRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_OAUTH_LOGIN"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1OauthLoginIntent"]; + }; + v1OauthLoginResult: { + /** @description Signed JWT containing an expiry, public key, session type, user id, and organization id */ + session: string; + }; + v1OauthProvider: { + /** @description Unique identifier for an OAuth Provider */ + providerId: string; + /** @description Human-readable name to identify a Provider. */ + providerName: string; + /** @description The issuer of the token, typically a URL indicating the authentication server, e.g https://accounts.google.com */ + issuer: string; + /** @description Expected audience ('aud' attribute of the signed token) which represents the app ID */ + audience: string; + /** @description Expected subject ('sub' attribute of the signed token) which represents the user ID */ + subject: string; + createdAt: definitions["externaldatav1Timestamp"]; + updatedAt: definitions["externaldatav1Timestamp"]; + }; + v1OauthProviderParams: { + /** @description Human-readable name to identify a Provider. */ + providerName: string; + /** @description Base64 encoded OIDC token */ + oidcToken: string; + }; + v1OauthRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_OAUTH"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1OauthIntent"]; + }; + v1OauthResult: { + /** @description Unique identifier for the authenticating User. */ + userId: string; + /** @description Unique identifier for the created API key. */ + apiKeyId: string; + /** @description HPKE encrypted credential bundle */ + credentialBundle: string; + }; + /** @enum {string} */ + v1Operator: + | "OPERATOR_EQUAL" + | "OPERATOR_MORE_THAN" + | "OPERATOR_MORE_THAN_OR_EQUAL" + | "OPERATOR_LESS_THAN" + | "OPERATOR_LESS_THAN_OR_EQUAL" + | "OPERATOR_CONTAINS" + | "OPERATOR_NOT_EQUAL" + | "OPERATOR_IN" + | "OPERATOR_NOT_IN" + | "OPERATOR_CONTAINS_ONE" + | "OPERATOR_CONTAINS_ALL"; + v1OrganizationData: { + organizationId?: string; + name?: string; + users?: definitions["v1User"][]; + policies?: definitions["v1Policy"][]; + privateKeys?: definitions["v1PrivateKey"][]; + invitations?: definitions["v1Invitation"][]; + tags?: definitions["datav1Tag"][]; + rootQuorum?: definitions["externaldatav1Quorum"]; + features?: definitions["v1Feature"][]; + wallets?: definitions["v1Wallet"][]; + smartContractInterfaceReferences?: definitions["v1SmartContractInterfaceReference"][]; + }; + v1OtpAuthIntent: { + /** @description ID representing the result of an init OTP activity. */ + otpId: string; + /** @description OTP sent out to a user's contact (email or SMS) */ + otpCode: string; + /** @description Client-side public key generated by the user, to which the OTP bundle (credentials) will be encrypted. */ + targetPublicKey: string; + /** @description Optional human-readable name for an API Key. If none provided, default to OTP Auth - */ + apiKeyName?: string; + /** @description Expiration window (in seconds) indicating how long the API key is valid for. If not provided, a default of 15 minutes will be used. */ + expirationSeconds?: string; + /** @description Invalidate all other previously generated OTP Auth API keys */ + invalidateExisting?: boolean; + }; + v1OtpAuthRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_OTP_AUTH"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1OtpAuthIntent"]; + }; + v1OtpAuthResult: { + /** @description Unique identifier for the authenticating User. */ + userId: string; + /** @description Unique identifier for the created API key. */ + apiKeyId?: string; + /** @description HPKE encrypted credential bundle */ + credentialBundle?: string; + }; + v1OtpLoginIntent: { + /** @description Signed JWT containing a unique id, expiry, verification type, contact */ + verificationToken: string; + /** @description Client-side public key generated by the user, which will be conditionally added to org data based on the validity of the verification token */ + publicKey: string; + /** @description Expiration window (in seconds) indicating how long the Session is valid for. If not provided, a default of 15 minutes will be used. */ + expirationSeconds?: string; + /** @description Invalidate all other previously generated Login API keys */ + invalidateExisting?: boolean; + }; + v1OtpLoginRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_OTP_LOGIN"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1OtpLoginIntent"]; + }; + v1OtpLoginResult: { + /** @description Signed JWT containing an expiry, public key, session type, user id, and organization id */ + session: string; + }; + v1Pagination: { + /** @description A limit of the number of object to be returned, between 1 and 100. Defaults to 10. */ + limit?: string; + /** @description A pagination cursor. This is an object ID that enables you to fetch all objects before this ID. */ + before?: string; + /** @description A pagination cursor. This is an object ID that enables you to fetch all objects after this ID. */ + after?: string; + }; + /** @enum {string} */ + v1PathFormat: "PATH_FORMAT_BIP32"; + /** @enum {string} */ + v1PayloadEncoding: + | "PAYLOAD_ENCODING_HEXADECIMAL" + | "PAYLOAD_ENCODING_TEXT_UTF8" + | "PAYLOAD_ENCODING_EIP712"; + v1Policy: { + /** @description Unique identifier for a given Policy. */ + policyId: string; + /** @description Human-readable name for a Policy. */ + policyName: string; + /** @description The instruction to DENY or ALLOW a particular activity following policy selector(s). */ + effect: definitions["v1Effect"]; + createdAt: definitions["externaldatav1Timestamp"]; + updatedAt: definitions["externaldatav1Timestamp"]; + /** @description Human-readable notes added by a User to describe a particular policy. */ + notes: string; + /** @description A consensus expression that evalutes to true or false. */ + consensus: string; + /** @description A condition expression that evalutes to true or false. */ + condition: string; + }; + v1PrivateKey: { + /** @description Unique identifier for a given Private Key. */ + privateKeyId: string; + /** @description The public component of a cryptographic key pair used to sign messages and transactions. */ + publicKey: string; + /** @description Human-readable name for a Private Key. */ + privateKeyName: string; + /** @description Cryptographic Curve used to generate a given Private Key. */ + curve: definitions["v1Curve"]; + /** @description Derived cryptocurrency addresses for a given Private Key. */ + addresses: definitions["externaldatav1Address"][]; + /** @description A list of Private Key Tag IDs. */ + privateKeyTags: string[]; + createdAt: definitions["externaldatav1Timestamp"]; + updatedAt: definitions["externaldatav1Timestamp"]; + /** @description True when a given Private Key is exported, false otherwise. */ + exported: boolean; + /** @description True when a given Private Key is imported, false otherwise. */ + imported: boolean; + }; + v1PrivateKeyParams: { + /** @description Human-readable name for a Private Key. */ + privateKeyName: string; + /** @description Cryptographic Curve used to generate a given Private Key. */ + curve: definitions["v1Curve"]; + /** @description A list of Private Key Tag IDs. This field, if not needed, should be an empty array in your request body. */ + privateKeyTags: string[]; + /** @description Cryptocurrency-specific formats for a derived address (e.g., Ethereum). */ + addressFormats: definitions["v1AddressFormat"][]; + }; + v1PrivateKeyResult: { + privateKeyId?: string; + addresses?: definitions["immutableactivityv1Address"][]; + }; + v1ProxyAuthConfig: { + organizationId?: string; + allowedOrigins?: string[]; + allowedAuthMethods?: string[]; + encryptedApiKey?: string; + turnkeySignerUserId?: string; + sendFromEmailAddress?: string; + replyToEmailAddress?: string; + emailAuthTemplateId?: string; + otpTemplateId?: string; + emailCustomizationParams?: string; + smsCustomizationParams?: string; + /** Format: int32 */ + otpExpirationSeconds?: number; + /** Format: int32 */ + verificationTokenExpirationSeconds?: number; + /** Format: int32 */ + otpSessionExpirationSeconds?: number; + /** Format: int32 */ + oauthSessionExpirationSeconds?: number; + /** Format: int32 */ + passkeySessionExpirationSeconds?: number; + /** Format: int32 */ + walletSessionExpirationSeconds?: number; + /** Format: date-time */ + createdAt?: string; + /** Format: date-time */ + updatedAt?: string; + otpAlphanumeric?: boolean; + /** Format: int32 */ + otpLength?: number; + socialLinking?: boolean; + policyId?: string; + proxyId?: string; + ewkSettings?: string; + }; + v1PublicKeyCredentialWithAttestation: { + id: string; + /** @enum {string} */ + type: "public-key"; + rawId: string; + /** @enum {string} */ + authenticatorAttachment?: "cross-platform" | "platform" | null; + response: definitions["v1AuthenticatorAttestationResponse"]; + clientExtensionResults: definitions["v1SimpleClientExtensionResults"]; + }; + v1RecoverUserIntent: { + /** @description The new authenticator to register. */ + authenticator: definitions["v1AuthenticatorParamsV2"]; + /** @description Unique identifier for the user performing recovery. */ + userId: string; + }; + v1RecoverUserRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_RECOVER_USER"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1RecoverUserIntent"]; + }; + v1RecoverUserResult: { + /** @description ID of the authenticator created. */ + authenticatorId: string[]; + }; + v1RejectActivityIntent: { + /** @description An artifact verifying a User's action. */ + fingerprint: string; + }; + v1RejectActivityRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_REJECT_ACTIVITY"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1RejectActivityIntent"]; + }; + v1RemoveOrganizationFeatureIntent: { + /** @description Name of the feature to remove */ + name: definitions["v1FeatureName"]; + }; + v1RemoveOrganizationFeatureRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_REMOVE_ORGANIZATION_FEATURE"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1RemoveOrganizationFeatureIntent"]; + }; + v1RemoveOrganizationFeatureResult: { + /** @description Resulting list of organization features. */ + features: definitions["v1Feature"][]; + }; + v1Result: { + createOrganizationResult?: definitions["v1CreateOrganizationResult"]; + createAuthenticatorsResult?: definitions["v1CreateAuthenticatorsResult"]; + createUsersResult?: definitions["v1CreateUsersResult"]; + createPrivateKeysResult?: definitions["v1CreatePrivateKeysResult"]; + createInvitationsResult?: definitions["v1CreateInvitationsResult"]; + acceptInvitationResult?: definitions["v1AcceptInvitationResult"]; + signRawPayloadResult?: definitions["v1SignRawPayloadResult"]; + createPolicyResult?: definitions["v1CreatePolicyResult"]; + disablePrivateKeyResult?: definitions["v1DisablePrivateKeyResult"]; + deleteUsersResult?: definitions["v1DeleteUsersResult"]; + deleteAuthenticatorsResult?: definitions["v1DeleteAuthenticatorsResult"]; + deleteInvitationResult?: definitions["v1DeleteInvitationResult"]; + deleteOrganizationResult?: definitions["v1DeleteOrganizationResult"]; + deletePolicyResult?: definitions["v1DeletePolicyResult"]; + createUserTagResult?: definitions["v1CreateUserTagResult"]; + deleteUserTagsResult?: definitions["v1DeleteUserTagsResult"]; + signTransactionResult?: definitions["v1SignTransactionResult"]; + deleteApiKeysResult?: definitions["v1DeleteApiKeysResult"]; + createApiKeysResult?: definitions["v1CreateApiKeysResult"]; + createPrivateKeyTagResult?: definitions["v1CreatePrivateKeyTagResult"]; + deletePrivateKeyTagsResult?: definitions["v1DeletePrivateKeyTagsResult"]; + setPaymentMethodResult?: definitions["billingSetPaymentMethodResult"]; + activateBillingTierResult?: definitions["billingActivateBillingTierResult"]; + deletePaymentMethodResult?: definitions["billingDeletePaymentMethodResult"]; + createApiOnlyUsersResult?: definitions["v1CreateApiOnlyUsersResult"]; + updateRootQuorumResult?: definitions["v1UpdateRootQuorumResult"]; + updateUserTagResult?: definitions["v1UpdateUserTagResult"]; + updatePrivateKeyTagResult?: definitions["v1UpdatePrivateKeyTagResult"]; + createSubOrganizationResult?: definitions["v1CreateSubOrganizationResult"]; + updateAllowedOriginsResult?: definitions["v1UpdateAllowedOriginsResult"]; + createPrivateKeysResultV2?: definitions["v1CreatePrivateKeysResultV2"]; + updateUserResult?: definitions["v1UpdateUserResult"]; + updatePolicyResult?: definitions["v1UpdatePolicyResult"]; + createSubOrganizationResultV3?: definitions["v1CreateSubOrganizationResultV3"]; + createWalletResult?: definitions["v1CreateWalletResult"]; + createWalletAccountsResult?: definitions["v1CreateWalletAccountsResult"]; + initUserEmailRecoveryResult?: definitions["v1InitUserEmailRecoveryResult"]; + recoverUserResult?: definitions["v1RecoverUserResult"]; + setOrganizationFeatureResult?: definitions["v1SetOrganizationFeatureResult"]; + removeOrganizationFeatureResult?: definitions["v1RemoveOrganizationFeatureResult"]; + exportPrivateKeyResult?: definitions["v1ExportPrivateKeyResult"]; + exportWalletResult?: definitions["v1ExportWalletResult"]; + createSubOrganizationResultV4?: definitions["v1CreateSubOrganizationResultV4"]; + emailAuthResult?: definitions["v1EmailAuthResult"]; + exportWalletAccountResult?: definitions["v1ExportWalletAccountResult"]; + initImportWalletResult?: definitions["v1InitImportWalletResult"]; + importWalletResult?: definitions["v1ImportWalletResult"]; + initImportPrivateKeyResult?: definitions["v1InitImportPrivateKeyResult"]; + importPrivateKeyResult?: definitions["v1ImportPrivateKeyResult"]; + createPoliciesResult?: definitions["v1CreatePoliciesResult"]; + signRawPayloadsResult?: definitions["v1SignRawPayloadsResult"]; + createReadOnlySessionResult?: definitions["v1CreateReadOnlySessionResult"]; + createOauthProvidersResult?: definitions["v1CreateOauthProvidersResult"]; + deleteOauthProvidersResult?: definitions["v1DeleteOauthProvidersResult"]; + createSubOrganizationResultV5?: definitions["v1CreateSubOrganizationResultV5"]; + oauthResult?: definitions["v1OauthResult"]; + createReadWriteSessionResult?: definitions["v1CreateReadWriteSessionResult"]; + createSubOrganizationResultV6?: definitions["v1CreateSubOrganizationResultV6"]; + deletePrivateKeysResult?: definitions["v1DeletePrivateKeysResult"]; + deleteWalletsResult?: definitions["v1DeleteWalletsResult"]; + createReadWriteSessionResultV2?: definitions["v1CreateReadWriteSessionResultV2"]; + deleteSubOrganizationResult?: definitions["v1DeleteSubOrganizationResult"]; + initOtpAuthResult?: definitions["v1InitOtpAuthResult"]; + otpAuthResult?: definitions["v1OtpAuthResult"]; + createSubOrganizationResultV7?: definitions["v1CreateSubOrganizationResultV7"]; + updateWalletResult?: definitions["v1UpdateWalletResult"]; + updatePolicyResultV2?: definitions["v1UpdatePolicyResultV2"]; + initOtpAuthResultV2?: definitions["v1InitOtpAuthResultV2"]; + initOtpResult?: definitions["v1InitOtpResult"]; + verifyOtpResult?: definitions["v1VerifyOtpResult"]; + otpLoginResult?: definitions["v1OtpLoginResult"]; + stampLoginResult?: definitions["v1StampLoginResult"]; + oauthLoginResult?: definitions["v1OauthLoginResult"]; + updateUserNameResult?: definitions["v1UpdateUserNameResult"]; + updateUserEmailResult?: definitions["v1UpdateUserEmailResult"]; + updateUserPhoneNumberResult?: definitions["v1UpdateUserPhoneNumberResult"]; + initFiatOnRampResult?: definitions["v1InitFiatOnRampResult"]; + createSmartContractInterfaceResult?: definitions["v1CreateSmartContractInterfaceResult"]; + deleteSmartContractInterfaceResult?: definitions["v1DeleteSmartContractInterfaceResult"]; + enableUserInitiatedAuthResult?: definitions["v1EnableUserInitiatedAuthResult"]; + disableUserInitiatedAuthResult?: definitions["v1DisableUserInitiatedAuthResult"]; + updateProxyAuthConfigResult?: definitions["v1UpdateProxyAuthConfigResult"]; + }; + v1RootUserParams: { + /** @description Human-readable name for a User. */ + userName: string; + /** @description The user's email address. */ + userEmail?: string; + /** @description A list of API Key parameters. This field, if not needed, should be an empty array in your request body. */ + apiKeys: definitions["apiApiKeyParams"][]; + /** @description A list of Authenticator parameters. This field, if not needed, should be an empty array in your request body. */ + authenticators: definitions["v1AuthenticatorParamsV2"][]; + }; + v1RootUserParamsV2: { + /** @description Human-readable name for a User. */ + userName: string; + /** @description The user's email address. */ + userEmail?: string; + /** @description A list of API Key parameters. This field, if not needed, should be an empty array in your request body. */ + apiKeys: definitions["apiApiKeyParams"][]; + /** @description A list of Authenticator parameters. This field, if not needed, should be an empty array in your request body. */ + authenticators: definitions["v1AuthenticatorParamsV2"][]; + /** @description A list of Oauth providers. This field, if not needed, should be an empty array in your request body. */ + oauthProviders: definitions["v1OauthProviderParams"][]; + }; + v1RootUserParamsV3: { + /** @description Human-readable name for a User. */ + userName: string; + /** @description The user's email address. */ + userEmail?: string; + /** @description A list of API Key parameters. This field, if not needed, should be an empty array in your request body. */ + apiKeys: definitions["v1ApiKeyParamsV2"][]; + /** @description A list of Authenticator parameters. This field, if not needed, should be an empty array in your request body. */ + authenticators: definitions["v1AuthenticatorParamsV2"][]; + /** @description A list of Oauth providers. This field, if not needed, should be an empty array in your request body. */ + oauthProviders: definitions["v1OauthProviderParams"][]; + }; + v1RootUserParamsV4: { + /** @description Human-readable name for a User. */ + userName: string; + /** @description The user's email address. */ + userEmail?: string; + /** @description The user's phone number in E.164 format e.g. +13214567890 */ + userPhoneNumber?: string; + /** @description A list of API Key parameters. This field, if not needed, should be an empty array in your request body. */ + apiKeys: definitions["v1ApiKeyParamsV2"][]; + /** @description A list of Authenticator parameters. This field, if not needed, should be an empty array in your request body. */ + authenticators: definitions["v1AuthenticatorParamsV2"][]; + /** @description A list of Oauth providers. This field, if not needed, should be an empty array in your request body. */ + oauthProviders: definitions["v1OauthProviderParams"][]; + }; + v1Selector: { + subject?: string; + operator?: definitions["v1Operator"]; + target?: string; + }; + v1SelectorV2: { + subject?: string; + operator?: definitions["v1Operator"]; + targets?: string[]; + }; + v1SetOrganizationFeatureIntent: { + /** @description Name of the feature to set */ + name: definitions["v1FeatureName"]; + /** @description Optional value for the feature. Will override existing values if feature is already set. */ + value: string; + }; + v1SetOrganizationFeatureRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_SET_ORGANIZATION_FEATURE"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1SetOrganizationFeatureIntent"]; + }; + v1SetOrganizationFeatureResult: { + /** @description Resulting list of organization features. */ + features: definitions["v1Feature"][]; + }; + v1SignRawPayloadIntent: { + /** @description Unique identifier for a given Private Key. */ + privateKeyId: string; + /** @description Raw unsigned payload to be signed. */ + payload: string; + /** @description Encoding of the `payload` string. Turnkey uses this information to convert `payload` into bytes with the correct decoder (e.g. hex, utf8). */ + encoding: definitions["v1PayloadEncoding"]; + /** @description Hash function to apply to payload bytes before signing. This field must be set to HASH_FUNCTION_NOT_APPLICABLE for EdDSA/ed25519 signature requests; configurable payload hashing is not supported by RFC 8032. */ + hashFunction: definitions["v1HashFunction"]; + }; + v1SignRawPayloadIntentV2: { + /** @description A Wallet account address, Private Key address, or Private Key identifier. */ + signWith: string; + /** @description Raw unsigned payload to be signed. */ + payload: string; + /** @description Encoding of the `payload` string. Turnkey uses this information to convert `payload` into bytes with the correct decoder (e.g. hex, utf8). */ + encoding: definitions["v1PayloadEncoding"]; + /** @description Hash function to apply to payload bytes before signing. This field must be set to HASH_FUNCTION_NOT_APPLICABLE for EdDSA/ed25519 signature requests; configurable payload hashing is not supported by RFC 8032. */ + hashFunction: definitions["v1HashFunction"]; + }; + v1SignRawPayloadRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_SIGN_RAW_PAYLOAD_V2"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1SignRawPayloadIntentV2"]; + }; + v1SignRawPayloadResult: { + /** @description Component of an ECSDA signature. */ + r: string; + /** @description Component of an ECSDA signature. */ + s: string; + /** @description Component of an ECSDA signature. */ + v: string; + }; + v1SignRawPayloadsIntent: { + /** @description A Wallet account address, Private Key address, or Private Key identifier. */ + signWith: string; + /** @description An array of raw unsigned payloads to be signed. */ + payloads: string[]; + /** @description Encoding of the `payload` string. Turnkey uses this information to convert `payload` into bytes with the correct decoder (e.g. hex, utf8). */ + encoding: definitions["v1PayloadEncoding"]; + /** @description Hash function to apply to payload bytes before signing. This field must be set to HASH_FUNCTION_NOT_APPLICABLE for EdDSA/ed25519 signature requests; configurable payload hashing is not supported by RFC 8032. */ + hashFunction: definitions["v1HashFunction"]; + }; + v1SignRawPayloadsRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_SIGN_RAW_PAYLOADS"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1SignRawPayloadsIntent"]; + }; + v1SignRawPayloadsResult: { + signatures?: definitions["v1SignRawPayloadResult"][]; + }; + v1SignTransactionIntent: { + /** @description Unique identifier for a given Private Key. */ + privateKeyId: string; + /** @description Raw unsigned transaction to be signed by a particular Private Key. */ + unsignedTransaction: string; + type: definitions["v1TransactionType"]; + }; + v1SignTransactionIntentV2: { + /** @description A Wallet account address, Private Key address, or Private Key identifier. */ + signWith: string; + /** @description Raw unsigned transaction to be signed */ + unsignedTransaction: string; + type: definitions["v1TransactionType"]; + }; + v1SignTransactionRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_SIGN_TRANSACTION_V2"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1SignTransactionIntentV2"]; + }; + v1SignTransactionResult: { + signedTransaction: string; + }; + v1SimpleClientExtensionResults: { + appid?: boolean; + appidExclude?: boolean; + credProps?: definitions["v1CredPropsAuthenticationExtensionsClientOutputs"]; + }; + v1SmartContractInterface: { + /** @description The Organization the Smart Contract Interface belongs to. */ + organizationId: string; + /** @description Unique identifier for a given Smart Contract Interface (ABI or IDL). */ + smartContractInterfaceId: string; + /** @description The address corresponding to the Smart Contract or Program. */ + smartContractAddress: string; + /** @description The JSON corresponding to the Smart Contract Interface (ABI or IDL). */ + smartContractInterface: string; + /** @description The type corresponding to the Smart Contract Interface (either ETHEREUM or SOLANA). */ + type: string; + /** @description The label corresponding to the Smart Contract Interface (either ETHEREUM or SOLANA). */ + label: string; + /** @description The notes corresponding to the Smart Contract Interface (either ETHEREUM or SOLANA). */ + notes: string; + createdAt: definitions["externaldatav1Timestamp"]; + updatedAt: definitions["externaldatav1Timestamp"]; + }; + v1SmartContractInterfaceReference: { + smartContractInterfaceId?: string; + smartContractAddress?: string; + digest?: string; + }; + /** @enum {string} */ + v1SmartContractInterfaceType: + | "SMART_CONTRACT_INTERFACE_TYPE_ETHEREUM" + | "SMART_CONTRACT_INTERFACE_TYPE_SOLANA"; + v1SmsCustomizationParams: { + /** @description Template containing references to .OtpCode i.e Your OTP is {{.OtpCode}} */ + template?: string; + }; + v1StampLoginIntent: { + /** @description Client-side public key generated by the user, which will be conditionally added to org data based on the passkey stamp associated with this request */ + publicKey: string; + /** @description Expiration window (in seconds) indicating how long the Session is valid for. If not provided, a default of 15 minutes will be used. */ + expirationSeconds?: string; + /** @description Invalidate all other previously generated Login API keys */ + invalidateExisting?: boolean; + }; + v1StampLoginRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_STAMP_LOGIN"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1StampLoginIntent"]; + }; + v1StampLoginResult: { + /** @description Signed JWT containing an expiry, public key, session type, user id, and organization id */ + session: string; + }; + /** @enum {string} */ + v1TagType: "TAG_TYPE_USER" | "TAG_TYPE_PRIVATE_KEY"; + v1TestRateLimitsRequest: { + /** @description Unique identifier for a given Organization. If the request is being made by a WebAuthN user and their Sub-Organization ID is unknown, this can be the Parent Organization ID; using the Sub-Organization ID when possible is preferred due to performance reasons. */ + organizationId: string; + /** @description Whether or not to set a limit on this request. */ + isSetLimit: boolean; + /** + * Format: int64 + * @description Rate limit to set for org, if is_set_limit is set to true + */ + limit: number; + }; + v1TestRateLimitsResponse: { [key: string]: unknown }; + /** @enum {string} */ + v1TransactionType: + | "TRANSACTION_TYPE_ETHEREUM" + | "TRANSACTION_TYPE_SOLANA" + | "TRANSACTION_TYPE_TRON"; + v1UpdateAllowedOriginsIntent: { + /** @description Additional origins requests are allowed from besides Turnkey origins */ + allowedOrigins: string[]; + }; + v1UpdateAllowedOriginsResult: { [key: string]: unknown }; + v1UpdatePolicyIntent: { + /** @description Unique identifier for a given Policy. */ + policyId: string; + /** @description Human-readable name for a Policy. */ + policyName?: string; + /** @description The instruction to DENY or ALLOW an activity (optional). */ + policyEffect?: definitions["v1Effect"]; + /** @description The condition expression that triggers the Effect (optional). */ + policyCondition?: string; + /** @description The consensus expression that triggers the Effect (optional). */ + policyConsensus?: string; + /** @description Accompanying notes for a Policy (optional). */ + policyNotes?: string; + }; + v1UpdatePolicyIntentV2: { + /** @description Unique identifier for a given Policy. */ + policyId: string; + /** @description Human-readable name for a Policy. */ + policyName?: string; + /** @description The instruction to DENY or ALLOW an activity (optional). */ + policyEffect?: definitions["v1Effect"]; + /** @description The condition expression that triggers the Effect (optional). */ + policyCondition?: string; + /** @description The consensus expression that triggers the Effect (optional). */ + policyConsensus?: string; + /** @description Accompanying notes for a Policy (optional). */ + policyNotes?: string; + }; + v1UpdatePolicyRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_UPDATE_POLICY_V2"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1UpdatePolicyIntentV2"]; + }; + v1UpdatePolicyResult: { + /** @description Unique identifier for a given Policy. */ + policyId: string; + }; + v1UpdatePolicyResultV2: { + /** @description Unique identifier for a given Policy. */ + policyId: string; + }; + v1UpdatePrivateKeyTagIntent: { + /** @description Unique identifier for a given Private Key Tag. */ + privateKeyTagId: string; + /** @description The new, human-readable name for the tag with the given ID. */ + newPrivateKeyTagName?: string; + /** @description A list of Private Keys IDs to add this tag to. */ + addPrivateKeyIds: string[]; + /** @description A list of Private Key IDs to remove this tag from. */ + removePrivateKeyIds: string[]; + }; + v1UpdatePrivateKeyTagRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_UPDATE_PRIVATE_KEY_TAG"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1UpdatePrivateKeyTagIntent"]; + }; + v1UpdatePrivateKeyTagResult: { + /** @description Unique identifier for a given Private Key Tag. */ + privateKeyTagId: string; + }; + v1UpdateProxyAuthConfigIntent: { + /** @description Updated list of allowed origins for CORS. */ + allowedOrigins?: string[]; + /** @description Updated list of allowed origins for CORS. */ + allowedAuthMethods?: string[]; + /** @description Custom 'from' address for auth-related emails. */ + sendFromEmailAddress?: string; + /** @description Custom reply-to address for auth-related emails. */ + replyToEmailAddress?: string; + /** @description Template ID for email-auth messages. */ + emailAuthTemplateId?: string; + /** @description Template ID for OTP SMS messages. */ + otpTemplateId?: string; + /** @description Overrides for auth-related email content. */ + emailCustomizationParams?: definitions["v1EmailCustomizationParams"]; + /** @description Overrides for auth-related SMS content. */ + smsCustomizationParams?: definitions["v1SmsCustomizationParams"]; + /** @description Overrides for EWK related settings. */ + ewkSettings?: definitions["v1EwkSettingsParams"]; + /** + * Format: int32 + * @description OTP code lifetime in seconds. + */ + otpExpirationSeconds?: number; + /** + * Format: int32 + * @description Verification-token lifetime in seconds. + */ + verificationTokenExpirationSeconds?: number; + /** + * Format: int32 + * @description OTP session lifetime in seconds. + */ + otpSessionExpirationSeconds?: number; + /** + * Format: int32 + * @description Passkey session lifetime in seconds. + */ + passkeySessionExpirationSeconds?: number; + /** + * Format: int32 + * @description Wallet session lifetime in seconds. + */ + walletSessionExpirationSeconds?: number; + /** + * Format: int32 + * @description OAuth session lifetime in seconds. + */ + oauthSessionExpirationSeconds?: number; + /** @description Enable alphanumeric OTP codes. */ + otpAlphanumeric?: boolean; + /** + * Format: int32 + * @description Desired OTP code length (6–9). + */ + otpLength?: number; + /** @description Enable social linking (userEmail <-> gmail) */ + socialLinking?: boolean; + }; + v1UpdateProxyAuthConfigRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_UPDATE_PROXY_AUTH_CONFIG"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1UpdateProxyAuthConfigIntent"]; + }; + v1UpdateProxyAuthConfigResult: { [key: string]: unknown }; + v1UpdateRootQuorumIntent: { + /** + * Format: int32 + * @description The threshold of unique approvals to reach quorum. + */ + threshold: number; + /** @description The unique identifiers of users who comprise the quorum set. */ + userIds: string[]; + }; + v1UpdateRootQuorumRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_UPDATE_ROOT_QUORUM"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1UpdateRootQuorumIntent"]; + }; + v1UpdateRootQuorumResult: { [key: string]: unknown }; + v1UpdateUserEmailIntent: { + /** @description Unique identifier for a given User. */ + userId: string; + /** @description The user's email address. Setting this to an empty string will remove the user's email. */ + userEmail: string; + /** @description Signed JWT containing a unique id, expiry, verification type, contact */ + verificationToken?: string; + }; + v1UpdateUserEmailRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_UPDATE_USER_EMAIL"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1UpdateUserEmailIntent"]; + }; + v1UpdateUserEmailResult: { + /** @description Unique identifier of the User whose email was updated. */ + userId: string; + }; + v1UpdateUserIntent: { + /** @description Unique identifier for a given User. */ + userId: string; + /** @description Human-readable name for a User. */ + userName?: string; + /** @description The user's email address. */ + userEmail?: string; + /** @description An updated list of User Tags to apply to this User. This field, if not needed, should be an empty array in your request body. */ + userTagIds?: string[]; + /** @description The user's phone number in E.164 format e.g. +13214567890 */ + userPhoneNumber?: string; + }; + v1UpdateUserNameIntent: { + /** @description Unique identifier for a given User. */ + userId: string; + /** @description Human-readable name for a User. */ + userName: string; + }; + v1UpdateUserNameRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_UPDATE_USER_NAME"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1UpdateUserNameIntent"]; + }; + v1UpdateUserNameResult: { + /** @description Unique identifier of the User whose name was updated. */ + userId: string; + }; + v1UpdateUserPhoneNumberIntent: { + /** @description Unique identifier for a given User. */ + userId: string; + /** @description The user's phone number in E.164 format e.g. +13214567890. Setting this to an empty string will remove the user's phone number. */ + userPhoneNumber: string; + /** @description Signed JWT containing a unique id, expiry, verification type, contact */ + verificationToken?: string; + }; + v1UpdateUserPhoneNumberRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_UPDATE_USER_PHONE_NUMBER"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1UpdateUserPhoneNumberIntent"]; + }; + v1UpdateUserPhoneNumberResult: { + /** @description Unique identifier of the User whose phone number was updated. */ + userId: string; + }; + v1UpdateUserRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_UPDATE_USER"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1UpdateUserIntent"]; + }; + v1UpdateUserResult: { + /** @description A User ID. */ + userId: string; + }; + v1UpdateUserTagIntent: { + /** @description Unique identifier for a given User Tag. */ + userTagId: string; + /** @description The new, human-readable name for the tag with the given ID. */ + newUserTagName?: string; + /** @description A list of User IDs to add this tag to. */ + addUserIds: string[]; + /** @description A list of User IDs to remove this tag from. */ + removeUserIds: string[]; + }; + v1UpdateUserTagRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_UPDATE_USER_TAG"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1UpdateUserTagIntent"]; + }; + v1UpdateUserTagResult: { + /** @description Unique identifier for a given User Tag. */ + userTagId: string; + }; + v1UpdateWalletIntent: { + /** @description Unique identifier for a given Wallet. */ + walletId: string; + /** @description Human-readable name for a Wallet. */ + walletName?: string; + }; + v1UpdateWalletRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_UPDATE_WALLET"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1UpdateWalletIntent"]; + }; + v1UpdateWalletResult: { + /** @description A Wallet ID. */ + walletId: string; + }; + v1User: { + /** @description Unique identifier for a given User. */ + userId: string; + /** @description Human-readable name for a User. */ + userName: string; + /** @description The user's email address. */ + userEmail?: string; + /** @description The user's phone number in E.164 format e.g. +13214567890 */ + userPhoneNumber?: string; + /** @description A list of Authenticator parameters. */ + authenticators: definitions["v1Authenticator"][]; + /** @description A list of API Key parameters. This field, if not needed, should be an empty array in your request body. */ + apiKeys: definitions["v1ApiKey"][]; + /** @description A list of User Tag IDs. */ + userTags: string[]; + /** @description A list of Oauth Providers. */ + oauthProviders: definitions["v1OauthProvider"][]; + createdAt: definitions["externaldatav1Timestamp"]; + updatedAt: definitions["externaldatav1Timestamp"]; + }; + v1UserParams: { + /** @description Human-readable name for a User. */ + userName: string; + /** @description The user's email address. */ + userEmail?: string; + /** @description The User's permissible access method(s). */ + accessType: definitions["v1AccessType"]; + /** @description A list of API Key parameters. This field, if not needed, should be an empty array in your request body. */ + apiKeys: definitions["apiApiKeyParams"][]; + /** @description A list of Authenticator parameters. This field, if not needed, should be an empty array in your request body. */ + authenticators: definitions["v1AuthenticatorParams"][]; + /** @description A list of User Tag IDs. This field, if not needed, should be an empty array in your request body. */ + userTags: string[]; + }; + v1UserParamsV2: { + /** @description Human-readable name for a User. */ + userName: string; + /** @description The user's email address. */ + userEmail?: string; + /** @description A list of API Key parameters. This field, if not needed, should be an empty array in your request body. */ + apiKeys: definitions["apiApiKeyParams"][]; + /** @description A list of Authenticator parameters. This field, if not needed, should be an empty array in your request body. */ + authenticators: definitions["v1AuthenticatorParamsV2"][]; + /** @description A list of User Tag IDs. This field, if not needed, should be an empty array in your request body. */ + userTags: string[]; + }; + v1UserParamsV3: { + /** @description Human-readable name for a User. */ + userName: string; + /** @description The user's email address. */ + userEmail?: string; + /** @description The user's phone number in E.164 format e.g. +13214567890 */ + userPhoneNumber?: string; + /** @description A list of API Key parameters. This field, if not needed, should be an empty array in your request body. */ + apiKeys: definitions["v1ApiKeyParamsV2"][]; + /** @description A list of Authenticator parameters. This field, if not needed, should be an empty array in your request body. */ + authenticators: definitions["v1AuthenticatorParamsV2"][]; + /** @description A list of Oauth providers. This field, if not needed, should be an empty array in your request body. */ + oauthProviders: definitions["v1OauthProviderParams"][]; + /** @description A list of User Tag IDs. This field, if not needed, should be an empty array in your request body. */ + userTags: string[]; + }; + v1VerifyOtpIntent: { + /** @description ID representing the result of an init OTP activity. */ + otpId: string; + /** @description OTP sent out to a user's contact (email or SMS) */ + otpCode: string; + /** @description Expiration window (in seconds) indicating how long the verification token is valid for. If not provided, a default of 1 hour will be used. Maximum value is 86400 seconds (24 hours) */ + expirationSeconds?: string; + }; + v1VerifyOtpRequest: { + /** @enum {string} */ + type: "ACTIVITY_TYPE_VERIFY_OTP"; + /** @description Timestamp (in milliseconds) of the request, used to verify liveness of user requests. */ + timestampMs: string; + /** @description Unique identifier for a given Organization. */ + organizationId: string; + parameters: definitions["v1VerifyOtpIntent"]; + }; + v1VerifyOtpResult: { + /** @description Signed JWT containing a unique id, expiry, verification type, contact. Verification status of a user is updated when the token is consumed (in OTP_LOGIN requests) */ + verificationToken: string; + }; + v1Vote: { + /** @description Unique identifier for a given Vote object. */ + id: string; + /** @description Unique identifier for a given User. */ + userId: string; + /** @description Web and/or API user within your Organization. */ + user: definitions["v1User"]; + /** @description Unique identifier for a given Activity object. */ + activityId: string; + /** @enum {string} */ + selection: "VOTE_SELECTION_APPROVED" | "VOTE_SELECTION_REJECTED"; + /** @description The raw message being signed within a Vote. */ + message: string; + /** @description The public component of a cryptographic key pair used to sign messages and transactions. */ + publicKey: string; + /** @description The signature applied to a particular vote. */ + signature: string; + /** @description Method used to produce a signature. */ + scheme: string; + createdAt: definitions["externaldatav1Timestamp"]; + }; + v1Wallet: { + /** @description Unique identifier for a given Wallet. */ + walletId: string; + /** @description Human-readable name for a Wallet. */ + walletName: string; + createdAt: definitions["externaldatav1Timestamp"]; + updatedAt: definitions["externaldatav1Timestamp"]; + /** @description True when a given Wallet is exported, false otherwise. */ + exported: boolean; + /** @description True when a given Wallet is imported, false otherwise. */ + imported: boolean; + }; + v1WalletAccount: { + /** @description Unique identifier for a given Wallet Account. */ + walletAccountId: string; + /** @description The Organization the Account belongs to. */ + organizationId: string; + /** @description The Wallet the Account was derived from. */ + walletId: string; + /** @description Cryptographic curve used to generate the Account. */ + curve: definitions["v1Curve"]; + /** @description Path format used to generate the Account. */ + pathFormat: definitions["v1PathFormat"]; + /** @description Path used to generate the Account. */ + path: string; + /** @description Address format used to generate the Account. */ + addressFormat: definitions["v1AddressFormat"]; + /** @description Address generated using the Wallet seed and Account parameters. */ + address: string; + createdAt: definitions["externaldatav1Timestamp"]; + updatedAt: definitions["externaldatav1Timestamp"]; + /** @description The public component of this wallet account's underlying cryptographic key pair. */ + publicKey?: string; + }; + v1WalletAccountParams: { + /** @description Cryptographic curve used to generate a wallet Account. */ + curve: definitions["v1Curve"]; + /** @description Path format used to generate a wallet Account. */ + pathFormat: definitions["v1PathFormat"]; + /** @description Path used to generate a wallet Account. */ + path: string; + /** @description Address format used to generate a wallet Acccount. */ + addressFormat: definitions["v1AddressFormat"]; + }; + v1WalletParams: { + /** @description Human-readable name for a Wallet. */ + walletName: string; + /** @description A list of wallet Accounts. This field, if not needed, should be an empty array in your request body. */ + accounts: definitions["v1WalletAccountParams"][]; + /** + * Format: int32 + * @description Length of mnemonic to generate the Wallet seed. Defaults to 12. Accepted values: 12, 15, 18, 21, 24. + */ + mnemonicLength?: number; + }; + v1WalletResult: { + walletId: string; + /** @description A list of account addresses. */ + addresses: string[]; + }; + v1WebAuthnStamp: { + /** @description A base64 url encoded Unique identifier for a given credential. */ + credentialId: string; + /** @description A base64 encoded payload containing metadata about the signing context and the challenge. */ + clientDataJson: string; + /** @description A base64 encoded payload containing metadata about the authenticator. */ + authenticatorData: string; + /** @description The base64 url encoded signature bytes contained within the WebAuthn assertion response. */ + signature: string; + }; +}; + +export type operations = { + /** Get details about an Activity */ + PublicApiService_GetActivity: { + parameters: { + body: { + body: definitions["v1GetActivityRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Get details about an API key */ + PublicApiService_GetApiKey: { + parameters: { + body: { + body: definitions["v1GetApiKeyRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1GetApiKeyResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Get details about API keys for a user */ + PublicApiService_GetApiKeys: { + parameters: { + body: { + body: definitions["v1GetApiKeysRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1GetApiKeysResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Get the attestation document corresponding to an enclave. */ + PublicApiService_GetAttestationDocument: { + parameters: { + body: { + body: definitions["v1GetAttestationDocumentRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1GetAttestationDocumentResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Get details about an authenticator */ + PublicApiService_GetAuthenticator: { + parameters: { + body: { + body: definitions["v1GetAuthenticatorRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1GetAuthenticatorResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Get details about authenticators for a user */ + PublicApiService_GetAuthenticators: { + parameters: { + body: { + body: definitions["v1GetAuthenticatorsRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1GetAuthenticatorsResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Get details about Oauth providers for a user */ + PublicApiService_GetOauthProviders: { + parameters: { + body: { + body: definitions["v1GetOauthProvidersRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1GetOauthProvidersResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Get details about an Organization */ + PublicApiService_GetOrganization: { + parameters: { + body: { + body: definitions["v1GetOrganizationRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1GetOrganizationResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Get quorum settings and features for an organization */ + PublicApiService_GetOrganizationConfigs: { + parameters: { + body: { + body: definitions["v1GetOrganizationConfigsRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1GetOrganizationConfigsResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Get details about a Policy */ + PublicApiService_GetPolicy: { + parameters: { + body: { + body: definitions["v1GetPolicyRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1GetPolicyResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Get details about a Private Key */ + PublicApiService_GetPrivateKey: { + parameters: { + body: { + body: definitions["v1GetPrivateKeyRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1GetPrivateKeyResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Get the proxy-auth configuration (allowed origins, etc.) for an Organization */ + PublicApiService_GetProxyAuthConfig: { + parameters: { + body: { + body: definitions["v1GetProxyAuthConfigRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1GetProxyAuthConfigResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Get details about a Smart Contract Interface */ + PublicApiService_GetSmartContractInterface: { + parameters: { + body: { + body: definitions["v1GetSmartContractInterfaceRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1GetSmartContractInterfaceResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Get details about a User */ + PublicApiService_GetUser: { + parameters: { + body: { + body: definitions["v1GetUserRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1GetUserResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Get details about a Wallet */ + PublicApiService_GetWallet: { + parameters: { + body: { + body: definitions["v1GetWalletRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1GetWalletResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Get a single wallet account */ + PublicApiService_GetWalletAccount: { + parameters: { + body: { + body: definitions["v1GetWalletAccountRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1GetWalletAccountResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** List all Activities within an Organization */ + PublicApiService_GetActivities: { + parameters: { + body: { + body: definitions["v1GetActivitiesRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1GetActivitiesResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** List all Policies within an Organization */ + PublicApiService_GetPolicies: { + parameters: { + body: { + body: definitions["v1GetPoliciesRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1GetPoliciesResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** List all Private Key Tags within an Organization */ + PublicApiService_ListPrivateKeyTags: { + parameters: { + body: { + body: definitions["v1ListPrivateKeyTagsRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ListPrivateKeyTagsResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** List all Private Keys within an Organization */ + PublicApiService_GetPrivateKeys: { + parameters: { + body: { + body: definitions["v1GetPrivateKeysRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1GetPrivateKeysResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** List all Smart Contract Interfaces within an Organization */ + PublicApiService_GetSmartContractInterfaces: { + parameters: { + body: { + body: definitions["v1GetSmartContractInterfacesRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1GetSmartContractInterfacesResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Get all suborg IDs associated given a parent org ID and an optional filter. */ + PublicApiService_GetSubOrgIds: { + parameters: { + body: { + body: definitions["v1GetSubOrgIdsRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1GetSubOrgIdsResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** List all User Tags within an Organization */ + PublicApiService_ListUserTags: { + parameters: { + body: { + body: definitions["v1ListUserTagsRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ListUserTagsResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** List all Users within an Organization */ + PublicApiService_GetUsers: { + parameters: { + body: { + body: definitions["v1GetUsersRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1GetUsersResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Get all email or phone verified suborg IDs associated given a parent org ID. */ + PublicApiService_GetVerifiedSubOrgIds: { + parameters: { + body: { + body: definitions["v1GetVerifiedSubOrgIdsRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1GetVerifiedSubOrgIdsResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** List all Accounts within a Wallet */ + PublicApiService_GetWalletAccounts: { + parameters: { + body: { + body: definitions["v1GetWalletAccountsRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1GetWalletAccountsResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** List all Wallets within an Organization */ + PublicApiService_GetWallets: { + parameters: { + body: { + body: definitions["v1GetWalletsRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1GetWalletsResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Get basic information about your current API or WebAuthN user and their organization. Affords Sub-Organization look ups via Parent Organization for WebAuthN or API key users. */ + PublicApiService_GetWhoami: { + parameters: { + body: { + body: definitions["v1GetWhoamiRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1GetWhoamiResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Approve an Activity */ + PublicApiService_ApproveActivity: { + parameters: { + body: { + body: definitions["v1ApproveActivityRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Add api keys to an existing User */ + PublicApiService_CreateApiKeys: { + parameters: { + body: { + body: definitions["v1CreateApiKeysRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Create API-only Users in an existing Organization */ + PublicApiService_CreateApiOnlyUsers: { + parameters: { + body: { + body: definitions["v1CreateApiOnlyUsersRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Create Authenticators to authenticate requests to Turnkey */ + PublicApiService_CreateAuthenticators: { + parameters: { + body: { + body: definitions["v1CreateAuthenticatorsRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Create Invitations to join an existing Organization */ + PublicApiService_CreateInvitations: { + parameters: { + body: { + body: definitions["v1CreateInvitationsRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Creates Oauth providers for a specified user - BETA */ + PublicApiService_CreateOauthProviders: { + parameters: { + body: { + body: definitions["v1CreateOauthProvidersRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Create new Policies */ + PublicApiService_CreatePolicies: { + parameters: { + body: { + body: definitions["v1CreatePoliciesRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Create a new Policy */ + PublicApiService_CreatePolicy: { + parameters: { + body: { + body: definitions["v1CreatePolicyRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Create a private key tag and add it to private keys. */ + PublicApiService_CreatePrivateKeyTag: { + parameters: { + body: { + body: definitions["v1CreatePrivateKeyTagRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Create new Private Keys */ + PublicApiService_CreatePrivateKeys: { + parameters: { + body: { + body: definitions["v1CreatePrivateKeysRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Create a read only session for a user (valid for 1 hour) */ + PublicApiService_CreateReadOnlySession: { + parameters: { + body: { + body: definitions["v1CreateReadOnlySessionRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Create a read write session for a user */ + PublicApiService_CreateReadWriteSession: { + parameters: { + body: { + body: definitions["v1CreateReadWriteSessionRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Create an ABI/IDL in JSON */ + PublicApiService_CreateSmartContractInterface: { + parameters: { + body: { + body: definitions["v1CreateSmartContractInterfaceRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Create a new Sub-Organization */ + PublicApiService_CreateSubOrganization: { + parameters: { + body: { + body: definitions["v1CreateSubOrganizationRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Create a user tag and add it to users. */ + PublicApiService_CreateUserTag: { + parameters: { + body: { + body: definitions["v1CreateUserTagRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Create Users in an existing Organization */ + PublicApiService_CreateUsers: { + parameters: { + body: { + body: definitions["v1CreateUsersRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Create a Wallet and derive addresses */ + PublicApiService_CreateWallet: { + parameters: { + body: { + body: definitions["v1CreateWalletRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Derive additional addresses using an existing wallet */ + PublicApiService_CreateWalletAccounts: { + parameters: { + body: { + body: definitions["v1CreateWalletAccountsRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Remove api keys from a User */ + PublicApiService_DeleteApiKeys: { + parameters: { + body: { + body: definitions["v1DeleteApiKeysRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Remove authenticators from a User */ + PublicApiService_DeleteAuthenticators: { + parameters: { + body: { + body: definitions["v1DeleteAuthenticatorsRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Delete an existing Invitation */ + PublicApiService_DeleteInvitation: { + parameters: { + body: { + body: definitions["v1DeleteInvitationRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Removes Oauth providers for a specified user - BETA */ + PublicApiService_DeleteOauthProviders: { + parameters: { + body: { + body: definitions["v1DeleteOauthProvidersRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Delete an existing Policy */ + PublicApiService_DeletePolicy: { + parameters: { + body: { + body: definitions["v1DeletePolicyRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Delete Private Key Tags within an Organization */ + PublicApiService_DeletePrivateKeyTags: { + parameters: { + body: { + body: definitions["v1DeletePrivateKeyTagsRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Deletes private keys for an organization */ + PublicApiService_DeletePrivateKeys: { + parameters: { + body: { + body: definitions["v1DeletePrivateKeysRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Delete a Smart Contract Interface */ + PublicApiService_DeleteSmartContractInterface: { + parameters: { + body: { + body: definitions["v1DeleteSmartContractInterfaceRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Deletes a sub organization */ + PublicApiService_DeleteSubOrganization: { + parameters: { + body: { + body: definitions["v1DeleteSubOrganizationRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Delete User Tags within an Organization */ + PublicApiService_DeleteUserTags: { + parameters: { + body: { + body: definitions["v1DeleteUserTagsRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Delete Users within an Organization */ + PublicApiService_DeleteUsers: { + parameters: { + body: { + body: definitions["v1DeleteUsersRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Deletes wallets for an organization */ + PublicApiService_DeleteWallets: { + parameters: { + body: { + body: definitions["v1DeleteWalletsRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Disable User Initiated Auth */ + PublicApiService_DisableUserInitiatedAuth: { + parameters: { + body: { + body: definitions["v1DisableUserInitiatedAuthRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Authenticate a user via Email */ + PublicApiService_EmailAuth: { + parameters: { + body: { + body: definitions["v1EmailAuthRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Enable User Initiated Auth */ + PublicApiService_EnableUserInitiatedAuth: { + parameters: { + body: { + body: definitions["v1EnableUserInitiatedAuthRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Exports a Private Key */ + PublicApiService_ExportPrivateKey: { + parameters: { + body: { + body: definitions["v1ExportPrivateKeyRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Exports a Wallet */ + PublicApiService_ExportWallet: { + parameters: { + body: { + body: definitions["v1ExportWalletRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Exports a Wallet Account */ + PublicApiService_ExportWalletAccount: { + parameters: { + body: { + body: definitions["v1ExportWalletAccountRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Imports a private key */ + PublicApiService_ImportPrivateKey: { + parameters: { + body: { + body: definitions["v1ImportPrivateKeyRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Imports a wallet */ + PublicApiService_ImportWallet: { + parameters: { + body: { + body: definitions["v1ImportWalletRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Initiate a fiat on ramp flow */ + PublicApiService_InitFiatOnRamp: { + parameters: { + body: { + body: definitions["v1InitFiatOnRampRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Initializes a new private key import */ + PublicApiService_InitImportPrivateKey: { + parameters: { + body: { + body: definitions["v1InitImportPrivateKeyRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Initializes a new wallet import */ + PublicApiService_InitImportWallet: { + parameters: { + body: { + body: definitions["v1InitImportWalletRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Initiate a Generic OTP activity */ + PublicApiService_InitOtp: { + parameters: { + body: { + body: definitions["v1InitOtpRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Initiate an OTP auth activity */ + PublicApiService_InitOtpAuth: { + parameters: { + body: { + body: definitions["v1InitOtpAuthRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Initializes a new email recovery */ + PublicApiService_InitUserEmailRecovery: { + parameters: { + body: { + body: definitions["v1InitUserEmailRecoveryRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Authenticate a user with an Oidc token (Oauth) - BETA */ + PublicApiService_Oauth: { + parameters: { + body: { + body: definitions["v1OauthRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Create an Oauth session for a user */ + PublicApiService_OauthLogin: { + parameters: { + body: { + body: definitions["v1OauthLoginRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Authenticate a user with an OTP code sent via email or SMS */ + PublicApiService_OtpAuth: { + parameters: { + body: { + body: definitions["v1OtpAuthRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Create an OTP session for a user */ + PublicApiService_OtpLogin: { + parameters: { + body: { + body: definitions["v1OtpLoginRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Completes the process of recovering a user by adding an authenticator */ + PublicApiService_RecoverUser: { + parameters: { + body: { + body: definitions["v1RecoverUserRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Reject an Activity */ + PublicApiService_RejectActivity: { + parameters: { + body: { + body: definitions["v1RejectActivityRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Removes an organization feature. This activity must be approved by the current root quorum. */ + PublicApiService_RemoveOrganizationFeature: { + parameters: { + body: { + body: definitions["v1RemoveOrganizationFeatureRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Sets an organization feature. This activity must be approved by the current root quorum. */ + PublicApiService_SetOrganizationFeature: { + parameters: { + body: { + body: definitions["v1SetOrganizationFeatureRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Sign a raw payload */ + PublicApiService_SignRawPayload: { + parameters: { + body: { + body: definitions["v1SignRawPayloadRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Sign multiple raw payloads with the same signing parameters */ + PublicApiService_SignRawPayloads: { + parameters: { + body: { + body: definitions["v1SignRawPayloadsRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Sign a transaction */ + PublicApiService_SignTransaction: { + parameters: { + body: { + body: definitions["v1SignTransactionRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Create a session for a user through stamping client side (api key, wallet client, or passkey client) */ + PublicApiService_StampLogin: { + parameters: { + body: { + body: definitions["v1StampLoginRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Update an existing Policy */ + PublicApiService_UpdatePolicy: { + parameters: { + body: { + body: definitions["v1UpdatePolicyRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Update human-readable name or associated private keys. Note that this activity is atomic: all of the updates will succeed at once, or all of them will fail. */ + PublicApiService_UpdatePrivateKeyTag: { + parameters: { + body: { + body: definitions["v1UpdatePrivateKeyTagRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Update the proxy-auth configuration (allowed origins, etc.) for an Organization */ + PublicApiService_UpdateProxyAuthConfig: { + parameters: { + body: { + body: definitions["v1UpdateProxyAuthConfigRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Set the threshold and members of the root quorum. This activity must be approved by the current root quorum. */ + PublicApiService_UpdateRootQuorum: { + parameters: { + body: { + body: definitions["v1UpdateRootQuorumRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Update a User in an existing Organization */ + PublicApiService_UpdateUser: { + parameters: { + body: { + body: definitions["v1UpdateUserRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Update a User's email in an existing Organization */ + PublicApiService_UpdateUserEmail: { + parameters: { + body: { + body: definitions["v1UpdateUserEmailRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Update a User's name in an existing Organization */ + PublicApiService_UpdateUserName: { + parameters: { + body: { + body: definitions["v1UpdateUserNameRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Update a User's phone number in an existing Organization */ + PublicApiService_UpdateUserPhoneNumber: { + parameters: { + body: { + body: definitions["v1UpdateUserPhoneNumberRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Update human-readable name or associated users. Note that this activity is atomic: all of the updates will succeed at once, or all of them will fail. */ + PublicApiService_UpdateUserTag: { + parameters: { + body: { + body: definitions["v1UpdateUserTagRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Update a wallet for an organization */ + PublicApiService_UpdateWallet: { + parameters: { + body: { + body: definitions["v1UpdateWalletRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Verify a Generic OTP */ + PublicApiService_VerifyOtp: { + parameters: { + body: { + body: definitions["v1VerifyOtpRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1ActivityResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + PublicApiService_NOOPCodegenAnchor: { + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1NOOPCodegenAnchorResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; + /** Set a rate local rate limit just on the current endpoint, for purposes of testing with Vivosuite */ + PublicApiService_TestRateLimits: { + parameters: { + body: { + body: definitions["v1TestRateLimitsRequest"]; + }; + }; + responses: { + /** A successful response. */ + 200: { + schema: definitions["v1TestRateLimitsResponse"]; + }; + /** An unexpected error response. */ + default: { + schema: definitions["rpcStatus"]; + }; + }; + }; +}; + +export type external = {}; diff --git a/packages/core/src/__polyfills__/window.ts b/packages/core/src/__polyfills__/window.ts new file mode 100644 index 000000000..50aacef27 --- /dev/null +++ b/packages/core/src/__polyfills__/window.ts @@ -0,0 +1,25 @@ +const loadWindow = () => { + if (typeof window !== "undefined") { + return window; + } else { + return { + localStorage: { + getItem: (_key: string): string | null => { + return null; + }, + setItem: (_key: string, _value: string) => {}, + removeItem: (_key: string) => {}, + clear: () => {}, + key: (_index: number): string | null => { + return null; + }, + length: 0, + }, + location: { + hostname: "", + }, + }; + } +}; + +export default loadWindow(); diff --git a/packages/core/src/__stampers__/api/base.ts b/packages/core/src/__stampers__/api/base.ts new file mode 100644 index 000000000..3e54a8b9f --- /dev/null +++ b/packages/core/src/__stampers__/api/base.ts @@ -0,0 +1,75 @@ +import { isReactNative, isWeb } from "@utils"; +import { IndexedDbStamper } from "./web/stamper"; +import type { TStamp, TStamper, StorageBase, ApiKeyStamperBase } from "@types"; + +export class CrossPlatformApiKeyStamper implements TStamper { + private stamper!: ApiKeyStamperBase; + private publicKeyOverride?: string | undefined; + constructor(private storageManager: StorageBase) { + // Use init method to set up the stamper based on the platform. It's async, so can't be done in the constructor. + } + + async init(): Promise { + if (isWeb()) { + this.stamper = new IndexedDbStamper(); + } else if (isReactNative()) { + try { + // Dynamic import to prevent bundling the native module in web environments. + const { ReactNativeKeychainStamper } = await import("./mobile/stamper"); + this.stamper = new ReactNativeKeychainStamper(); + } catch (error) { + throw new Error( + `Failed to load keychain stamper for react-native: ${error}`, + ); + } + } else { + throw new Error("Unsupported platform for API key stamper"); + } + } + + listKeyPairs(): Promise { + return this.stamper.listKeyPairs(); + } + + createKeyPair( + externalKeyPair?: CryptoKeyPair | { publicKey: string; privateKey: string }, + ): Promise { + return this.stamper.createKeyPair(externalKeyPair); + } + + deleteKeyPair(publicKeyHex: string): Promise { + return this.stamper.deleteKeyPair(publicKeyHex); + } + + clearKeyPairs?(): Promise { + return this.stamper.clearKeyPairs(); + } + + // This allows forcing a specific public key to find the key pair for stamping. The key pair must already exist in indexedDB / Keychain. + // This is useful if you need to stamp with a specific key pair without having an active session. + // See "signUpWithPasskey" function in core.ts for usage + setPublicKeyOverride(publicKeyHex: string | undefined): void { + this.publicKeyOverride = publicKeyHex; + } + + getPublicKeyOverride(): string | undefined { + return this.publicKeyOverride; + } + + clearPublicKeyOverride(): void { + this.publicKeyOverride = undefined; + } + + async stamp(payload: string): Promise { + let publicKeyHex = this.publicKeyOverride; + if (!publicKeyHex) { + const session = await this.storageManager.getActiveSession(); + if (!session) { + throw new Error("No active session or token available."); + } + publicKeyHex = session.publicKey!; + } + + return this.stamper.stamp(payload, publicKeyHex); + } +} diff --git a/packages/core/src/__stampers__/api/mobile/stamper.ts b/packages/core/src/__stampers__/api/mobile/stamper.ts new file mode 100644 index 000000000..34beb5081 --- /dev/null +++ b/packages/core/src/__stampers__/api/mobile/stamper.ts @@ -0,0 +1,78 @@ +import { ApiKeyStamper } from "@turnkey/api-key-stamper"; +import { generateP256KeyPair } from "@turnkey/crypto"; +import type { TStamp, ApiKeyStamperBase } from "@types"; + +let Keychain: typeof import("react-native-keychain"); + +try { + Keychain = require("react-native-keychain"); +} catch { + throw new Error( + "Please install react-native-keychain in your app to use ReactNativeKeychainStamper", + ); +} + +export class ReactNativeKeychainStamper implements ApiKeyStamperBase { + async listKeyPairs(): Promise { + return await Keychain.getAllGenericPasswordServices(); + } + + async clearKeyPairs(): Promise { + const keys = await this.listKeyPairs(); + for (const key of keys) { + await this.deleteKeyPair(key); + } + } + + async createKeyPair(externalKeyPair?: { + publicKey: string; + privateKey: string; + }): Promise { + let privateKey: string; + let publicKey: string; + + if (externalKeyPair) { + privateKey = externalKeyPair.privateKey; + publicKey = externalKeyPair.publicKey; + } else { + const pair = generateP256KeyPair(); + privateKey = pair.privateKey; + publicKey = pair.publicKey; + } + + // store in Keychain + await Keychain.setGenericPassword(publicKey, privateKey, { + service: publicKey, + }); + + return publicKey; + } + + async deleteKeyPair(publicKeyHex: string): Promise { + await Keychain.resetGenericPassword({ + service: publicKeyHex, + }); + } + + private async getPrivateKey(publicKeyHex: string): Promise { + const creds = await Keychain.getGenericPassword({ + service: publicKeyHex, + }); + if (!creds) return null; + + return creds.password; + } + + async stamp(payload: string, publicKeyHex: string): Promise { + const privateKey = await this.getPrivateKey(publicKeyHex); + if (!privateKey) { + throw new Error(`No private key found for public key: ${publicKeyHex}`); + } + const stamper = new ApiKeyStamper({ + apiPublicKey: publicKeyHex, + apiPrivateKey: privateKey, + }); + const { stampHeaderName, stampHeaderValue } = await stamper.stamp(payload); + return { stampHeaderName, stampHeaderValue }; + } +} diff --git a/packages/core/src/__stampers__/api/web/stamper.ts b/packages/core/src/__stampers__/api/web/stamper.ts new file mode 100644 index 000000000..dbfa73ac4 --- /dev/null +++ b/packages/core/src/__stampers__/api/web/stamper.ts @@ -0,0 +1,238 @@ +import { + uint8ArrayToHexString, + stringToBase64urlString, + pointEncode, +} from "@turnkey/encoding"; +import type { TStamp, ApiKeyStamperBase } from "@types"; + +const DB_NAME = "TurnkeyStamperDB"; +const DB_STORE = "KeyStore"; +const stampHeaderName = "X-Stamp"; + +/** + * `SubtleCrypto.sign(...)` outputs signature in IEEE P1363 format: + * - https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/sign#ecdsa + * + * Turnkey expects the signature encoding to be DER-encoded ASN.1: + * - https://github.com/tkhq/tkcli/blob/7f0159af5a73387ff050647180d1db4d3a3aa033/src/internal/apikey/apikey.go#L149 + * + * Code modified from https://github.com/google/tink/blob/6f74b99a2bfe6677e3670799116a57268fd067fa/javascript/subtle/elliptic_curves.ts#L114 + * + * Transform an ECDSA signature in IEEE 1363 encoding to DER encoding. + * + * @param ieee the ECDSA signature in IEEE encoding + * @return ECDSA signature in DER encoding + */ +function convertEcdsaIeee1363ToDer(ieee: Uint8Array): Uint8Array { + if (ieee.length % 2 != 0 || ieee.length == 0 || ieee.length > 132) { + throw new Error( + "Invalid IEEE P1363 signature encoding. Length: " + ieee.length, + ); + } + const r = toUnsignedBigNum(ieee.subarray(0, ieee.length / 2)); + const s = toUnsignedBigNum(ieee.subarray(ieee.length / 2, ieee.length)); + let offset = 0; + const length = 1 + 1 + r.length + 1 + 1 + s.length; + let der: Uint8Array; + if (length >= 128) { + der = new Uint8Array(length + 3); + der[offset++] = 48; + der[offset++] = 128 + 1; + der[offset++] = length; + } else { + der = new Uint8Array(length + 2); + der[offset++] = 48; + der[offset++] = length; + } + der[offset++] = 2; + der[offset++] = r.length; + der.set(r, offset); + offset += r.length; + der[offset++] = 2; + der[offset++] = s.length; + der.set(s, offset); + return der; +} + +/** + * Code modified from https://github.com/google/tink/blob/6f74b99a2bfe6677e3670799116a57268fd067fa/javascript/subtle/elliptic_curves.ts#L311 + * + * Transform a big integer in big endian to minimal unsigned form which has + * no extra zero at the beginning except when the highest bit is set. + */ +function toUnsignedBigNum(bytes: Uint8Array): Uint8Array { + let start = 0; + while (start < bytes.length && bytes[start] == 0) { + start++; + } + if (start == bytes.length) { + start = bytes.length - 1; + } + let extraZero = 0; + if ((bytes[start]! & 128) == 128) { + extraZero = 1; + } + const res = new Uint8Array(bytes.length - start + extraZero); + res.set(bytes.subarray(start), extraZero); + return res; +} + +export class IndexedDbStamper implements ApiKeyStamperBase { + constructor() { + if (typeof window === "undefined") { + throw new Error("IndexedDB is only available in the browser"); + } + } + + private async openDb(): Promise { + return new Promise((resolve, reject) => { + const request = indexedDB.open(DB_NAME, 1); + request.onupgradeneeded = (event) => { + const db = (event.target as IDBOpenDBRequest).result; + if (!db.objectStoreNames.contains(DB_STORE)) { + db.createObjectStore(DB_STORE); + } + }; + request.onsuccess = () => resolve(request.result); + request.onerror = () => reject(request.error); + }); + } + + private async storeKeyPair( + publicKeyHex: string, + privateKey: CryptoKey, + ): Promise { + const db = await this.openDb(); + return new Promise((resolve, reject) => { + const tx = db.transaction(DB_STORE, "readwrite"); + const store = tx.objectStore(DB_STORE); + store.put(privateKey, publicKeyHex); + tx.oncomplete = () => { + db.close(); + resolve(); + }; + tx.onerror = () => reject(tx.error); + tx.onabort = () => reject(tx.error); + }); + } + + private async getPrivateKey(publicKeyHex: string): Promise { + const db = await this.openDb(); + return new Promise((resolve, reject) => { + const tx = db.transaction(DB_STORE, "readonly"); + const store = tx.objectStore(DB_STORE); + const request = store.get(publicKeyHex); + request.onsuccess = () => { + db.close(); + resolve(request.result || null); + }; + request.onerror = () => { + db.close(); + reject(request.error); + }; + }); + } + + async listKeyPairs(): Promise { + const db = await this.openDb(); + return new Promise((resolve, reject) => { + const tx = db.transaction(DB_STORE, "readonly"); + const store = tx.objectStore(DB_STORE); + const request = store.getAllKeys(); + request.onsuccess = () => { + db.close(); + resolve(request.result as string[]); + }; + request.onerror = () => { + db.close(); + reject(request.error); + }; + }); + } + + async createKeyPair(externalKeyPair?: CryptoKeyPair): Promise { + let privateKey: CryptoKey; + let publicKey: CryptoKey; + if (externalKeyPair) { + const extractable = (externalKeyPair.privateKey as any).extractable; + if (extractable !== false) { + throw new Error("Provided privateKey must be non-extractable."); + } + privateKey = externalKeyPair.privateKey; + publicKey = externalKeyPair.publicKey; + } else { + const keyPair = await crypto.subtle.generateKey( + { name: "ECDSA", namedCurve: "P-256" }, + false, // Non-extractable private key + ["sign", "verify"], + ); + privateKey = keyPair.privateKey; + publicKey = keyPair.publicKey; + } + const rawPubKey = new Uint8Array( + await crypto.subtle.exportKey("raw", publicKey), + ); + const compressedPubKey = pointEncode(rawPubKey); + const compressedHex = uint8ArrayToHexString(compressedPubKey); + await this.storeKeyPair(compressedHex, privateKey); + return compressedHex; + } + + async deleteKeyPair(publicKeyHex: string): Promise { + const db = await this.openDb(); + return new Promise((resolve, reject) => { + const tx = db.transaction(DB_STORE, "readwrite"); + const store = tx.objectStore(DB_STORE); + store.delete(publicKeyHex); + tx.oncomplete = () => { + db.close(); + resolve(); + }; + tx.onerror = () => reject(tx.error); + }); + } + + async clearKeyPairs(): Promise { + const db = await this.openDb(); + return new Promise((resolve, reject) => { + const tx = db.transaction(DB_STORE, "readwrite"); + const store = tx.objectStore(DB_STORE); + store.clear(); + tx.oncomplete = () => { + db.close(); + resolve(); + }; + tx.onerror = () => reject(tx.error); + }); + } + + private async sign(payload: string, publicKeyHex: string): Promise { + const privateKey = await this.getPrivateKey(publicKeyHex); + if (!privateKey) { + throw new Error("Key not found for publicKey: " + publicKeyHex); + } + const encodedPayload = new TextEncoder().encode(payload); + const signatureIeee1363 = await crypto.subtle.sign( + { name: "ECDSA", hash: { name: "SHA-256" } }, + privateKey, + encodedPayload, + ); + const signatureDer = convertEcdsaIeee1363ToDer( + new Uint8Array(signatureIeee1363), + ); + return uint8ArrayToHexString(signatureDer); + } + + async stamp(payload: string, publicKeyHex: string): Promise { + const signature = await this.sign(payload, publicKeyHex); + const stamp = { + publicKey: publicKeyHex, + scheme: "SIGNATURE_SCHEME_TK_API_P256", + signature, + }; + return { + stampHeaderName, + stampHeaderValue: stringToBase64urlString(JSON.stringify(stamp)), + }; + } +} diff --git a/packages/core/src/__stampers__/passkey/base.ts b/packages/core/src/__stampers__/passkey/base.ts new file mode 100644 index 000000000..201a0dd29 --- /dev/null +++ b/packages/core/src/__stampers__/passkey/base.ts @@ -0,0 +1,165 @@ +import { generateRandomBuffer, isReactNative, isWeb } from "@utils"; +import type { Passkey, TStamp, TStamper, TPasskeyStamperConfig } from "@types"; +import { WebauthnStamper } from "@turnkey/webauthn-stamper"; +import { + base64StringToBase64UrlEncodedString, + uint8ArrayToHexString, +} from "@turnkey/encoding"; +import { getWebAuthnAttestation, TurnkeyApiTypes } from "@turnkey/http"; +import { v4 as uuidv4 } from "uuid"; + +let PasskeyStamperModule: typeof import("@turnkey/react-native-passkey-stamper"); + +export type TurnkeyAuthenticatorParams = + TurnkeyApiTypes["v1AuthenticatorParamsV2"]; + +export class CrossPlatformPasskeyStamper implements TStamper { + private stamper!: TStamper; + private config: TPasskeyStamperConfig; + + constructor(config: TPasskeyStamperConfig) { + // Use init method to set up the stamper based on the platform. It's async, so can't be done in the constructor. + this.config = config; + } + + async init(): Promise { + if (isWeb()) { + const { default: WindowWrapper } = await import("@polyfills/window"); + + this.stamper = new WebauthnStamper({ + ...this.config, + rpId: this.config.rpId ?? WindowWrapper.location.hostname, + }); + } else if (isReactNative()) { + try { + // Dynamic import to prevent bundling the native module in web environments. + let PasskeyStamper; + try { + PasskeyStamperModule = require("@turnkey/react-native-passkey-stamper"); + PasskeyStamper = PasskeyStamperModule.PasskeyStamper; + } catch { + throw new Error( + "Please install react-native-passkeys and @turnkey/react-native-passkey-stamper in your app to use passkeys.", + ); + } + + this.stamper = new PasskeyStamper({ + ...this.config, + rpId: this.config.rpId!, + allowCredentials: this.config.allowCredentials?.map((cred) => ({ + id: uint8ArrayToHexString(cred.id as Uint8Array), + type: cred.type, + transports: cred.transports, + })) as any, + }); + } catch (error) { + throw new Error( + `Failed to load passkey stamper for react-native: ${error}`, + ); + } + } else { + throw new Error("Unsupported platform for passkey stamper"); + } + } + + async stamp(payload: string): Promise { + return await this.stamper.stamp(payload); + } + + /** + * Create a passkey for an end-user, taking care of various lower-level details. + * + * @returns {Promise} + */ + createWebPasskey = async ( + config: Record = {}, // TODO (Amir): This needs to be typed + ): Promise => { + const challenge = generateRandomBuffer(); + const encodedChallenge = base64StringToBase64UrlEncodedString( + btoa(String.fromCharCode(...new Uint8Array(challenge))), + ); + const authenticatorUserId = generateRandomBuffer(); + + // WebAuthn credential options options can be found here: + // https://www.w3.org/TR/webauthn-2/#sctn-sample-registration + // + // All pubkey algorithms can be found here: https://www.iana.org/assignments/cose/cose.xhtml#algorithms + // Turnkey only supports ES256 (-7) and RS256 (-257) + // + // The pubkey type only supports one value, "public-key" + // See https://www.w3.org/TR/webauthn-2/#enumdef-publickeycredentialtype for more details + // TODO: consider un-nesting these config params + const webauthnConfig: CredentialCreationOptions = { + publicKey: { + rp: { + id: config.publicKey?.rp?.id ?? this.config.rpId, + name: config.publicKey?.rp?.name ?? "", + }, + challenge: config.publicKey?.challenge ?? challenge, + pubKeyCredParams: config.publicKey?.pubKeyCredParams ?? [ + { + type: "public-key", + alg: -7, + }, + { + type: "public-key", + alg: -257, + }, + ], + user: { + id: config.publicKey?.user?.id ?? authenticatorUserId, + name: config.publicKey?.user?.name ?? "Default User", + displayName: config.publicKey?.user?.displayName ?? "Default User", + }, + authenticatorSelection: { + authenticatorAttachment: + config.publicKey?.authenticatorSelection?.authenticatorAttachment ?? + undefined, // default to empty + requireResidentKey: + config.publicKey?.authenticatorSelection?.requireResidentKey ?? + true, + residentKey: + config.publicKey?.authenticatorSelection?.residentKey ?? "required", + userVerification: + config.publicKey?.authenticatorSelection?.userVerification ?? + "preferred", + }, + }, + }; + + const attestation = await getWebAuthnAttestation(webauthnConfig); + + return { + encodedChallenge: config.publicKey?.challenge + ? base64StringToBase64UrlEncodedString(config.publicKey?.challenge) + : encodedChallenge, + attestation, + }; + }; + + createReactNativePasskey = async ( + config: Record = {}, // TODO (Amir): This needs to be typed + ): Promise => { + const { name, displayName, authenticatorName } = config; + const { createPasskey } = PasskeyStamperModule; // We do a 'selective' import when initializing the stamper. This is safe to do here. + + if (!createPasskey) { + throw new Error( + "Ensure you have @turnkey/react-native-passkey-stamper installed and linked correctly. Are you not on React Native?", + ); + } + + return await createPasskey({ + rp: { + id: this.config.rpId!, + name: this.config.rpName ?? "Turnkey", + }, + user: { + id: uuidv4(), + name, + displayName, + }, + authenticatorName: authenticatorName ?? name ?? "End-User Passkey", + }); + }; +} diff --git a/packages/core/src/__storage__/base.ts b/packages/core/src/__storage__/base.ts new file mode 100644 index 000000000..d8df71e3b --- /dev/null +++ b/packages/core/src/__storage__/base.ts @@ -0,0 +1,22 @@ +import { WebStorageManager } from "./web/storage"; +import { isReactNative, isWeb } from "@utils"; +import type { StorageBase } from "@types"; + +// TODO (Amir): Turn this into a class that extends StorageBase and make an init function. See stamper +export async function createStorageManager(): Promise { + if (isReactNative()) { + try { + // Dynamic import to prevent bundling the native module in web environments + const { MobileStorageManager } = await import("./mobile/storage"); + return new MobileStorageManager(); + } catch (error) { + throw new Error( + `Failed to load storage manager for react-native: ${error}`, + ); + } + } else if (isWeb()) { + return new WebStorageManager(); + } else { + throw new Error("Unsupported environment for storage manager."); + } +} diff --git a/packages/core/src/__storage__/mobile/storage.ts b/packages/core/src/__storage__/mobile/storage.ts new file mode 100644 index 000000000..0fce0b656 --- /dev/null +++ b/packages/core/src/__storage__/mobile/storage.ts @@ -0,0 +1,103 @@ +import { type StorageBase, SessionKey } from "@types"; +import { parseSession } from "@utils"; +import type { Session } from "@turnkey/sdk-types"; + +let AsyncStorage: (typeof import("@react-native-async-storage/async-storage"))["default"]; + +try { + const mod = require("@react-native-async-storage/async-storage"); + AsyncStorage = mod.default ?? mod; +} catch { + throw new Error( + "Please install @react-native-async-storage/async-storage in your app to use MobileStorageManager", + ); +} + +export class MobileStorageManager implements StorageBase { + private static ALL_SESSION_KEYS = "@turnkey/all-session-keys"; + private static ACTIVE_SESSION_KEY = "@turnkey/active-session-key"; + + async getStorageValue(sessionKey: string): Promise { + const item = await AsyncStorage.getItem(sessionKey); + return item ? JSON.parse(item) : undefined; + } + + async setStorageValue(sessionKey: string, storageValue: any): Promise { + await AsyncStorage.setItem(sessionKey, JSON.stringify(storageValue)); + } + + async setActiveSessionKey(sessionKey: string): Promise { + await AsyncStorage.setItem( + MobileStorageManager.ACTIVE_SESSION_KEY, + sessionKey, + ); + } + + async removeStorageValue(sessionKey: string): Promise { + await AsyncStorage.removeItem(sessionKey); + } + + async storeSession( + session: string, + sessionKey: string = SessionKey.DefaultSessionkey, + ): Promise { + const sessionWithMetadata = parseSession(session); + await this.setStorageValue(sessionKey, sessionWithMetadata); + + const raw = await this.getStorageValue( + MobileStorageManager.ALL_SESSION_KEYS, + ); + const keys: string[] = Array.isArray(raw) ? raw : []; + if (!keys.includes(sessionKey)) { + keys.push(sessionKey); + await this.setStorageValue(MobileStorageManager.ALL_SESSION_KEYS, keys); + } + + await this.setStorageValue( + MobileStorageManager.ACTIVE_SESSION_KEY, + sessionKey, + ); + } + + async getSession( + sessionKey: string = SessionKey.DefaultSessionkey, + ): Promise { + return this.getStorageValue(sessionKey); + } + + async getActiveSessionKey(): Promise { + return this.getStorageValue(MobileStorageManager.ACTIVE_SESSION_KEY); + } + + async getActiveSession(): Promise { + const key = await this.getActiveSessionKey(); + return key ? this.getSession(key) : undefined; + } + + async listSessionKeys(): Promise { + const raw = await this.getStorageValue( + MobileStorageManager.ALL_SESSION_KEYS, + ); + return Array.isArray(raw) ? raw : []; + } + + async clearSession(sessionKey: string): Promise { + await this.removeStorageValue(sessionKey); + + const keys = await this.listSessionKeys(); + const updated = keys.filter((k) => k !== sessionKey); + await this.setStorageValue(MobileStorageManager.ALL_SESSION_KEYS, updated); + + const active = await this.getActiveSessionKey(); + if (active === sessionKey) { + await this.removeStorageValue(MobileStorageManager.ACTIVE_SESSION_KEY); + } + } + + async clearAllSessions(): Promise { + const keys = await this.listSessionKeys(); + await Promise.all(keys.map((k) => AsyncStorage.removeItem(k))); + await this.removeStorageValue(MobileStorageManager.ALL_SESSION_KEYS); + await this.removeStorageValue(MobileStorageManager.ACTIVE_SESSION_KEY); + } +} diff --git a/packages/core/src/__storage__/web/storage.ts b/packages/core/src/__storage__/web/storage.ts new file mode 100644 index 000000000..8228e7746 --- /dev/null +++ b/packages/core/src/__storage__/web/storage.ts @@ -0,0 +1,112 @@ +import WindowWrapper from "@polyfills/window"; +import { type StorageBase, type Wallet, SessionKey } from "@types"; +import { parseSession } from "@utils"; +import { + TurnkeyError, + TurnkeyErrorCodes, + type Session, +} from "@turnkey/sdk-types"; + +const browserStorage = WindowWrapper.localStorage; + +export class WebStorageManager implements StorageBase { + private static ALL_SESSION_KEYS = "@turnkey/all-session-keys"; + private static ACTIVE_SESSION_KEY = "@turnkey/active-session-key"; + + getStorageValue = async (sessionKey: string): Promise => { + const item = browserStorage.getItem(sessionKey); + return item ? JSON.parse(item) : undefined; + }; + + setStorageValue = async ( + sessionKey: string, + storageValue: Session | string | string[], + ): Promise => { + if (storageValue === undefined) { + throw new TurnkeyError( + "Session value cannot be undefined", + TurnkeyErrorCodes.STORE_SESSION_ERROR, + ); + } + browserStorage.setItem(sessionKey, JSON.stringify(storageValue)); + }; + + setActiveSessionKey = async (sessionKey: string): Promise => { + await this.setStorageValue( + WebStorageManager.ACTIVE_SESSION_KEY, + sessionKey, + ); + }; + + removeStorageValue = async (sessionKey: string): Promise => { + browserStorage.removeItem(sessionKey); + }; + + storeSession = async ( + session: string, + sessionKey: string = SessionKey.DefaultSessionkey, + ): Promise => { + const sessionWithMetadata = parseSession(session); + + await this.setStorageValue(sessionKey, sessionWithMetadata); + + // Ensure the session key is stored in the session keys list + const keys: string[] = + (await this.getStorageValue(WebStorageManager.ALL_SESSION_KEYS)) ?? []; + if (!keys.includes(sessionKey)) { + keys.push(sessionKey); + await this.setStorageValue(WebStorageManager.ALL_SESSION_KEYS, keys); + } + + // Set the active session key + await this.setStorageValue( + WebStorageManager.ACTIVE_SESSION_KEY, + sessionKey, + ); + }; + + getSession = async ( + sessionKey: string = SessionKey.DefaultSessionkey, + ): Promise => { + return this.getStorageValue(sessionKey); + }; + + getActiveSessionKey = async (): Promise => { + return this.getStorageValue(WebStorageManager.ACTIVE_SESSION_KEY); + }; + + getActiveSession = async (): Promise => { + const key = await this.getActiveSessionKey(); + return key ? this.getSession(key) : undefined; + }; + + listSessionKeys = async (): Promise => { + return ( + (await this.getStorageValue(WebStorageManager.ALL_SESSION_KEYS)) ?? [] + ); + }; + + clearSession = async (sessionKey: string): Promise => { + await this.removeStorageValue(sessionKey); + const keys = await this.listSessionKeys(); + const updated = keys.filter((k) => k !== sessionKey); + await this.setStorageValue(WebStorageManager.ALL_SESSION_KEYS, updated); + const active = await this.getActiveSessionKey(); + if (active === sessionKey) { + await this.removeStorageValue(WebStorageManager.ACTIVE_SESSION_KEY); + } + }; + + clearAllSessions = async (): Promise => { + const keys = await this.listSessionKeys(); + await Promise.all(keys.map((k) => this.removeStorageValue(k))); + await this.removeStorageValue(WebStorageManager.ALL_SESSION_KEYS); + await this.removeStorageValue(WebStorageManager.ACTIVE_SESSION_KEY); + }; + + storeWallets = async (wallets: Wallet[]): Promise => { + for (const wallet of wallets) { + browserStorage.setItem(wallet.walletId, JSON.stringify(wallet)); + } + }; +} diff --git a/packages/core/src/__types__/base.ts b/packages/core/src/__types__/base.ts new file mode 100644 index 000000000..865bf9264 --- /dev/null +++ b/packages/core/src/__types__/base.ts @@ -0,0 +1,531 @@ +import type { TActivityId, TActivityStatus } from "@turnkey/http"; +import type { EIP1193Provider as EthereumProvider } from "viem"; +import type { Wallet as SolanaProvider } from "@wallet-standard/base"; +import type { + SessionType, + v1ApiKeyCurve, + v1Attestation, + v1OauthProviderParams, + v1User, + v1Wallet, + v1WalletAccount, + v1WalletAccountParams, + Session, +} from "@turnkey/sdk-types"; +import type { CrossPlatformWalletStamper } from "../__wallet__/stamper"; +import type { CrossPlatformWalletConnector } from "../__wallet__/connector"; + +export const DEFAULT_SESSION_EXPIRATION_IN_SECONDS = "900"; // 15 minutes + +export type GrpcStatus = { + message: string; + code: number; + details: unknown[] | null; +}; + +export enum MethodType { + Get, + List, + Command, +} + +export type TStamp = { + stampHeaderName: string; + stampHeaderValue: string; +}; + +export interface TStamper { + stamp: (input: string) => Promise; +} + +export type THttpConfig = { + baseUrl: string; +}; + +export class TurnkeyRequestError extends Error { + details: any[] | null; + code: number; + + constructor(input: GrpcStatus) { + let turnkeyErrorMessage = `Turnkey error ${input.code}: ${input.message}`; + + if (input.details != null) { + turnkeyErrorMessage += ` (Details: ${JSON.stringify(input.details)})`; + } + + super(turnkeyErrorMessage); + + this.name = "TurnkeyRequestError"; + this.details = input.details ?? null; + this.code = input.code; + } +} + +export interface ActivityResponse { + activity: { + id: TActivityId; + status: TActivityStatus; + result: Record; + }; +} + +export interface ActivityMetadata { + activity: { + id: TActivityId; + status: TActivityStatus; + }; +} + +export type TActivityPollerConfig = { + intervalMs: number; + numRetries: number; +}; + +export interface SubOrganization { + organizationId: string; + organizationName: string; +} + +export type EmbeddedAPIKey = { + authBundle: string; + publicKey: string; +}; + +export type Passkey = { + encodedChallenge: string; + attestation: { + credentialId: string; + clientDataJson: string; + attestationObject: string; + transports: ( + | "AUTHENTICATOR_TRANSPORT_BLE" + | "AUTHENTICATOR_TRANSPORT_INTERNAL" + | "AUTHENTICATOR_TRANSPORT_NFC" + | "AUTHENTICATOR_TRANSPORT_USB" + | "AUTHENTICATOR_TRANSPORT_HYBRID" + )[]; + }; +}; + +export interface TurnkeyHttpClientConfig { + apiBaseUrl: string; + organizationId: string; + authProxyUrl?: string | undefined; + authProxyConfigId?: string | undefined; + + activityPoller?: TActivityPollerConfig | undefined; + apiKeyStamper?: TStamper | undefined; + passkeyStamper?: TStamper | undefined; + walletStamper?: TStamper | undefined; + storageManager?: StorageBase | undefined; + readOnlySession?: string | undefined; // TODO (Amir): Shouldn't this be getten from the storage manager?. TODO (Amir) from the future: I thought we were getting rid of readOnlySessions all together. So..... delete this???? +} + +export interface TurnkeySDKClientConfig { + apiBaseUrl?: string | undefined; + authProxyUrl?: string | undefined; + authProxyConfigId?: string | undefined; // Auth proxy won't be used if not passed in + organizationId: string; + + passkeyConfig?: TPasskeyStamperConfig; + walletConfig?: TWalletManagerConfig; +} + +export type queryOverrideParams = { + organizationId?: string; +}; + +export type commandOverrideParams = { + organizationId?: string; + timestampMs?: string; +}; + +export interface IframeClientParams { + iframeContainer: HTMLElement | null | undefined; + iframeUrl: string; + iframeElementId?: string; + dangerouslyOverrideIframeKeyTtl?: number; +} + +export interface PasskeyClientParams { + rpId?: string; + timeout?: number; + userVerification?: UserVerificationRequirement; + allowCredentials?: PublicKeyCredentialDescriptor[]; +} +export interface RefreshSessionParams { + sessionType: SessionType; + expirationSeconds?: string | undefined; + publicKey?: string; +} + +export interface LoginWithBundleParams { + bundle: string; + expirationSeconds?: string; +} + +export interface LoginWithWalletParams { + sessionType: SessionType; + expirationSeconds?: string | undefined; + publicKey?: string; +} + +export type User = v1User; // TODO (Amir): I dunno if we need this. We may want to add more stuff to the user type in the future, so let's keep it for now since + +export type ExportBundle = string; + +export enum Curve { + SECP256K1 = "CURVE_SECP256K1", + ED25519 = "CURVE_ED25519", +} + +export enum WalletSource { + Embedded = "embedded", + Connected = "connected", +} + +export interface EmbeddedWalletAccount extends v1WalletAccount { + source: WalletSource.Embedded; +} + +export interface ConnectedWalletAccount extends v1WalletAccount { + source: WalletSource.Connected; + signMessage: (message: string) => Promise; + signTransaction?: (unsignedTransaction: string) => Promise; + signAndSendTransaction?: (unsignedTransaction: string) => Promise; +} + +export type WalletAccount = EmbeddedWalletAccount | ConnectedWalletAccount; + +export interface EmbeddedWallet extends v1Wallet { + source: WalletSource.Embedded; + accounts: WalletAccount[]; +} + +export interface ConnectedWallet extends v1Wallet { + source: WalletSource.Connected; + accounts: WalletAccount[]; +} + +export type Wallet = EmbeddedWallet | ConnectedWallet; + +export type WalletAccountParams = v1WalletAccountParams; + +export type Provider = { + providerName: string; + oidcToken: string; +}; + +export type CreateSuborgResponse = { + subOrganizationId: string; +}; + +export type CreateSubOrgParams = { + userName?: string | undefined; + subOrgName?: string | undefined; + userEmail?: string | undefined; + userTag?: string | undefined; + authenticators?: { + authenticatorName: string; + challenge: string; + attestation: v1Attestation; + }[]; + userPhoneNumber?: string | undefined; + verificationToken?: string | undefined; + apiKeys?: { + apiKeyName?: string | undefined; + publicKey: string; + expirationSeconds?: string | undefined; + curveType?: v1ApiKeyCurve | undefined; + }[]; + customWallet?: + | { + walletName: string; + walletAccounts: v1WalletAccountParams[]; + } + | undefined; + oauthProviders?: Provider[] | undefined; +}; + +export type SignUpBody = { + userName: string; + subOrgName: string; + userEmail?: string | undefined; + userTag?: string | undefined; + authenticators?: { + authenticatorName: string; + challenge: string; + attestation: v1Attestation; + }[]; + userPhoneNumber?: string | undefined; + verificationToken?: string | undefined; + apiKeys?: { + apiKeyName: string; + publicKey: string; + expirationSeconds: string; + curveType?: v1ApiKeyCurve | undefined; + }[]; + customWallet?: + | { + walletName: string; + walletAccounts: WalletAccountParams[]; + } + | undefined; + oauthProviders?: v1OauthProviderParams[] | undefined; +}; + +/** + * The Client used to authenticate the user. + */ +export enum AuthClient { + Passkey = "passkey", + Wallet = "wallet", + IndexedDb = "indexed-db", +} + +export enum StamperType { + ApiKey = "api-key", + Passkey = "passkey", + Wallet = "wallet", +} + +export enum OtpType { + Email = "OTP_TYPE_EMAIL", + Sms = "OTP_TYPE_SMS", +} + +export enum FilterType { + Email = "EMAIL", + Sms = "PHONE_NUMBER", + OidcToken = "OIDC_TOKEN", + PublicKey = "PUBLIC_KEY", +} + +export const OtpTypeToFilterTypeMap = { + [OtpType.Email]: FilterType.Email, + [OtpType.Sms]: FilterType.Sms, +}; + +export enum SessionKey { + DefaultSessionkey = "@turnkey/session/v3", +} + +export interface StorageBase { + getStorageValue(sessionKey: string): Promise; + setStorageValue(sessionKey: string, storageValue: any): Promise; + setActiveSessionKey(sessionKey: string): Promise; + removeStorageValue(sessionKey: string): Promise; + storeSession(session: string, sessionKey?: string): Promise; + getSession(sessionKey?: string): Promise; + getActiveSessionKey(): Promise; + getActiveSession(): Promise; + listSessionKeys(): Promise; + clearSession(sessionKey: string): Promise; + clearAllSessions(): Promise; +} + +export interface WalletManagerBase { + getProviders: (chain?: Chain) => Promise; + stamper?: CrossPlatformWalletStamper; + connector?: CrossPlatformWalletConnector; +} + +export type TPasskeyStamperConfig = { + // The RPID ("Relying Party ID") for your app. This is automatically determined in web environments based on the current hostname. + // See https://github.com/f-23/react-native-passkey?tab=readme-ov-file#configuration to set this up for react-native. + rpId?: string | undefined; + + // Optional timeout value in milliseconds. Defaults to 5 minutes. + timeout?: number; + + // Optional override for UV flag. Defaults to "preferred". + userVerification?: UserVerificationRequirement; + + // Optional list of credentials to pass. Defaults to empty. + allowCredentials?: PublicKeyCredentialDescriptor[]; + + // The below options do not exist in the WebauthnStamper: + + // Optional name for the Relying Party (RP). This is used in the passkey creation flow on mobile. + rpName?: string; + + // Option to force security passkeys on native platforms + withSecurityKey?: boolean; + + // Option to force platform passkeys on native platforms + withPlatformKey?: boolean; + + // Optional extensions. Defaults to empty. + extensions?: Record; +}; + +type EvmNamespace = `eip155:${string}`; // e.g. "eip155:1", "eip155:8453" +type SolNamespace = `solana:${string}`; // e.g. "solana:mainnet", cluster id, etc. + +export type TWalletManagerConfig = { + features?: { + auth?: boolean; + connecting?: boolean; + }; + chains: { + ethereum?: { + native?: boolean; + walletConnectNamespaces?: EvmNamespace[]; + }; + solana?: { + native?: boolean; + walletConnectNamespaces?: SolNamespace[]; + }; + }; + walletConnect?: { + projectId: string; + appMetadata: { + name: string; + description: string; + url: string; + icons: string[]; + }; + }; +}; + +export interface ApiKeyStamperBase { + listKeyPairs(): Promise; + createKeyPair( + externalKeyPair?: CryptoKeyPair | { publicKey: string; privateKey: string }, + ): Promise; + deleteKeyPair(publicKeyHex: string): Promise; + clearKeyPairs(): Promise; + stamp(payload: string, publicKeyHex: string): Promise; +} + +export interface WalletProviderInfo { + name: string; + uuid?: string; + icon?: string; + rdns?: string; +} + +export enum Chain { + Ethereum = "ethereum", + Solana = "solana", +} + +export type SwitchableChain = { + id: string; + name: string; + rpcUrls: string[]; + blockExplorerUrls?: string[]; + iconUrls?: string[]; + nativeCurrency: { + name: string; + symbol: string; + decimals: number; + }; +}; + +export type EvmChainInfo = { + namespace: Chain.Ethereum; + chainId: string; +}; + +export type SolanaChainInfo = { + namespace: Chain.Solana; +}; + +export type ChainInfo = EvmChainInfo | SolanaChainInfo; + +export interface WalletConnectProvider { + request(args: { method: string; params?: any[] }): Promise; +} + +export type WalletRpcProvider = + | EthereumProvider + | SolanaProvider + | WalletConnectProvider; + +export interface WalletProvider { + interfaceType: WalletInterfaceType; + chainInfo: ChainInfo; + info: WalletProviderInfo; + provider: WalletRpcProvider; + connectedAddresses: string[]; + uri?: string; +} + +export enum SignIntent { + SignMessage = "sign_message", + SignTransaction = "sign_transaction", + SignAndSendTransaction = "sign_and_send", +} + +export enum WalletInterfaceType { + Solana = "solana", + Ethereum = "ethereum", + WalletConnect = "wallet_connect", +} + +/** + * Base interface for wallet functionalities common across different blockchain chains. + * @interface BaseWalletInterface + * @property {function(string): Promise} signMessage - Signs a message and returns the hex signature as a string. + * @property {function(): Promise} getPublicKey - Retrieves the public key as a string. + */ +export interface BaseWalletInterface { + interfaceType: WalletInterfaceType; + sign: ( + payload: string, + provider: WalletProvider, + intent: SignIntent, + ) => Promise; + getPublicKey: (provider: WalletProvider) => Promise; + getProviders: () => Promise; + connectWalletAccount: (provider: WalletProvider) => Promise; + disconnectWalletAccount: (provider: WalletProvider) => Promise; + switchChain?: ( + provider: WalletProvider, + chainOrId: string | SwitchableChain, + ) => Promise; +} + +/** + * Solana wallets can directly access the public key without needing a signed message. + * @interface SolanaWalletInterface + * @extends BaseWalletInterface + * @property {function(): string} getPublicKey - Returns the public key, which is the ED25519 hex encoded public key from your Solana wallet public key. + * @property {'solana'} type - The type of the wallet. + */ +export interface SolanaWalletInterface extends BaseWalletInterface { + interfaceType: WalletInterfaceType.Solana; +} + +/** + * Ethereum wallets require a signed message to derive the public key. + * + * @remarks This is the SECP256K1 public key of the Ethereum wallet, not the address. + * This requires that the wallet signs a message in order to derive the public key. + * + * @interface EthereumWalletInterface + * @extends BaseWalletInterface + * @property {function(): Promise} getPublicKey - Returns the public key, which is the SECP256K1 hex encoded public key from your Ethereum wallet. + * @property {'ethereum'} type - The type of the wallet. + */ +export interface EthereumWalletInterface extends BaseWalletInterface { + interfaceType: WalletInterfaceType.Ethereum; +} + +export interface WalletConnectInterface extends BaseWalletInterface { + interfaceType: WalletInterfaceType.WalletConnect; + init: (opts: { + ethereumNamespaces: string[]; + solanaNamespaces: string[]; + }) => Promise; +} + +/** + * Union type for wallet interfaces, supporting both Solana and Ethereum wallets. + * @typedef {SolanaWalletInterface | EthereumWalletInterface} WalletInterface + */ +export type WalletInterface = + | SolanaWalletInterface + | EthereumWalletInterface + | WalletConnectInterface; diff --git a/packages/core/src/__wallet__/base.ts b/packages/core/src/__wallet__/base.ts new file mode 100644 index 000000000..0ecfd54e3 --- /dev/null +++ b/packages/core/src/__wallet__/base.ts @@ -0,0 +1,31 @@ +import { WebWalletManager } from "./web/manager"; +import { isReactNative, isWeb } from "@utils"; +import type { TWalletManagerConfig, WalletManagerBase } from "@types"; +import { MobileWalletManager } from "./mobile/manager"; + +/** + * Creates and initializes a wallet manager instance based on the runtime environment. + * + * - If the environment is React Native, it creates and initializes a `MobileWalletManager`. + * - If the environment is Web, it creates and initializes a `WebWalletManager`. + * - Throws an error if the environment is neither supported. + * + * @param cfg - Configuration object used to initialize the wallet manager. + * @returns A promise that resolves to an initialized `WalletManagerBase` instance. + * @throws {Error} If the environment is not supported (neither React Native nor Web). + */ +export async function createWalletManager( + cfg: TWalletManagerConfig, +): Promise { + if (isReactNative()) { + const manager = new MobileWalletManager(cfg); + await manager.init(cfg); + return manager; + } else if (isWeb()) { + const manager = new WebWalletManager(cfg); + await manager.init(cfg); + return manager; + } else { + throw new Error("Unsupported environment for wallet manager"); + } +} diff --git a/packages/core/src/__wallet__/connector.ts b/packages/core/src/__wallet__/connector.ts new file mode 100644 index 000000000..1b996a7d8 --- /dev/null +++ b/packages/core/src/__wallet__/connector.ts @@ -0,0 +1,133 @@ +import { + SignIntent, + WalletProvider, + WalletInterface, + WalletInterfaceType, + SwitchableChain, + Chain, +} from "@types"; + +export interface CrossPlatformWalletConnectorInterface { + sign( + message: string | Uint8Array, + walletProvider: WalletProvider, + intent: SignIntent, + ): Promise; +} + +export class CrossPlatformWalletConnector + implements CrossPlatformWalletConnectorInterface +{ + /** + * Constructs a CrossPlatformWalletConnector. + * + * - Validates that at least one wallet interface is provided. + * - Stores the provided mapping of wallet interfaces. + * + * @param wallets - A partial mapping of wallet interfaces by type. + * @throws {Error} If no wallet interfaces are provided. + */ + constructor( + private readonly wallets: Partial< + Record + >, + ) { + if (!Object.keys(wallets).length) { + throw new Error( + "Cannot create WalletConnector: no wallet interfaces provided", + ); + } + } + + /** + * Connects the wallet account for the given provider. + * + * @param provider - The wallet provider to connect. + * @returns A promise that resolves once the wallet account is connected. + */ + async connectWalletAccount(provider: WalletProvider): Promise { + const wallet = this.wallets[provider.interfaceType]; + + if (!wallet) { + throw new Error(`Wallet for ${provider.interfaceType} not initialized`); + } + + await wallet.connectWalletAccount(provider); + } + + /** + * Disconnects the wallet account for the given provider. + * + * @param provider - The wallet provider to disconnect. + * @returns A promise that resolves once the wallet account is disconnected. + */ + async disconnectWalletAccount(provider: WalletProvider): Promise { + const wallet = this.wallets[provider.interfaceType]; + + if (!wallet) { + throw new Error(`Wallet for ${provider.interfaceType} not initialized`); + } + + await wallet.disconnectWalletAccount(provider); + } + + /** + * Switches the chain for an EVM-compatible wallet provider (native or WalletConnect). + * + * - Only supported for wallet providers on the Ethereum namespace. + * - Native (extension) wallets: + * - If `chainOrId` is a hex string and the wallet doesn't support it, the switch will fail. + * - If `chainOrId` is a `SwitchableChain` object, the wallet will attempt to switch; if the chain + * is unsupported, it will first add the chain (via `wallet_addEthereumChain`) and then retry switching. + * - WalletConnect wallets: + * - Chain support is negotiated up front via namespaces. If the target chain isn't in the session's + * `ethereumNamespaces`, the switch will fail. To support a new chain, you must specify it in the walletConfig. + * + * @param provider - The EVM-compatible wallet provider to switch chains for. + * @param chainOrId - The target chain ID (hex string) or full chain config (`SwitchableChain`). + * @returns A promise that resolves once the chain switch is complete. + * @throws {Error} If the provider is not Ethereum-based or doesn't support switching. + */ + async switchChain( + provider: WalletProvider, + chainOrId: string | SwitchableChain, + ): Promise { + if (provider.chainInfo.namespace !== Chain.Ethereum) { + throw new Error("Only Ethereum wallets support chain switching"); + } + + const wallet = this.wallets[provider.interfaceType]; + if (!wallet?.switchChain) { + throw new Error( + `Wallet ${provider.interfaceType} doesn’t support switching chains`, + ); + } + + return wallet.switchChain(provider, chainOrId); + } + + /** + * Signs a payload using the appropriate wallet based on the provider. + * + * @param payload - The payload to be signed. + * @param walletProvider - The wallet provider used for signing. + * @param intent - The signing intent (e.g., message, transaction). + * @returns A promise that resolves to a hex string (signature or tx hash). + * @throws {Error} If the wallet is not initialized. + */ + async sign( + payload: string, + walletProvider: WalletProvider, + intent: SignIntent, + ): Promise { + const wallet = this.wallets[walletProvider.interfaceType]; + + if (!wallet) { + throw new Error( + `Wallet for ${walletProvider.interfaceType} not initialized`, + ); + } + + return wallet.sign(payload, walletProvider, intent); + } +} diff --git a/packages/core/src/__wallet__/mobile/manager.ts b/packages/core/src/__wallet__/mobile/manager.ts new file mode 100644 index 000000000..da761e75e --- /dev/null +++ b/packages/core/src/__wallet__/mobile/manager.ts @@ -0,0 +1,155 @@ +import { CrossPlatformWalletStamper } from "../stamper"; +import { CrossPlatformWalletConnector } from "../connector"; +import { + TWalletManagerConfig, + WalletInterface, + WalletProvider, + WalletInterfaceType, + Chain, +} from "@types"; +import { WalletConnectClient } from "../wallet-connect/client"; +import { WalletConnectWallet } from "../wallet-connect/base"; + +export class MobileWalletManager { + // queue of async initialization functions + private initializers: Array<() => Promise> = []; + + // WalletConnect client instance + private wcClient?: WalletConnectClient; + + // mapping of wallet interface types to their wallet instances + readonly wallets: Partial> = {}; + + // maps a blockchain chain to its corresponding wallet interface types + private chainToInterfaces: Partial> = {}; + + // responsible for stamping messages using wallets + readonly stamper?: CrossPlatformWalletStamper; + + // handles signature flows for authentication + readonly connector?: CrossPlatformWalletConnector; + + /** + * Constructs a MobileWalletManager that only uses WalletConnect. + * + * - Determines enabled chains based on provided namespaces for Ethereum and Solana. + * - Initializes WalletConnect wallet interface and maps it to supported chains. + * - Optionally enables stamping and connecting flows based on feature flags that live in the cfg. + * - Sets up `CrossPlatformWalletStamper` and `CrossPlatformWalletConnector` if auth or connecting features are enabled. + * + * @param cfg - Wallet manager configuration (we only use WalletConnect fields). + */ + constructor(cfg: TWalletManagerConfig) { + const ethereumNamespaces = + cfg.chains.ethereum?.walletConnectNamespaces ?? []; + const solanaNamespaces = cfg.chains.solana?.walletConnectNamespaces ?? []; + + const enableWalletConnectEvm = ethereumNamespaces.length > 0; + const enableWalletConnectSol = solanaNamespaces.length > 0; + + const enableWalletConnect = + enableWalletConnectEvm || enableWalletConnectSol; + + if (cfg.walletConnect && enableWalletConnect) { + this.wcClient = new WalletConnectClient(); + const wcUnified = new WalletConnectWallet(this.wcClient); + + this.wallets[WalletInterfaceType.WalletConnect] = wcUnified; + + // add async init step to the initializer queue + this.initializers.push(() => + wcUnified.init({ ethereumNamespaces, solanaNamespaces }), + ); + + // register WalletConnect as a wallet interface for each enabled chain + if (enableWalletConnectEvm) { + this.addChainInterface( + Chain.Ethereum, + WalletInterfaceType.WalletConnect, + ); + } + if (enableWalletConnectSol) { + this.addChainInterface(Chain.Solana, WalletInterfaceType.WalletConnect); + } + } + + if (cfg.features?.auth) { + this.stamper = new CrossPlatformWalletStamper(this.wallets); + } + + if (cfg.features?.connecting) { + this.connector = new CrossPlatformWalletConnector(this.wallets); + } + } + + /** + * Initializes WalletConnect components and any registered wallet interfaces. + * + * - First initializes the low-level WalletConnect client with the provided config. + * - Then initializes higher-level wallet interface `WalletConnectWallet` using registered async initializers. + * + * @param cfg - Wallet manager configuration used for initializing the WalletConnect client. + */ + async init(cfg: TWalletManagerConfig): Promise { + if (this.wcClient) { + await this.wcClient.init(cfg.walletConnect!); + } + + // we initialize the high-level WalletConnectWallet + // we do this because we can't init this inside the constructor since it's async + await Promise.all(this.initializers.map((fn) => fn())); + } + + /** + * Retrieves available wallet providers, optionally filtered by chain. + * + * - If a chain is specified, filters wallet interfaces that support that chain. + * - Aggregates providers across all registered wallet interfaces. + * - Filters WalletConnect results to match the specified chain. + * + * @param chain - Optional chain to filter providers by. + * @returns A promise that resolves to an array of `WalletProvider` objects. + * @throws {Error} If no wallet interface is registered for the given chain. + */ + async getProviders(chain?: Chain): Promise { + if (chain) { + const interfaceType = this.chainToInterfaces[chain]; + if (!interfaceType || interfaceType.length === 0) { + throw new Error(`No wallet supports chain: ${chain}`); + } + + const walletsToQuery = interfaceType + .map((iface) => this.wallets[iface]) + .filter(Boolean) as WalletInterface[]; + + const providersArrays = await Promise.all( + walletsToQuery.map((wallet) => wallet.getProviders()), + ); + + // we still need to filter by chain because WalletConnect can return providers for multiple chains + return providersArrays + .flat() + .filter((p) => p.chainInfo.namespace === chain); + } + + const providersArrays = await Promise.all( + Object.values(this.wallets).map((wallet) => wallet.getProviders()), + ); + + return providersArrays.flat(); + } + + /** + * Registers a wallet interface type as supporting a specific blockchain chain. + * + * @param chain - Chain (e.g., Ethereum, Solana). + * @param interfaceType - Wallet interface type to associate with the chain. + */ + private addChainInterface = ( + chain: Chain, + interfaceType: WalletInterfaceType, + ) => { + if (!this.chainToInterfaces[chain]) this.chainToInterfaces[chain] = []; + this.chainToInterfaces[chain]!.push(interfaceType); + }; +} diff --git a/packages/core/src/__wallet__/stamper.ts b/packages/core/src/__wallet__/stamper.ts new file mode 100644 index 000000000..be5a7c6ba --- /dev/null +++ b/packages/core/src/__wallet__/stamper.ts @@ -0,0 +1,247 @@ +import { + SignIntent, + type WalletInterface, + type TStamp, + type TStamper, + type WalletProvider, + WalletInterfaceType, +} from "@types"; +import { + stringToBase64urlString, + uint8ArrayFromHexString, + uint8ArrayToHexString, +} from "@turnkey/encoding"; +import type { Hex } from "viem"; +import { isEthereumWallet, isSolanaWallet } from "@utils"; + +const SIGNATURE_SCHEME_TK_API_SECP256K1_EIP191 = + "SIGNATURE_SCHEME_TK_API_SECP256K1_EIP191"; +const SIGNATURE_SCHEME_TK_API_ED25519 = "SIGNATURE_SCHEME_TK_API_ED25519"; +const STAMP_HEADER_NAME = "X-Stamp"; + +interface WalletContext { + wallet: WalletInterface; + stamper: WalletStamper; + provider?: WalletProvider; +} + +type ContextMap = Partial>; + +export class CrossPlatformWalletStamper implements TStamper { + private readonly ctx: ContextMap = {}; + private activeInterfaceType?: WalletInterfaceType; + + /** + * Constructs a CrossPlatformWalletStamper. + * + * - Validates that at least one wallet interface is provided. + * - For each wallet interface, creates an internal `WalletStamper` bound to it. + * - Ensures the stamper instance is always initialized in a usable state. + * + * @param wallets - A partial mapping of wallet interfaces by type. + * @throws {Error} If no wallet interfaces are provided. + */ + constructor(wallets: Partial>) { + const walletEntries = Object.entries(wallets).filter(([, w]) => + Boolean(w), + ) as Array<[string, WalletInterface]>; + + if (walletEntries.length === 0) { + throw new Error( + "Cannot create WalletStamper: no wallet interfaces provided", + ); + } + + for (const [interfaceType, wallet] of walletEntries) { + const typed = interfaceType as WalletInterfaceType; + this.ctx[typed] = { wallet, stamper: new WalletStamper(wallet) }; + } + } + + /** + * Stamps a payload using the specified wallet interface and provider. + * + * - Uses the explicitly provided interface and provider if given. + * - Falls back to the default interface and stored provider otherwise. + * + * @param payload - The string payload to sign. + * @param interfaceType - Optional wallet interface type (defaults to the active or first available). + * @param provider - Optional provider (defaults to the one set via `setProvider`). + * @returns A `TStamp` object containing the stamp header name and encoded value. + * @throws {Error} If no provider is available for the selected interface. + */ + async stamp( + payload: string, + interfaceType: WalletInterfaceType = this.defaultInterface(), + provider?: WalletProvider, + ): Promise { + const ctx = this.getCtx(interfaceType); + const selectedProvider = provider ?? ctx.provider; + + if (!selectedProvider) { + throw new Error( + `Could not find a provider for interface '${interfaceType}'.`, + ); + } + + return ctx.stamper.stamp(payload, selectedProvider); + } + + /** + * Retrieves the public key for the given provider. + * + * @param interfaceType - Optional wallet interface type (defaults to the active or first available). + * @param provider - Wallet provider for which to fetch the public key. + * @returns A promise resolving to the public key in hex format. + */ + async getPublicKey( + interfaceType: WalletInterfaceType = this.defaultInterface(), + provider: WalletProvider, + ): Promise { + return this.getCtx(interfaceType).wallet.getPublicKey(provider); + } + + /** + * Sets the active provider for a given wallet interface. + * + * - The active provider is used as a fallback in `stamp` if none is passed explicitly. + * + * @param interfaceType - Wallet interface type. + * @param provider - Provider instance to associate with the interface. + */ + setProvider( + interfaceType: WalletInterfaceType, + provider: WalletProvider, + ): void { + this.getCtx(interfaceType).provider = provider; + this.activeInterfaceType = interfaceType; + } + + /** + * Determines the default wallet interface to use when none is specified. + * + * - Preference order: Active provider > Ethereum > Solana > WalletConnect. + * + * @returns The default wallet interface type. + * @throws {Error} If no wallet interfaces are initialized. + */ + private defaultInterface(): WalletInterfaceType { + if (this.activeInterfaceType) { + return this.activeInterfaceType; + } + + const initializedInterfaces = Object.keys( + this.ctx, + ) as WalletInterfaceType[]; + + if (initializedInterfaces.includes(WalletInterfaceType.Ethereum)) { + return WalletInterfaceType.Ethereum; + } + + if (initializedInterfaces.includes(WalletInterfaceType.Solana)) { + return WalletInterfaceType.Solana; + } + + if (initializedInterfaces.includes(WalletInterfaceType.WalletConnect)) { + return WalletInterfaceType.WalletConnect; + } + + throw new Error("No interfaces initialized"); + } + + /** + * Retrieves the internal context for a given wallet interface. + * + * @param interfaceType - Wallet interface type. + * @returns The context including wallet, stamper, and optional provider. + * @throws {Error} If the interface is not initialized. + */ + private getCtx(interfaceType: WalletInterfaceType): WalletContext { + const ctx = this.ctx[interfaceType]; + + if (!ctx) { + throw new Error(`Interface '${interfaceType}' not initialised`); + } + + return ctx; + } +} + +export class WalletStamper { + /** + * Constructs a WalletStamper bound to a single wallet interface. + * + * @param wallet - The wallet interface used for signing. + */ + constructor(private readonly wallet: WalletInterface) {} + + /** + * Signs a payload and returns a standardized stamp header. + * + * - For Ethereum: + * - Signs using EIP-191. + * - Recovers and compresses the public key. + * - Converts the signature into DER format. + * - For Solana: + * - Signs using Ed25519. + * - Fetches the public key directly from the wallet. + * + * @param payload - The payload to sign. + * @param provider - The wallet provider used for signing. + * @returns A `TStamp` containing the header name and base64url-encoded JSON value. + * @throws {Error} If signing or public key recovery fails. + */ + async stamp(payload: string, provider: WalletProvider): Promise { + let signature: string; + let publicKey: string; + + try { + signature = await this.wallet.sign( + payload, + provider, + SignIntent.SignMessage, + ); + } catch (error) { + throw new Error(`Failed to sign the message: ${error}`); + } + + const scheme = isSolanaWallet(provider) + ? SIGNATURE_SCHEME_TK_API_ED25519 + : SIGNATURE_SCHEME_TK_API_SECP256K1_EIP191; + + try { + if (isEthereumWallet(provider)) { + const { recoverPublicKey, hashMessage } = await import("viem"); + const { compressRawPublicKey, toDerSignature } = await import( + "@turnkey/crypto" + ); + + const rawPublicKey = await recoverPublicKey({ + hash: hashMessage(payload), + signature: signature as Hex, + }); + + const publicKeyHex = rawPublicKey.startsWith("0x") + ? rawPublicKey.slice(2) + : rawPublicKey; + + const publicKeyBytes = uint8ArrayFromHexString(publicKeyHex); + const publicKeyBytesCompressed = compressRawPublicKey(publicKeyBytes); + + publicKey = uint8ArrayToHexString(publicKeyBytesCompressed); + signature = toDerSignature(signature.replace("0x", "")); + } else { + publicKey = await this.wallet.getPublicKey(provider); + } + } catch (error) { + throw new Error(`Failed to recover public key: ${error}`); + } + + return { + stampHeaderName: STAMP_HEADER_NAME, + stampHeaderValue: stringToBase64urlString( + JSON.stringify({ publicKey, scheme, signature }), + ), + }; + } +} diff --git a/packages/core/src/__wallet__/wallet-connect/base.ts b/packages/core/src/__wallet__/wallet-connect/base.ts new file mode 100644 index 000000000..ea8552cc3 --- /dev/null +++ b/packages/core/src/__wallet__/wallet-connect/base.ts @@ -0,0 +1,580 @@ +import { + uint8ArrayFromHexString, + uint8ArrayToHexString, + stringToBase64urlString, +} from "@turnkey/encoding"; +import bs58 from "bs58"; +import { recoverPublicKey, hashMessage, type Hex, toHex } from "viem"; +import { compressRawPublicKey } from "@turnkey/crypto"; +import { + Chain, + WalletInterfaceType, + WalletProvider, + WalletProviderInfo, + SignIntent, + WalletConnectProvider, + WalletConnectInterface, + SwitchableChain, +} from "@types"; +import type { WalletConnectClient } from "./client"; +import type { SessionTypes } from "@walletconnect/types"; +import { Transaction } from "ethers"; + +export class WalletConnectWallet implements WalletConnectInterface { + readonly interfaceType = WalletInterfaceType.WalletConnect; + + private ethereumNamespaces: string[] = []; + private solanaNamespaces: string[] = []; + + private ethChain!: string; + private solChain!: string; + + private uri?: string; + + /** + * Constructs a WalletConnectWallet bound to a WalletConnect client. + * + * - Subscribes to session deletions and automatically re-initiates pairing, + * updating `this.uri` so the UI can present a fresh QR/deeplink. + * + * @param client - The low-level WalletConnect client used for session/RPC. + */ + constructor(private client: WalletConnectClient) { + this.client.onSessionDelete(async () => { + try { + this.uri = await this.client.pair(this.buildNamespaces()); + } catch (err) { + console.warn( + "WalletConnect: failed to re-pair after session delete", + err, + ); + } + }); + } + + /** + * Initializes WalletConnect pairing flow with the specified namespaces. + * + * - Saves the requested chain namespaces (e.g., `["eip155:1", "eip155:137", "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"]`). + * - If an active session already has connected accounts, pairing is skipped. + * - Otherwise initiates a pairing and stores the resulting URI. + * + * @param opts.ethereumNamespaces - List of EVM CAIP IDs (e.g., "eip155:1"). + * @param opts.solanaNamespaces - List of Solana CAIP IDs (e.g., "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"). + * @throws {Error} If no namespaces are provided for either chain. + */ + async init(opts: { + ethereumNamespaces: string[]; + solanaNamespaces: string[]; + }): Promise { + this.ethereumNamespaces = opts.ethereumNamespaces; + if (this.ethereumNamespaces.length > 0) { + this.ethChain = this.ethereumNamespaces[0]!; + } + + this.solanaNamespaces = opts.solanaNamespaces; + if (this.solanaNamespaces.length > 0) { + this.solChain = this.solanaNamespaces[0]!; + } + + if ( + this.ethereumNamespaces.length === 0 && + this.solanaNamespaces.length === 0 + ) { + throw new Error( + "At least one namespace must be enabled for WalletConnect", + ); + } + + // we don't want to create more than one active session + // so we don't make a pair request if one is already active + // since pairing would mean initializing a new session + const session = this.client.getSession(); + if (hasConnectedAccounts(session)) { + return; + } + + const namespaces = this.buildNamespaces(); + + this.uri = await this.client.pair(namespaces); + } + + /** + * Returns WalletConnect providers with associated chain/account metadata. + * + * - Builds an EVM provider (if Ethereum namespaces are enabled). + * - Builds a Solana provider (if Solana namespaces are enabled). + * + * @returns A promise resolving to an array of WalletProvider objects. + */ + async getProviders(): Promise { + const session = this.client.getSession(); + + const info: WalletProviderInfo = { + name: "WalletConnect", + icon: "https://raw.githubusercontent.com/WalletConnect/walletconnect-assets/refs/heads/master/Icon/Blue%20(Default)/Icon.svg", + }; + + const providers: WalletProvider[] = []; + + if (this.ethereumNamespaces.length > 0) { + providers.push(await this.buildEthProvider(session, info)); + } + + if (this.solanaNamespaces.length > 0) { + providers.push(this.buildSolProvider(session, info)); + } + + return providers; + } + + /** + * Approves the session if needed and ensures at least one account is available. + * + * - Calls `approve()` on the underlying client when pairing is pending. + * - Throws if the approved session contains no connected accounts. + * + * @param _provider - Unused (present for interface compatibility). + * @throws {Error} If the session contains no accounts. + */ + async connectWalletAccount(_provider: WalletProvider): Promise { + const session = await this.client.approve(); + if (!hasConnectedAccounts(session)) + throw new Error("No account found in session"); + } + + /** + * Switches the user’s WalletConnect session to a new EVM chain. + * + * - Ethereum-only: only supported for providers on the Ethereum namespace. + * - No add-then-switch: WalletConnect cannot add chains mid-session. The target chain + * must be present in `ethereumNamespaces` negotiated at pairing time. To support a new chain, + * you must include it in the walletConfig. + * - Accepts a hex chain ID (e.g., "0x1"). If a `SwitchableChain` is passed, only its `id` + * (hex chain ID) is used; metadata is ignored for WalletConnect. + * + * @param provider - The WalletProvider returned by `getProviders()`. + * @param chainOrId - Hex chain ID (e.g., "0x1") or a `SwitchableChain` (its `id` is used). + * @returns A promise that resolves when the switch completes. + * @throws {Error} If no active session, provider is non-EVM, the chain is not in `ethereumNamespaces`, + * or the switch RPC fails. + */ + async switchChain( + provider: WalletProvider, + chainOrId: string | SwitchableChain, + ): Promise { + if (provider.chainInfo.namespace !== Chain.Ethereum) { + throw new Error("Only EVM wallets support chain switching"); + } + + const session = this.client.getSession(); + if (!session) { + throw new Error("No active WalletConnect session"); + } + + const hexChainId = typeof chainOrId === "string" ? chainOrId : chainOrId.id; + const caip = `eip155:${Number.parseInt(hexChainId, 16)}`; + + if (!this.ethereumNamespaces.includes(caip)) { + throw new Error( + `Unsupported chain ${caip}. Supported chains: ${this.ethereumNamespaces.join( + ", ", + )}. If you’d like to support ${caip}, add it to the \`ethereumNamespaces\` in your WalletConnect config.`, + ); + } + + try { + // first we just try switching + await this.client.request(this.ethChain, "wallet_switchEthereumChain", [ + { chainId: hexChainId }, + ]); + + this.ethChain = caip; + } catch (err: any) { + throw new Error( + `Failed to switch chain: ${err.message || err.toString()}`, + ); + } + } + + /** + * Signs a message or transaction using the specified wallet provider and intent. + * + * - Ensures an active WalletConnect session: + * - If a pairing is in progress (URI shown but not yet approved), this call will + * wait for the user to approve the session and may appear stuck until they do. + * - If no pairing is in progress, this will throw (e.g., "call pair() before approve()"). + * - Ethereum: + * - `SignMessage` β†’ `personal_sign` (returns hex signature). + * - `SignAndSendTransaction` β†’ `eth_sendTransaction` (returns tx hash). + * - Solana: + * - `SignMessage` β†’ `solana_signMessage` (returns hex signature). + * - `SignTransaction` β†’ `solana_signTransaction` (returns hex signature). + * - `SignAndSendTransaction` β†’ `solana_sendTransaction` (returns hex signature of the submitted tx). + * + * @param payload - Payload or serialized transaction to sign. + * @param provider - The WalletProvider to use. + * @param intent - The signing intent. + * @returns A hex string (signature or transaction hash, depending on intent). + * @throws {Error} If no account is available, no pairing is in progress, or the intent is unsupported. + */ + async sign( + payload: string, + provider: WalletProvider, + intent: SignIntent, + ): Promise { + const session = await this.ensureSession(); + + if (!hasConnectedAccounts(session)) { + await this.connectWalletAccount(provider); + } + + if (provider.chainInfo.namespace === Chain.Ethereum) { + const address = getConnectedEthereum(session); + if (!address) { + throw new Error("no Ethereum account to sign with"); + } + + switch (intent) { + case SignIntent.SignMessage: + return (await this.client.request(this.ethChain, "personal_sign", [ + payload as Hex, + address, + ])) as string; + case SignIntent.SignAndSendTransaction: + const account = provider.connectedAddresses[0]; + const tx = Transaction.from(payload); + const txParams = { + from: account, + to: tx.to?.toString() as Hex, + value: toHex(tx.value), + gas: toHex(tx.gasLimit), + maxFeePerGas: toHex(tx.maxFeePerGas ?? 0n), + maxPriorityFeePerGas: toHex(tx.maxPriorityFeePerGas ?? 0n), + nonce: toHex(tx.nonce), + chainId: toHex(tx.chainId), + data: (tx.data?.toString() as Hex) ?? "0x", + }; + + return (await this.client.request( + this.ethChain, + "eth_sendTransaction", + [txParams], + )) as string; + default: + throw new Error(`Unsupported Ethereum intent: ${intent}`); + } + } + + if (provider.chainInfo.namespace === Chain.Solana) { + const address = getConnectedSolana(session); + if (!address) { + throw new Error("no Solana account to sign with"); + } + + switch (intent) { + case SignIntent.SignMessage: { + const msgBytes = new TextEncoder().encode(payload); + const msgB58 = bs58.encode(msgBytes); + const { signature: sigB58 } = await this.client.request( + this.solChain, + "solana_signMessage", + { + pubkey: address, + message: msgB58, + }, + ); + return uint8ArrayToHexString(bs58.decode(sigB58)); + } + case SignIntent.SignTransaction: { + const txBytes = uint8ArrayFromHexString(payload); + const txBase64 = stringToBase64urlString( + String.fromCharCode(...txBytes), + ); + const { signature: sigB58 } = await this.client.request( + this.solChain, + "solana_signTransaction", + { + feePayer: address, + transaction: txBase64, + }, + ); + return uint8ArrayToHexString(bs58.decode(sigB58)); + } + case SignIntent.SignAndSendTransaction: { + const txBytes = uint8ArrayFromHexString(payload); + const txBase64 = stringToBase64urlString( + String.fromCharCode(...txBytes), + ); + const sigB58 = await this.client.request( + this.solChain, + "solana_sendTransaction", + { + feePayer: address, + transaction: txBase64, + options: { skipPreflight: false }, + }, + ); + return uint8ArrayToHexString(bs58.decode(sigB58)); + } + default: + throw new Error(`Unsupported Solana intent: ${intent}`); + } + } + + throw new Error("No supported namespace available for signing"); + } + + /** + * Retrieves the public key of the connected wallet. + * + * - Ethereum: signs a fixed challenge and recovers the compressed secp256k1 public key. + * - Solana: decodes the base58-encoded address to raw bytes. + * + * @param provider - The WalletProvider to fetch the key from. + * @returns A compressed public key as a hex string. + * @throws {Error} If no account is available or the namespace is unsupported. + */ + async getPublicKey(provider: WalletProvider): Promise { + const session = this.client.getSession(); + + if (provider.chainInfo.namespace === Chain.Ethereum) { + const address = getConnectedEthereum(session); + if (!address) { + throw new Error("No Ethereum account to retrieve public key"); + } + + const sig = await this.client.request(this.ethChain, "personal_sign", [ + "GET_PUBLIC_KEY", + address, + ]); + const rawPublicKey = await recoverPublicKey({ + hash: hashMessage("GET_PUBLIC_KEY"), + signature: sig as Hex, + }); + + const publicKeyHex = rawPublicKey.startsWith("0x") + ? rawPublicKey.slice(2) + : rawPublicKey; + + const publicKeyBytes = uint8ArrayFromHexString(publicKeyHex); + const publicKeyBytesCompressed = compressRawPublicKey(publicKeyBytes); + + return uint8ArrayToHexString(publicKeyBytesCompressed); + } + + if (provider.chainInfo.namespace === Chain.Solana) { + const address = getConnectedSolana(session); + if (!address) { + throw new Error("No Solana account to retrieve public key"); + } + + const publicKeyBytes = bs58.decode(address); + return uint8ArrayToHexString(publicKeyBytes); + } + + throw new Error("No supported namespace for public key retrieval"); + } + + /** + * Disconnects the current session and re-initiates a fresh pairing URI. + * + * - Calls `disconnect()` on the client, then `pair()` with current namespaces. + * - Updates `this.uri` so the UI can present a new QR/deeplink. + */ + async disconnectWalletAccount(_provider: WalletProvider): Promise { + await this.client.disconnect(); + + const namespaces = this.buildNamespaces(); + + await this.client.pair(namespaces).then((newUri) => { + this.uri = newUri; + }); + } + + /** + * Builds a lightweight provider interface for the given chain. + * + * @param chainId - Namespace chain ID (e.g., "eip155:1" or "solana:101"). + * @returns A WalletConnect-compatible provider that proxies JSON-RPC via WC. + */ + private makeProvider(chainId: string): WalletConnectProvider { + return { + request: ({ method, params }: any) => { + return this.client.request(chainId, method, params); + }, + }; + } + + /** + * Ensures there is an active WalletConnect session, initiating approval if necessary. + * + * - If a session exists, returns it immediately. + * - If no session exists but a pairing is in progress, awaits `approve()` β€” + * this will block until the user approves (or rejects) in their wallet. + * - If no session exists and no pairing is in progress, throws; the caller + * must have initiated pairing via `pair()` elsewhere. + * + * @returns The active WalletConnect session. + * @throws {Error} If approval is rejected, completes without establishing a session, + * or no pairing is in progress. + */ + private async ensureSession(): Promise { + let session = this.client.getSession(); + if (!session) { + await this.client.approve(); + session = this.client.getSession(); + if (!session) throw new Error("WalletConnect: approval failed"); + } + return session; + } + + /** + * Builds a WalletProvider descriptor for an EVM chain. + * + * - Extracts the connected address (if any) and current chain ID. + * - Includes the pairing `uri` if available. + * + * @param session - Current WalletConnect session (or null). + * @param info - Provider branding info (name, icon). + * @returns A WalletProvider object for Ethereum. + */ + private async buildEthProvider( + session: SessionTypes.Struct | null, + info: WalletProviderInfo, + ): Promise { + const raw = session?.namespaces.eip155?.accounts?.[0] ?? ""; + const address = raw.split(":")[2]; + + const chainIdString = this.ethChain.split(":")[1] ?? "1"; + const chainIdDecimal = Number(chainIdString); + const chainidHex = `0x${chainIdDecimal.toString(16)}`; + + return { + interfaceType: WalletInterfaceType.WalletConnect, + chainInfo: { + namespace: Chain.Ethereum, + chainId: chainidHex, + }, + info, + provider: this.makeProvider(this.ethChain), + connectedAddresses: address ? [address] : [], + ...(this.uri && { uri: this.uri }), + }; + } + + /** + * Builds a WalletProvider descriptor for Solana. + * + * - Extracts the connected address (if any). + * - Includes the fresh pairing `uri` if available. + * + * @param session - Current WalletConnect session (or null). + * @param info - Provider branding info (name, icon). + * @returns A WalletProvider object for Solana. + */ + private buildSolProvider( + session: SessionTypes.Struct | null, + info: WalletProviderInfo, + ): WalletProvider { + const raw = session?.namespaces.solana?.accounts?.[0] ?? ""; + const address = raw.split(":")[2]; + + return { + interfaceType: WalletInterfaceType.WalletConnect, + chainInfo: { namespace: Chain.Solana }, + info, + provider: this.makeProvider(this.solChain), + connectedAddresses: address ? [address] : [], + ...(this.uri && { uri: this.uri }), + }; + } + + /** + * Builds the requested WalletConnect namespaces from the current config. + * + * - Includes methods and events for Ethereum and/or Solana based on enabled namespaces. + * + * @returns A namespaces object suitable for `WalletConnectClient.pair()`. + */ + private buildNamespaces(): Record { + const namespaces: Record = {}; + + if (this.ethereumNamespaces.length > 0) { + namespaces.eip155 = { + methods: [ + "personal_sign", + "eth_sendTransaction", + "eth_chainId", + "wallet_switchEthereumChain", + "wallet_addEthereumChain", + ], + chains: this.ethereumNamespaces, + events: ["accountsChanged", "chainChanged"], + }; + } + + if (this.solanaNamespaces.length > 0) { + namespaces.solana = { + methods: [ + "solana_signMessage", + "solana_signTransaction", + "solana_sendTransaction", + ], + chains: this.solanaNamespaces, + events: ["accountsChanged", "chainChanged"], + }; + } + + return namespaces; + } +} + +/** + * Determines whether the session has at least one connected account + * across any namespace. + * + * - Safe to call with `null` (returns `false`). + * - Checks all namespaces for a non-empty `accounts` array. + * + * @param session - The current WalletConnect session, or `null`. + * @returns `true` if any namespace has β‰₯1 account; otherwise `false`. + */ +function hasConnectedAccounts(session: SessionTypes.Struct | null): boolean { + return ( + !!session && + Object.values(session.namespaces).some((ns) => ns.accounts?.length > 0) + ); +} + +/** + * Retrieves the first connected Ethereum account. + * + * - Safe to call with `null` (returns `undefined`). + * - Returns only the address portion (e.g., `0xabc...`), not the full CAIP string. + * + * @param session - The current WalletConnect session, or `null`. + * @returns The connected EVM address, or `undefined` if none. + */ +function getConnectedEthereum( + session: SessionTypes.Struct | null, +): string | undefined { + const acc = session?.namespaces.eip155?.accounts?.[0]; + return acc ? acc.split(":")[2] : undefined; +} + +/** + * Retrieves the first connected Solana account. + * + * - Safe to call with `null` (returns `undefined`). + * - Returns only the base58 address portion, not the full CAIP string. + * + * @param session - The current WalletConnect session, or `null`. + * @returns The connected Solana address (base58), or `undefined` if none. + */ +function getConnectedSolana( + session: SessionTypes.Struct | null, +): string | undefined { + const acc = session?.namespaces.solana?.accounts?.[0]; + return acc ? acc.split(":")[2] : undefined; +} diff --git a/packages/core/src/__wallet__/wallet-connect/client.ts b/packages/core/src/__wallet__/wallet-connect/client.ts new file mode 100644 index 000000000..d25f823e5 --- /dev/null +++ b/packages/core/src/__wallet__/wallet-connect/client.ts @@ -0,0 +1,169 @@ +import SignClient from "@walletconnect/sign-client"; +import type { + CoreTypes, + ProposalTypes, + SessionTypes, +} from "@walletconnect/types"; + +/** + * WalletConnectClient is a low-level wrapper around the WalletConnect SignClient. + * + * - Used internally by `WalletConnectWallet` to manage connections and sessions. + * - Handles pairing, approval, session tracking, RPC requests, and disconnects. + * - Exposes a minimal API for lifecycle control; higher-level logic lives in `WalletConnectWallet`. + */ +export class WalletConnectClient { + private client!: SignClient; + + // tracks the pending approval callback returned from `connect()` + private pendingApproval: (() => Promise) | null = null; + + // callbacks to run when the session is deleted + private sessionDeleteHandlers: Array<() => void> = []; + + /** + * Registers a callback that runs when the WalletConnect session is deleted. + * + * - Useful for clearing UI state or internal session data. + * + * @param fn - A callback function to invoke when the session is deleted. + */ + public onSessionDelete(fn: () => void) { + this.sessionDeleteHandlers.push(fn); + } + + /** + * Initializes the WalletConnect SignClient with your project credentials. + * + * - Must be called before `pair()`, `approve()`, or `request()`. + * - Configures app metadata and an optional custom relay server. + * + * @param opts.projectId - WalletConnect project ID. + * @param opts.appMetadata - Metadata about your app (name, URL, icons). + * @param opts.relayUrl - (Optional) custom relay server URL. + * @returns A promise that resolves once the client is initialized. + */ + async init(opts: { + projectId: string; + appMetadata: CoreTypes.Metadata; + relayUrl?: string; + }): Promise { + this.client = await SignClient.init({ + projectId: opts.projectId, + metadata: opts.appMetadata, + ...(opts.relayUrl ? { relayUrl: opts.relayUrl } : {}), + }); + + // we listen for session deletion events and notify subscribers + this.client.on("session_delete", () => { + this.sessionDeleteHandlers.forEach((h) => h()); + }); + } + + /** + * Initiates a pairing request and returns a URI to be scanned or deep-linked. + * + * - Requires `init()` to have been called. + * - Must be followed by `approve()` after the wallet approves. + * - Throws if a pairing is already in progress. + * + * @param namespaces - Optional namespaces requesting capabilities. + * @returns A WalletConnect URI for the wallet to connect with. + * @throws {Error} If a pairing is already in progress or no URI is returned. + */ + async pair(namespaces: ProposalTypes.OptionalNamespaces): Promise { + if (this.pendingApproval) { + throw new Error("WalletConnect: Pairing already in progress"); + } + + const { uri, approval } = await this.client.connect({ + optionalNamespaces: namespaces, + }); + + if (!uri) { + throw new Error("WalletConnect: no URI returned"); + } + + this.pendingApproval = approval; + return uri; + } + + /** + * Completes the pairing approval process after the wallet approves the request. + * + * - Requires `init()` and a pending pairing started via `pair()`. + * + * @returns A promise that resolves to the established session. + * @throws {Error} If called before `pair()` or if approval fails. + */ + + async approve(): Promise { + if (!this.pendingApproval) { + throw new Error("WalletConnect: call pair() before approve()"); + } + + try { + const session = await this.pendingApproval(); + return session; + } finally { + // we clear the pending state regardless of outcome + this.pendingApproval = null; + } + } + + /** + * Retrieves the most recent active WalletConnect session. + * + * @returns The most recent session, or `null` if none are active. + */ + getSession(): SessionTypes.Struct | null { + const sessions = this.client.session.getAll(); + return sessions.length ? sessions[sessions.length - 1]! : null; + } + + /** + * Sends a JSON-RPC request over the active WalletConnect session. + * + * - Requires `init()` and an active session. + * + * @param chainId - Target chain ID (e.g. `eip155:1`). + * @param method - RPC method name. + * @param params - Parameters for the RPC method. + * @returns A promise that resolves with the RPC response. + * @throws {Error} If no active session exists. + */ + async request( + chainId: string, + method: string, + params: any[] | Record, + ): Promise { + const session = this.getSession(); + if (!session) { + throw new Error("WalletConnect: no active session"); + } + + return this.client.request({ + topic: session.topic, + chainId, + request: { method, params }, + }); + } + + /** + * Disconnects the active session, if one exists. + * + * - Sends a disconnect signal to the wallet. + * - Does nothing if no session is currently active. + * + * @returns A promise that resolves once disconnection is complete. + */ + async disconnect(): Promise { + const session = this.getSession(); + if (!session) return; + + await this.client.disconnect({ + topic: session.topic, + reason: { code: 6000, message: "User disconnected" }, + }); + } +} diff --git a/packages/core/src/__wallet__/web/manager.ts b/packages/core/src/__wallet__/web/manager.ts new file mode 100644 index 000000000..ae0fe7534 --- /dev/null +++ b/packages/core/src/__wallet__/web/manager.ts @@ -0,0 +1,169 @@ +import { CrossPlatformWalletStamper } from "../stamper"; +import { CrossPlatformWalletConnector } from "../connector"; +import { EthereumWallet } from "./native/ethereum"; +import { SolanaWallet } from "./native/solana"; +import { + TWalletManagerConfig, + WalletInterface, + WalletProvider, + WalletInterfaceType, + Chain, +} from "@types"; +import { WalletConnectClient } from "../wallet-connect/client"; +import { WalletConnectWallet } from "../wallet-connect/base"; + +export class WebWalletManager { + // queue of async initialization functions + private initializers: Array<() => Promise> = []; + + // WalletConnect client instance + private wcClient?: WalletConnectClient; + + // mapping of wallet interface types to their wallet instances + readonly wallets: Partial> = {}; + + // maps a blockchain chain to its corresponding wallet interface types + private chainToInterfaces: Partial> = {}; + + // responsible for stamping messages using wallets + readonly stamper?: CrossPlatformWalletStamper; + + // handles signature flows for authentication + readonly connector?: CrossPlatformWalletConnector; + + /** + * Constructs a WebWalletManager instance based on the provided configuration. + * + * - Enables native Ethereum and/or Solana wallet support if configured. + * - Enables WalletConnect support for Ethereum and/or Solana chains if namespaces are provided. + * - Sets up `CrossPlatformWalletStamper` and `CrossPlatformWalletConnector` if auth or connecting features are enabled. + * + * @param cfg - Wallet manager configuration. + */ + constructor(cfg: TWalletManagerConfig) { + const enableNativeEvm = cfg.chains.ethereum?.native ?? false; + const enableNativeSol = cfg.chains.solana?.native ?? false; + + const ethereumNamespaces = + cfg.chains.ethereum?.walletConnectNamespaces ?? []; + const solanaNamespaces = cfg.chains.solana?.walletConnectNamespaces ?? []; + + const enableWalletConnectEvm = ethereumNamespaces.length > 0; + const enableWalletConnectSol = solanaNamespaces.length > 0; + + const enableWalletConnect = + enableWalletConnectEvm || enableWalletConnectSol; + + // set up native Ethereum wallet support + if (enableNativeEvm) { + this.wallets[WalletInterfaceType.Ethereum] = new EthereumWallet(); + this.addChainInterface(Chain.Ethereum, WalletInterfaceType.Ethereum); + } + + // set up native Solana wallet support + if (enableNativeSol) { + this.wallets[WalletInterfaceType.Solana] = new SolanaWallet(); + this.addChainInterface(Chain.Solana, WalletInterfaceType.Solana); + } + + // if WalletConnect is configured, set it up + if (cfg.walletConnect && enableWalletConnect) { + this.wcClient = new WalletConnectClient(); + const wcUnified = new WalletConnectWallet(this.wcClient); + + this.wallets[WalletInterfaceType.WalletConnect] = wcUnified; + + // add async init step to the initializer queue + this.initializers.push(() => + wcUnified.init({ ethereumNamespaces, solanaNamespaces }), + ); + + // register WalletConnect as a wallet interface for each enabled chain + if (enableWalletConnectEvm) + this.addChainInterface( + Chain.Ethereum, + WalletInterfaceType.WalletConnect, + ); + if (enableWalletConnectSol) + this.addChainInterface(Chain.Solana, WalletInterfaceType.WalletConnect); + } + + if (cfg.features?.auth) { + this.stamper = new CrossPlatformWalletStamper(this.wallets); + } + + if (cfg.features?.connecting) { + this.connector = new CrossPlatformWalletConnector(this.wallets); + } + } + + /** + * Initializes WalletConnect components and any registered wallet interfaces. + * + * - Initializes the low-level WalletConnect client with the provided config. + * - Runs any registered async wallet initializers (currently only `WalletConnectWallet`). + * + * @param cfg - Wallet manager configuration used for initializing the WalletConnect client. + */ + async init(cfg: TWalletManagerConfig): Promise { + if (this.wcClient) { + await this.wcClient.init(cfg.walletConnect!); + } + + // we initialize the high-level WalletConnectWallet + // we do this because we can't init this inside the constructor since it's async + await Promise.all(this.initializers.map((fn) => fn())); + } + + /** + * Retrieves available wallet providers, optionally filtered by chain. + * + * - If a chain is specified, filters wallet interfaces that support that chain. + * - Aggregates providers across all wallet interfaces and filters WalletConnect results accordingly. + * + * @param chain - Optional chain to filter providers by (e.g., Ethereum, Solana). + * @returns A promise that resolves to an array of `WalletProvider` objects. + * @throws {Error} If no wallet interface is registered for the given chain. + */ + async getProviders(chain?: Chain): Promise { + if (chain) { + const interfaceTypes = this.chainToInterfaces[chain]; + if (!interfaceTypes || interfaceTypes.length === 0) + throw new Error(`No wallet supports chain: ${chain}`); + + const walletsToQuery = interfaceTypes + .map((iface) => this.wallets[iface]) + .filter(Boolean) as WalletInterface[]; + + const providersArrays = await Promise.all( + walletsToQuery.map((wallet) => wallet.getProviders()), + ); + + // we still need to filter by chain because WalletConnect can return providers for multiple chains + return providersArrays + .flat() + .filter((p) => p.chainInfo.namespace === chain); + } + + // collect all providers from all initialized wallets + const providersArrays = await Promise.all( + Object.values(this.wallets).map((wallet) => wallet.getProviders()), + ); + + return providersArrays.flat(); + } + + /** + * Registers a wallet interface type as supporting a specific blockchain chain. + * + * @param chain - Chain (e.g., Ethereum, Solana). + * @param interfaceType - Wallet interface type to associate with the chain. + */ + private addChainInterface = ( + chain: Chain, + interfaceType: WalletInterfaceType, + ) => { + if (!this.chainToInterfaces[chain]) this.chainToInterfaces[chain] = []; + this.chainToInterfaces[chain]!.push(interfaceType); + }; +} diff --git a/packages/core/src/__wallet__/web/native/ethereum.ts b/packages/core/src/__wallet__/web/native/ethereum.ts new file mode 100644 index 000000000..817b66ae0 --- /dev/null +++ b/packages/core/src/__wallet__/web/native/ethereum.ts @@ -0,0 +1,366 @@ +import { + recoverPublicKey, + hashMessage, + Hex, + Address, + EIP1193Provider, + toHex, +} from "viem"; +import { Transaction } from "ethers"; +import { compressRawPublicKey } from "@turnkey/crypto"; +import { + Chain, + EthereumWalletInterface, + SignIntent, + SwitchableChain, + WalletInterfaceType, + WalletProvider, + WalletProviderInfo, + WalletRpcProvider, +} from "@types"; +import { + uint8ArrayFromHexString, + uint8ArrayToHexString, +} from "@turnkey/encoding"; + +/** + * Abstract base class for Ethereum wallet implementations. + * + * Provides shared logic for: + * - Provider discovery via EIP-6963 (request/announce events) + * - Connecting/disconnecting via EIP-1193 + * - Recovering compressed secp256k1 public keys from EIP-191 signatures + */ +export abstract class BaseEthereumWallet implements EthereumWalletInterface { + readonly interfaceType = WalletInterfaceType.Ethereum; + + /** + * Signs a message using the specified wallet provider. + * + * @param message - The message to be signed, as a string or hex. + * @param provider - The wallet provider to use for signing. + * @param intent - The intent of the signature (e.g. message signing or transaction sending). + * @returns A promise resolving to a hex-encoded signature string. + */ + abstract sign( + payload: string | Hex, + provider: WalletProvider, + intent: SignIntent, + ): Promise; + + /** + * Retrieves the compressed secp256k1 public key by signing a known message. + * + * - Signs the fixed string "GET_PUBLIC_KEY" (EIP-191) and recovers the key. + * - Returns the compressed public key as a hex string (no 0x prefix). + * + * @param provider - The wallet provider to use. + * @returns A promise that resolves to the compressed public key (hex-encoded). + */ + getPublicKey = async (provider: WalletProvider): Promise => { + const message = "GET_PUBLIC_KEY"; + const signature = await this.sign( + message, + provider, + SignIntent.SignMessage, + ); + return getCompressedPublicKey(signature, message); + }; + + /** + * Discovers EIP-1193 providers using the EIP-6963 standard. + * + * - Dispatches "eip6963:requestProvider" and listens for "eip6963:announceProvider". + * - For each discovered provider, attempts to read `eth_accounts` and `eth_chainId` + * (silently ignored if unavailable), defaulting to chainId "0x1". + * - Returns providers discovered during this discovery cycle; may be empty. + * + * @returns A promise that resolves to a list of available wallet providers. + */ + getProviders = async (): Promise => { + const discovered: WalletProvider[] = []; + + type AnnounceEvent = CustomEvent<{ + info: WalletProviderInfo; + provider: WalletRpcProvider; + }>; + + const providerPromises: Promise[] = []; + + const handler = (ev: AnnounceEvent): void => { + const { provider, info } = ev.detail; + + const promise = (async () => { + let connectedAddresses: string[] = []; + + // we default to Ethereum mainnet + let chainId = "0x1"; + + try { + const accounts = await (provider as any).request?.({ + method: "eth_accounts", + }); + if (Array.isArray(accounts)) connectedAddresses = accounts; + + chainId = await (provider as any).request({ + method: "eth_chainId", + }); + } catch { + // fail silently + } + + discovered.push({ + interfaceType: WalletInterfaceType.Ethereum, + chainInfo: { + namespace: Chain.Ethereum, + chainId, + }, + info, + provider, + connectedAddresses, + }); + })(); + + providerPromises.push(promise); + }; + + window.addEventListener( + "eip6963:announceProvider", + handler as EventListener, + ); + window.dispatchEvent(new Event("eip6963:requestProvider")); + window.removeEventListener( + "eip6963:announceProvider", + handler as EventListener, + ); + + await Promise.all(providerPromises); + return discovered; + }; + + /** + * Requests or verifies account connection via `eth_requestAccounts`. + * + * - If the wallet is already connected, resolves immediately (no prompt). + * - If not connected, the wallet will typically prompt the user to authorize. + * + * @param provider - The wallet provider to use. + * @returns A promise that resolves once at least one account is connected. + * @throws {Error} If the wallet returns no accounts after the request. + */ + connectWalletAccount = async (provider: WalletProvider): Promise => { + const wallet = asEip1193(provider); + await getAccount(wallet); + }; + + /** + * Attempts to disconnect the wallet by revoking `eth_accounts` permission. + * + * - Calls `wallet_revokePermissions` with `{ eth_accounts: {} }`. + * - Provider behavior is wallet-specific: some implement it, some ignore it, + * and others (e.g., Phantom) throw β€œmethod not supported”. + * + * @param provider - The wallet provider to disconnect. + * @returns A promise that resolves once the request completes (or rejects if the provider errors). + */ + disconnectWalletAccount = async (provider: WalletProvider): Promise => { + const wallet = asEip1193(provider); + await wallet.request({ + method: "wallet_revokePermissions", + params: [{ eth_accounts: {} }], + }); + }; + + /** + * Switches to a new EVM chain, with add-then-switch fallback. + * + * - Tries `wallet_switchEthereumChain` first. + * - If the wallet returns error code 4902 (unknown chain): + * - If `chainOrId` is a string (hex chainId), throws and asks the caller to pass metadata. + * - If `chainOrId` is a `SwitchableChain`, calls `wallet_addEthereumChain` and then retries the switch. + * + * @param provider - The wallet provider to use. + * @param chainOrId - Hex chain ID string or full `SwitchableChain` metadata. + * @throws {Error} If provider is non-EVM, adding/switching fails, or metadata is missing. + */ + async switchChain( + provider: WalletProvider, + chainOrId: string | SwitchableChain, + ): Promise { + if (provider.chainInfo.namespace !== Chain.Ethereum) { + throw new Error("Only EVM wallets can switch chains"); + } + + const wallet = asEip1193(provider); + const chainId = typeof chainOrId === "string" ? chainOrId : chainOrId.id; + + try { + // first we just try switching + await wallet.request({ + method: "wallet_switchEthereumChain", + params: [{ chainId }], + }); + } catch (err: any) { + // if the error is not β€œchain not found” + // we just re-throw it + if (err.code !== 4902) { + throw err; + } + + // no metadata was provided so we throw an error + // telling them to pass it in + if (typeof chainOrId === "string") { + throw new Error( + `Chain ${chainId} not recognized. ` + + `If you want to add it, call switchChain with a SwitchableChain object.`, + ); + } + + // we have full metadata and can add the chain and switch + const { name, rpcUrls, blockExplorerUrls, iconUrls, nativeCurrency } = + chainOrId; + + // add the chain + await wallet.request({ + method: "wallet_addEthereumChain", + params: [ + { + chainId, + chainName: name, + rpcUrls, + blockExplorerUrls, + iconUrls, + nativeCurrency, + }, + ], + }); + + // then switch again + await wallet.request({ + method: "wallet_switchEthereumChain", + params: [{ chainId }], + }); + } + } +} + +/** + * EthereumWallet implementation using EIP-1193 compatible providers. + * + * Handles message signing and transaction submission. + */ +export class EthereumWallet extends BaseEthereumWallet { + /** + * Signs a message or sends a transaction depending on intent. + * + * - `SignMessage` β†’ `personal_sign` (hex signature). + * - `SignAndSendTransaction` β†’ `eth_sendTransaction` (tx hash). + * - For transactions, `message` must be a raw tx that `Transaction.from(...)` can parse. + * - May prompt the user (account access, signing, or send). + * + * @param payload - The payload or raw transaction to be signed/sent. + * @param provider - The wallet provider to use. + * @param intent - Signing intent (SignMessage or SignAndSendTransaction). + * @returns A promise that resolves to a hex string (signature or tx hash). + * @throws {Error} If the intent is unsupported or the wallet rejects the request. + */ + sign = async ( + payload: string, + provider: WalletProvider, + intent: SignIntent, + ): Promise => { + const selectedProvider = asEip1193(provider); + const account = await getAccount(selectedProvider); + + switch (intent) { + case SignIntent.SignMessage: + return await selectedProvider.request({ + method: "personal_sign", + params: [payload as Hex, account], + }); + + case SignIntent.SignAndSendTransaction: + const tx = Transaction.from(payload); + const txParams = { + from: account, + to: tx.to?.toString() as Hex, + value: toHex(tx.value), + gas: toHex(tx.gasLimit), + maxFeePerGas: toHex(tx.maxFeePerGas ?? 0n), + maxPriorityFeePerGas: toHex(tx.maxPriorityFeePerGas ?? 0n), + nonce: toHex(tx.nonce), + chainId: toHex(tx.chainId), + data: (tx.data?.toString() as Hex) ?? "0x", + }; + + return await selectedProvider.request({ + method: "eth_sendTransaction", + params: [txParams], + }); + + default: + throw new Error(`Unsupported sign intent: ${intent}`); + } + }; +} + +/** + * Retrieves the active Ethereum account from a provider. + * + * - Calls `eth_requestAccounts` (usually no prompt). + * + * @param provider - EIP-1193 compliant provider. + * @returns A promise resolving to the connected Ethereum address. + * @throws {Error} If no connected account is found. + */ +const getAccount = async (provider: EIP1193Provider): Promise
=> { + const [connectedAccount] = await provider.request({ + method: "eth_requestAccounts", + }); + if (!connectedAccount) throw new Error("No connected account found"); + return connectedAccount; +}; + +/** + * Recovers and compresses the public key from a signed message. + * + * - Recovers the secp256k1 public key from an EIP-191 signature and compresses it. + * - Returns a hex string with no 0x prefix. + * + * @param signature - The signature as a hex string. + * @param message - The original signed message. + * @returns A promise resolving to the compressed public key (hex-encoded). + */ +const getCompressedPublicKey = async ( + signature: string, + message: string, +): Promise => { + const secp256k1PublicKey = await recoverPublicKey({ + hash: hashMessage(message), + signature: signature as Hex, + }); + const publicKeyHex = secp256k1PublicKey.startsWith("0x") + ? secp256k1PublicKey.slice(2) + : secp256k1PublicKey; + + const publicKeyBytes = uint8ArrayFromHexString(publicKeyHex); + const publicKeyBytesCompressed = compressRawPublicKey(publicKeyBytes); + + return uint8ArrayToHexString(publicKeyBytesCompressed); +}; + +/** + * Validates and casts a `WalletProvider` to an EIP-1193 provider. + * + * - Expects `provider.request` to be a function. + * + * @param p - The wallet provider to validate. + * @returns An EIP-1193 provider. + * @throws {Error} If the provider does not implement `request()`. + */ +const asEip1193 = (p: WalletProvider): EIP1193Provider => { + if (p.provider && typeof (p.provider as any).request === "function") { + return p.provider as EIP1193Provider; + } + throw new Error("Expected an EIP-1193 provider (Ethereum wallet)"); +}; diff --git a/packages/core/src/__wallet__/web/native/solana.ts b/packages/core/src/__wallet__/web/native/solana.ts new file mode 100644 index 000000000..05a90870d --- /dev/null +++ b/packages/core/src/__wallet__/web/native/solana.ts @@ -0,0 +1,263 @@ +import type { Wallet as SWSWallet } from "@wallet-standard/base"; +import { getWallets } from "@wallet-standard/app"; +import bs58 from "bs58"; + +import { + uint8ArrayFromHexString, + uint8ArrayToHexString, +} from "@turnkey/encoding"; +import { + Chain, + SignIntent, + SolanaWalletInterface, + WalletInterfaceType, + WalletProvider, + WalletRpcProvider, +} from "@types"; + +/** + * Abstract base class for Solana wallet implementations using Wallet Standard. + * + * Provides shared logic for: + * - Provider discovery via `@wallet-standard/app` (`getWallets()`). + * - Connecting via `standard:connect` and disconnecting via `standard:disconnect`. + * - Public key retrieval from the wallet's account address (base58 β†’ hex). + */ +export abstract class BaseSolanaWallet implements SolanaWalletInterface { + readonly interfaceType = WalletInterfaceType.Solana; + + abstract sign( + message: string | Uint8Array, + provider: WalletProvider, + intent: SignIntent, + ): Promise; + + /** + * Retrieves the ed25519 public key for the active account as hex (no 0x prefix). + * + * - Ensures the wallet is connected (calls `standard:connect` if needed). + * - Decodes the Wallet Standard account address (base58) to raw bytes. + * + * @param provider - The wallet provider to use. + * @returns Hex-encoded ed25519 public key (no 0x prefix). + * @throws {Error} If no account is available. + */ + getPublicKey = async (provider: WalletProvider): Promise => { + const wallet = asSolana(provider); + await connectAccount(wallet); + const account = wallet.accounts[0]; + if (!account) { + throw new Error("No account in wallet"); + } + const rawBytes = bs58.decode(account.address); + return uint8ArrayToHexString(rawBytes); + }; + + /** + * Discovers Solana-capable Wallet Standard providers. + * + * - Uses `getWallets().get()` and filters wallets with at least one `chains` entry + * starting with `"solana:"`. + * - For each wallet, collects branding info and any currently connected addresses. + * + * @returns A list of discovered Solana `WalletProvider`s (may be empty). + */ + getProviders = async (): Promise => { + const discovered: WalletProvider[] = []; + const walletsApi = getWallets(); + const providers = walletsApi + .get() + .filter((w) => w.chains.some((c) => c.startsWith("solana:"))); + + await Promise.all( + providers.map(async (wallet) => { + let connectedAddresses: string[] = []; + try { + connectedAddresses = + wallet.accounts?.map((a: any) => a.address) ?? []; + } catch { + connectedAddresses = []; + } + + discovered.push({ + interfaceType: WalletInterfaceType.Solana, + chainInfo: { + namespace: Chain.Solana, + }, + info: { name: wallet.name, icon: wallet.icon }, + provider: wallet as WalletRpcProvider, + connectedAddresses, + }); + }), + ); + + return discovered; + }; + + /** + * Connects the wallet account, prompting the user if necessary. + * + * - Calls `standard:connect` only if no accounts are present. This will prompt the user to connect their wallet. + * + * @param provider - The wallet provider to connect. + * @returns A promise that resolves once the wallet has β‰₯ 1 account. + * @throws {Error} If the wallet does not implement `standard:connect`. + */ + connectWalletAccount = async (provider: WalletProvider): Promise => { + const wallet = asSolana(provider); + await connectAccount(wallet); + }; + + /** + * Disconnects the wallet account using Wallet Standard. + * + * - Calls `standard:disconnect` if implemented. + * - Throws if the wallet does not implement `standard:disconnect`. + * + * @param provider - The wallet provider to disconnect. + * @returns A promise that resolves once the wallet disconnects. + * @throws {Error} If `standard:disconnect` is not supported by the wallet. + */ + disconnectWalletAccount = async (provider: WalletProvider): Promise => { + const wallet = asSolana(provider); + const disconnectFeature = wallet.features["standard:disconnect"] as + | { disconnect: () => Promise } + | undefined; + if (disconnectFeature) { + await disconnectFeature.disconnect(); + } else { + throw new Error("Wallet does not support standard:disconnect"); + } + }; +} + +/** + * Signs a message or transaction with the connected Solana wallet. + * + * - Ensures the wallet is connected (may prompt via `standard:connect` if its not). + * - `SignMessage` β†’ `solana:signMessage` (returns hex signature). + * - `SignTransaction` β†’ `solana:signTransaction` (returns hex signature). + * + * @param payload - UTF-8 string (for message) or hex string (for transaction bytes). + * @param provider - The wallet provider to use. + * @param intent - The signing intent. + * @returns Hex-encoded signature (no 0x prefix). + * @throws {Error} If the provider lacks required features or intent is unsupported. + */ +export class SolanaWallet extends BaseSolanaWallet { + sign = async ( + payload: string, + provider: WalletProvider, + intent: SignIntent, + ): Promise => { + const wallet = asSolana(provider); + await connectAccount(wallet); + const account = wallet.accounts[0]; + if (!account) throw new Error("No account available"); + + switch (intent) { + case SignIntent.SignMessage: { + const signFeature = wallet.features["solana:signMessage"] as + | { + signMessage: (args: { + account: typeof account; + message: Uint8Array; + }) => Promise< + readonly { signedMessage: Uint8Array; signature: Uint8Array }[] + >; + } + | undefined; + + if (!signFeature) + throw new Error("Provider does not support solana:signMessage"); + + const data = new TextEncoder().encode(payload); + const results = await signFeature.signMessage({ + account, + message: data, + }); + if (!results?.length || !results[0]?.signature) { + throw new Error("No signature returned from signMessage"); + } + + return uint8ArrayToHexString(results[0].signature); + } + + case SignIntent.SignTransaction: { + const signFeature = wallet.features["solana:signTransaction"] as + | { + signTransaction: (args: { + account: typeof account; + transaction: Uint8Array; + }) => Promise; + } + | undefined; + + if (!signFeature) + throw new Error("Provider does not support solana:signTransaction"); + + const data = uint8ArrayFromHexString(payload); + const results = await signFeature.signTransaction({ + account, + transaction: data, + }); + if (!results?.length || !results[0]?.signature) { + throw new Error("No signature returned from signTransaction"); + } + + return uint8ArrayToHexString(results[0].signature); + } + + default: + throw new Error(`Unsupported sign intent: ${intent}`); + } + }; +} + +/** + * Casts a WalletRpcProvider to a Wallet Standard Solana wallet. + * + * - Validates presence of the Wallet Standard `features` map and `solana:signMessage`. + * - Use this before calling Solana-specific features (signMessage, signTransaction, etc.). + * + * @param provider - The wallet provider to cast. + * @returns The Wallet Standard wallet object. + * @throws {Error} If the provider is not a Wallet Standard Solana wallet. + */ +const asSolana = (provider: WalletProvider): SWSWallet => { + if ( + provider.provider && + "features" in provider.provider && + "solana:signMessage" in (provider.provider as any).features + ) { + return provider.provider as SWSWallet; + } + throw new Error("Expected a Wallet-Standard provider (Solana wallet)"); +}; + +/** + * Ensures the given Wallet Standard wallet has at least one connected account. + * + * - If accounts already exist, resolves immediately. + * - If not, attempts `standard:connect`, which may prompt the user. + * + * @param wallet - The Wallet Standard wallet to connect. + * @returns A promise that resolves once the wallet has β‰₯ 1 account. + * @throws {Error} If the wallet does not implement `standard:connect`. + */ +const connectAccount = async (wallet: SWSWallet): Promise => { + if (wallet.accounts.length) return; + + const stdConnect = wallet.features["standard:connect"] as + | { connect: () => Promise<{ accounts: readonly unknown[] }> } + | undefined; + + if (stdConnect) { + await stdConnect.connect(); + return; + } + + throw new Error( + "Wallet is not connected and does not implement standard:connect", + ); +}; diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts new file mode 100644 index 000000000..de6b9db4c --- /dev/null +++ b/packages/core/src/index.ts @@ -0,0 +1,28 @@ +// marked as internal to prevent inclusion in the core docs +/** @internal */ +export { + ApiKeyStamper, + signWithApiKey, + type TApiKeyStamperConfig, +} from "@turnkey/api-key-stamper"; + +// marked as internal to prevent inclusion in the core docs +/** @internal */ +export { + type TWebauthnStamperConfig, + WebauthnStamper, +} from "@turnkey/webauthn-stamper"; + +export { TurnkeyClient, type TurnkeyClientMethods } from "./__clients__/core"; +export { type TurnkeySDKClientBase } from "./__generated__/sdk-client-base"; + +// Export all types and values from __types__/base +export * from "./__types__/base"; + +export { + generateWalletAccountsFromAddressFormat, + isEthereumWallet, + isSolanaWallet, + getAuthProxyConfig, + addressFormatConfig, +} from "./utils"; diff --git a/packages/core/src/turnkey-helpers.ts b/packages/core/src/turnkey-helpers.ts new file mode 100644 index 000000000..5e4d32fe4 --- /dev/null +++ b/packages/core/src/turnkey-helpers.ts @@ -0,0 +1,534 @@ +import type { v1WalletAccountParams } from "@turnkey/sdk-types"; + +// ---------------------------- +// CURVE_SECP256K1 Accounts +// ---------------------------- + +// Ethereum +export const defaultEthereumAccountAtIndex = ( + pathIndex: number, +): v1WalletAccountParams => { + return { + curve: "CURVE_SECP256K1", + pathFormat: "PATH_FORMAT_BIP32", + path: `m/44'/60'/${pathIndex}'/0/0`, + addressFormat: "ADDRESS_FORMAT_ETHEREUM", + }; +}; + +export const DEFAULT_ETHEREUM_ACCOUNTS: v1WalletAccountParams[] = [ + defaultEthereumAccountAtIndex(0), +]; + +// Cosmos +export const defaultCosmosAccountAtIndex = ( + pathIndex: number, +): v1WalletAccountParams => { + return { + curve: "CURVE_SECP256K1", + pathFormat: "PATH_FORMAT_BIP32", + path: `m/44'/118'/${pathIndex}'/0/0`, + addressFormat: "ADDRESS_FORMAT_COSMOS", + }; +}; + +export const DEFAULT_COSMOS_ACCOUNTS: v1WalletAccountParams[] = [ + defaultCosmosAccountAtIndex(0), +]; + +// Tron +export const defaultTronAccountAtIndex = ( + pathIndex: number, +): v1WalletAccountParams => { + return { + curve: "CURVE_SECP256K1", + pathFormat: "PATH_FORMAT_BIP32", + path: `m/44'/195'/${pathIndex}'`, + addressFormat: "ADDRESS_FORMAT_TRON", + }; +}; + +export const DEFAULT_TRON_ACCOUNTS: v1WalletAccountParams[] = [ + defaultTronAccountAtIndex(0), +]; + +// Bitcoin Mainnet P2PKH +export const defaultBitcoinMainnetP2PKHAccountAtIndex = ( + pathIndex: number, +): v1WalletAccountParams => { + return { + curve: "CURVE_SECP256K1", + pathFormat: "PATH_FORMAT_BIP32", + path: `m/44'/0'/${pathIndex}'/0/0`, + addressFormat: "ADDRESS_FORMAT_BITCOIN_MAINNET_P2PKH", + }; +}; + +export const DEFAULT_BITCOIN_MAINNET_P2PKH_ACCOUNTS: v1WalletAccountParams[] = [ + defaultBitcoinMainnetP2PKHAccountAtIndex(0), +]; + +// Bitcoin Mainnet P2WPKH +export const defaultBitcoinMainnetP2WPKHAccountAtIndex = ( + pathIndex: number, +): v1WalletAccountParams => { + return { + curve: "CURVE_SECP256K1", + pathFormat: "PATH_FORMAT_BIP32", + path: `m/84'/0'/${pathIndex}'/0/0`, + addressFormat: "ADDRESS_FORMAT_BITCOIN_MAINNET_P2WPKH", + }; +}; + +export const DEFAULT_BITCOIN_MAINNET_P2WPKH_ACCOUNTS: v1WalletAccountParams[] = + [defaultBitcoinMainnetP2WPKHAccountAtIndex(0)]; + +// Bitcoin Mainnet P2WSH +export const defaultBitcoinMainnetP2WSHAccountAtIndex = ( + pathIndex: number, +): v1WalletAccountParams => { + return { + curve: "CURVE_SECP256K1", + pathFormat: "PATH_FORMAT_BIP32", + path: `m/48'/0'/${pathIndex}'/2'/0/0`, + addressFormat: "ADDRESS_FORMAT_BITCOIN_MAINNET_P2WSH", + }; +}; + +export const DEFAULT_BITCOIN_MAINNET_P2WSH_ACCOUNTS: v1WalletAccountParams[] = [ + defaultBitcoinMainnetP2WSHAccountAtIndex(0), +]; + +// Bitcoin Mainnet P2TR +export const defaultBitcoinMainnetP2TRAccountAtIndex = ( + pathIndex: number, +): v1WalletAccountParams => { + return { + curve: "CURVE_SECP256K1", + pathFormat: "PATH_FORMAT_BIP32", + path: `m/86'/0'/${pathIndex}'/0/0`, + addressFormat: "ADDRESS_FORMAT_BITCOIN_MAINNET_P2TR", + }; +}; + +export const DEFAULT_BITCOIN_MAINNET_P2TR_ACCOUNTS: v1WalletAccountParams[] = [ + defaultBitcoinMainnetP2TRAccountAtIndex(0), +]; + +// Bitcoin Mainnet P2SH +export const defaultBitcoinMainnetP2SHAccountAtIndex = ( + pathIndex: number, +): v1WalletAccountParams => { + return { + curve: "CURVE_SECP256K1", + pathFormat: "PATH_FORMAT_BIP32", + path: `m/44'/0'/${pathIndex}'/0/0`, + addressFormat: "ADDRESS_FORMAT_BITCOIN_MAINNET_P2SH", + }; +}; + +export const DEFAULT_BITCOIN_MAINNET_P2SH_ACCOUNTS: v1WalletAccountParams[] = [ + defaultBitcoinMainnetP2SHAccountAtIndex(0), +]; + +// Bitcoin Testnet P2PKH +export const defaultBitcoinTestnetP2PKHAccountAtIndex = ( + pathIndex: number, +): v1WalletAccountParams => { + return { + curve: "CURVE_SECP256K1", + pathFormat: "PATH_FORMAT_BIP32", + path: `m/44'/1'/${pathIndex}'/0/0`, + addressFormat: "ADDRESS_FORMAT_BITCOIN_TESTNET_P2PKH", + }; +}; + +export const DEFAULT_BITCOIN_TESTNET_P2PKH_ACCOUNTS: v1WalletAccountParams[] = [ + defaultBitcoinTestnetP2PKHAccountAtIndex(0), +]; + +// Bitcoin Testnet P2WPKH +export const defaultBitcoinTestnetP2WPKHAccountAtIndex = ( + pathIndex: number, +): v1WalletAccountParams => { + return { + curve: "CURVE_SECP256K1", + pathFormat: "PATH_FORMAT_BIP32", + path: `m/84'/1'/${pathIndex}'/0/0`, + addressFormat: "ADDRESS_FORMAT_BITCOIN_TESTNET_P2WPKH", + }; +}; + +export const DEFAULT_BITCOIN_TESTNET_P2WPKH_ACCOUNTS: v1WalletAccountParams[] = + [defaultBitcoinTestnetP2WPKHAccountAtIndex(0)]; + +// Bitcoin Testnet P2WSH +export const defaultBitcoinTestnetP2WSHAccountAtIndex = ( + pathIndex: number, +): v1WalletAccountParams => { + return { + curve: "CURVE_SECP256K1", + pathFormat: "PATH_FORMAT_BIP32", + path: `m/48'/1'/${pathIndex}'/2'/0/0`, + addressFormat: "ADDRESS_FORMAT_BITCOIN_TESTNET_P2WSH", + }; +}; + +export const DEFAULT_BITCOIN_TESTNET_P2WSH_ACCOUNTS: v1WalletAccountParams[] = [ + defaultBitcoinTestnetP2WSHAccountAtIndex(0), +]; + +// Bitcoin Testnet P2TR +export const defaultBitcoinTestnetP2TRAccountAtIndex = ( + pathIndex: number, +): v1WalletAccountParams => { + return { + curve: "CURVE_SECP256K1", + pathFormat: "PATH_FORMAT_BIP32", + path: `m/86'/1'/${pathIndex}'/0/0`, + addressFormat: "ADDRESS_FORMAT_BITCOIN_TESTNET_P2TR", + }; +}; + +export const DEFAULT_BITCOIN_TESTNET_P2TR_ACCOUNTS: v1WalletAccountParams[] = [ + defaultBitcoinTestnetP2TRAccountAtIndex(0), +]; + +// Bitcoin Testnet P2SH +export const defaultBitcoinTestnetP2SHAccountAtIndex = ( + pathIndex: number, +): v1WalletAccountParams => { + return { + curve: "CURVE_SECP256K1", + pathFormat: "PATH_FORMAT_BIP32", + path: `m/44'/1'/${pathIndex}'/0/0`, + addressFormat: "ADDRESS_FORMAT_BITCOIN_TESTNET_P2SH", + }; +}; + +export const DEFAULT_BITCOIN_TESTNET_P2SH_ACCOUNTS: v1WalletAccountParams[] = [ + defaultBitcoinTestnetP2SHAccountAtIndex(0), +]; + +// Bitcoin Signet P2PKH +export const defaultBitcoinSignetP2PKHAccountAtIndex = ( + pathIndex: number, +): v1WalletAccountParams => { + return { + curve: "CURVE_SECP256K1", + pathFormat: "PATH_FORMAT_BIP32", + path: `m/44'/1'/${pathIndex}'/0/0`, + addressFormat: "ADDRESS_FORMAT_BITCOIN_SIGNET_P2PKH", + }; +}; + +export const DEFAULT_BITCOIN_SIGNET_P2PKH_ACCOUNTS: v1WalletAccountParams[] = [ + defaultBitcoinSignetP2PKHAccountAtIndex(0), +]; + +// Bitcoin Signet P2WPKH +export const defaultBitcoinSignetP2WPKHAccountAtIndex = ( + pathIndex: number, +): v1WalletAccountParams => { + return { + curve: "CURVE_SECP256K1", + pathFormat: "PATH_FORMAT_BIP32", + path: `m/84'/1'/${pathIndex}'/0/0`, + addressFormat: "ADDRESS_FORMAT_BITCOIN_SIGNET_P2WPKH", + }; +}; + +export const DEFAULT_BITCOIN_SIGNET_P2WPKH_ACCOUNTS: v1WalletAccountParams[] = [ + defaultBitcoinSignetP2WPKHAccountAtIndex(0), +]; + +// Bitcoin Signet P2WSH +export const defaultBitcoinSignetP2WSHAccountAtIndex = ( + pathIndex: number, +): v1WalletAccountParams => { + return { + curve: "CURVE_SECP256K1", + pathFormat: "PATH_FORMAT_BIP32", + path: `m/48'/1'/${pathIndex}'/2'/0/0`, + addressFormat: "ADDRESS_FORMAT_BITCOIN_SIGNET_P2WSH", + }; +}; + +export const DEFAULT_BITCOIN_SIGNET_P2WSH_ACCOUNTS: v1WalletAccountParams[] = [ + defaultBitcoinSignetP2WSHAccountAtIndex(0), +]; + +// Bitcoin Signet P2TR +export const defaultBitcoinSignetP2TRAccountAtIndex = ( + pathIndex: number, +): v1WalletAccountParams => { + return { + curve: "CURVE_SECP256K1", + pathFormat: "PATH_FORMAT_BIP32", + path: `m/86'/1'/${pathIndex}'/0/0`, + addressFormat: "ADDRESS_FORMAT_BITCOIN_SIGNET_P2TR", + }; +}; + +export const DEFAULT_BITCOIN_SIGNET_P2TR_ACCOUNTS: v1WalletAccountParams[] = [ + defaultBitcoinSignetP2TRAccountAtIndex(0), +]; + +// Bitcoin Signet P2SH +export const defaultBitcoinSignetP2SHAccountAtIndex = ( + pathIndex: number, +): v1WalletAccountParams => { + return { + curve: "CURVE_SECP256K1", + pathFormat: "PATH_FORMAT_BIP32", + path: `m/44'/1'/${pathIndex}'/0/0`, + addressFormat: "ADDRESS_FORMAT_BITCOIN_SIGNET_P2SH", + }; +}; + +export const DEFAULT_BITCOIN_SIGNET_P2SH_ACCOUNTS: v1WalletAccountParams[] = [ + defaultBitcoinSignetP2SHAccountAtIndex(0), +]; + +// Bitcoin Regtest P2PKH +export const defaultBitcoinRegtestP2PKHAccountAtIndex = ( + pathIndex: number, +): v1WalletAccountParams => { + return { + curve: "CURVE_SECP256K1", + pathFormat: "PATH_FORMAT_BIP32", + path: `m/44'/1'/${pathIndex}'/0/0`, + addressFormat: "ADDRESS_FORMAT_BITCOIN_REGTEST_P2PKH", + }; +}; + +export const DEFAULT_BITCOIN_REGTEST_P2PKH_ACCOUNTS: v1WalletAccountParams[] = [ + defaultBitcoinRegtestP2PKHAccountAtIndex(0), +]; + +// Bitcoin Regtest P2WPKH +export const defaultBitcoinRegtestP2WPKHAccountAtIndex = ( + pathIndex: number, +): v1WalletAccountParams => { + return { + curve: "CURVE_SECP256K1", + pathFormat: "PATH_FORMAT_BIP32", + path: `m/84'/1'/${pathIndex}'/0/0`, + addressFormat: "ADDRESS_FORMAT_BITCOIN_REGTEST_P2WPKH", + }; +}; + +export const DEFAULT_BITCOIN_REGTEST_P2WPKH_ACCOUNTS: v1WalletAccountParams[] = + [defaultBitcoinRegtestP2WPKHAccountAtIndex(0)]; + +// Bitcoin Regtest P2WSH +export const defaultBitcoinRegtestP2WSHAccountAtIndex = ( + pathIndex: number, +): v1WalletAccountParams => { + return { + curve: "CURVE_SECP256K1", + pathFormat: "PATH_FORMAT_BIP32", + path: `m/48'/1'/${pathIndex}'/2'/0/0`, + addressFormat: "ADDRESS_FORMAT_BITCOIN_REGTEST_P2WSH", + }; +}; + +export const DEFAULT_BITCOIN_REGTEST_P2WSH_ACCOUNTS: v1WalletAccountParams[] = [ + defaultBitcoinRegtestP2WSHAccountAtIndex(0), +]; + +// Bitcoin Regtest P2TR +export const defaultBitcoinRegtestP2TRAccountAtIndex = ( + pathIndex: number, +): v1WalletAccountParams => { + return { + curve: "CURVE_SECP256K1", + pathFormat: "PATH_FORMAT_BIP32", + path: `m/86'/1'/${pathIndex}'/0/0`, + addressFormat: "ADDRESS_FORMAT_BITCOIN_REGTEST_P2TR", + }; +}; + +export const DEFAULT_BITCOIN_REGTEST_P2TR_ACCOUNTS: v1WalletAccountParams[] = [ + defaultBitcoinRegtestP2TRAccountAtIndex(0), +]; + +// Bitcoin Regtest P2SH +export const defaultBitcoinRegtestP2SHAccountAtIndex = ( + pathIndex: number, +): v1WalletAccountParams => { + return { + curve: "CURVE_SECP256K1", + pathFormat: "PATH_FORMAT_BIP32", + path: `m/44'/1'/${pathIndex}'/0/0`, + addressFormat: "ADDRESS_FORMAT_BITCOIN_REGTEST_P2SH", + }; +}; + +export const DEFAULT_BITCOIN_REGTEST_P2SH_ACCOUNTS: v1WalletAccountParams[] = [ + defaultBitcoinRegtestP2SHAccountAtIndex(0), +]; + +// Dogecoin Mainnet +export const defaultDogeMainnetAccountAtIndex = ( + pathIndex: number, +): v1WalletAccountParams => { + return { + curve: "CURVE_SECP256K1", + pathFormat: "PATH_FORMAT_BIP32", + path: `m/44'/3'/${pathIndex}'/0/0`, + addressFormat: "ADDRESS_FORMAT_DOGE_MAINNET", + }; +}; + +export const DEFAULT_DOGE_MAINNET_ACCOUNTS: v1WalletAccountParams[] = [ + defaultDogeMainnetAccountAtIndex(0), +]; + +// Dogecoin Testnet +export const defaultDogeTestnetAccountAtIndex = ( + pathIndex: number, +): v1WalletAccountParams => { + return { + curve: "CURVE_SECP256K1", + pathFormat: "PATH_FORMAT_BIP32", + path: `m/44'/3'/${pathIndex}'/0/0`, + addressFormat: "ADDRESS_FORMAT_DOGE_TESTNET", + }; +}; + +export const DEFAULT_DOGE_TESTNET_ACCOUNTS: v1WalletAccountParams[] = [ + defaultDogeTestnetAccountAtIndex(0), +]; + +// Sei +export const defaultSeiAccountAtIndex = ( + pathIndex: number, +): v1WalletAccountParams => { + return { + curve: "CURVE_SECP256K1", + pathFormat: "PATH_FORMAT_BIP32", + path: `m/44'/118'/${pathIndex}'/0'/0'`, + addressFormat: "ADDRESS_FORMAT_SEI", + }; +}; + +export const DEFAULT_SEI_ACCOUNTS: v1WalletAccountParams[] = [ + defaultSeiAccountAtIndex(0), +]; + +// Xrp +export const defaultXrpAccountAtIndex = ( + pathIndex: number, +): v1WalletAccountParams => { + return { + curve: "CURVE_SECP256K1", + pathFormat: "PATH_FORMAT_BIP32", + path: `m/44'/144'/${pathIndex}'/0'/0'`, + addressFormat: "ADDRESS_FORMAT_XRP", + }; +}; + +export const DEFAULT_XRP_ACCOUNTS: v1WalletAccountParams[] = [ + defaultXrpAccountAtIndex(0), +]; + +// ---------------------------- +// CURVE_ED25519 Accounts +// ---------------------------- + +// Solana +export const defaultSolanaAccountAtIndex = ( + pathIndex: number, +): v1WalletAccountParams => { + return { + curve: "CURVE_ED25519", + pathFormat: "PATH_FORMAT_BIP32", + path: `m/44'/501'/${pathIndex}'/0'`, + addressFormat: "ADDRESS_FORMAT_SOLANA", + }; +}; + +export const DEFAULT_SOLANA_ACCOUNTS: v1WalletAccountParams[] = [ + defaultSolanaAccountAtIndex(0), +]; + +// SUI +export const defaultSuiAccountAtIndex = ( + pathIndex: number, +): v1WalletAccountParams => { + return { + curve: "CURVE_ED25519", + pathFormat: "PATH_FORMAT_BIP32", + path: `m/44'/784'/${pathIndex}'/0'/0'`, + addressFormat: "ADDRESS_FORMAT_SUI", + }; +}; + +export const DEFAULT_SUI_ACCOUNTS: v1WalletAccountParams[] = [ + defaultSuiAccountAtIndex(0), +]; + +// Aptos +export const defaultAptosAccountAtIndex = ( + pathIndex: number, +): v1WalletAccountParams => { + return { + curve: "CURVE_ED25519", + pathFormat: "PATH_FORMAT_BIP32", + path: `m/44'/637'/${pathIndex}'/0'/0'`, + addressFormat: "ADDRESS_FORMAT_APTOS", + }; +}; + +export const DEFAULT_APTOS_ACCOUNTS: v1WalletAccountParams[] = [ + defaultAptosAccountAtIndex(0), +]; + +// Stellar (XLM) +export const defaultXlmAccountAtIndex = ( + pathIndex: number, +): v1WalletAccountParams => { + return { + curve: "CURVE_ED25519", + pathFormat: "PATH_FORMAT_BIP32", + path: `m/44'/148'/${pathIndex}'`, + addressFormat: "ADDRESS_FORMAT_XLM", + }; +}; + +export const DEFAULT_XLM_ACCOUNTS: v1WalletAccountParams[] = [ + defaultXlmAccountAtIndex(0), +]; + +// TON V3R2 +export const defaultTonV3r2AccountAtIndex = ( + pathIndex: number, +): v1WalletAccountParams => { + return { + curve: "CURVE_ED25519", + pathFormat: "PATH_FORMAT_BIP32", + path: `m/44'/607'/${pathIndex}'/0'/0'`, + addressFormat: "ADDRESS_FORMAT_TON_V3R2", + }; +}; + +export const DEFAULT_TON_V3R2_ACCOUNTS: v1WalletAccountParams[] = [ + defaultTonV3r2AccountAtIndex(0), +]; + +// TON V4R2 +export const defaultTonV4r2AccountAtIndex = ( + pathIndex: number, +): v1WalletAccountParams => { + return { + curve: "CURVE_ED25519", + pathFormat: "PATH_FORMAT_BIP32", + path: `m/44'/607'/${pathIndex}'/0'/0'`, + addressFormat: "ADDRESS_FORMAT_TON_V4R2", + }; +}; + +export const DEFAULT_TON_V4R2_ACCOUNTS: v1WalletAccountParams[] = [ + defaultTonV4r2AccountAtIndex(0), +]; diff --git a/packages/core/src/utils.ts b/packages/core/src/utils.ts new file mode 100644 index 000000000..280ae55f1 --- /dev/null +++ b/packages/core/src/utils.ts @@ -0,0 +1,893 @@ +import { + type v1AddressFormat, + type v1HashFunction, + type v1PayloadEncoding, + type Session, + type externaldatav1Timestamp, + type ProxyTSignupBody, + type v1ApiKeyParamsV2, + type v1ApiKeyCurve, + type v1AuthenticatorParamsV2, + type v1WalletAccountParams, + type v1WalletAccount, + TurnkeyError, + TurnkeyErrorCodes, + v1SignRawPayloadResult, + v1TransactionType, + ProxyTGetWalletKitConfigResponse, +} from "@turnkey/sdk-types"; +import { + type CreateSubOrgParams, + SignIntent, + type WalletProvider, + Chain, + GrpcStatus, + TurnkeyRequestError, +} from "@types"; +// Import all defaultAccountAtIndex functions for each address format +import { + DEFAULT_ETHEREUM_ACCOUNTS, + DEFAULT_COSMOS_ACCOUNTS, + DEFAULT_TRON_ACCOUNTS, + DEFAULT_BITCOIN_MAINNET_P2PKH_ACCOUNTS, + DEFAULT_BITCOIN_MAINNET_P2SH_ACCOUNTS, + DEFAULT_BITCOIN_MAINNET_P2WPKH_ACCOUNTS, + DEFAULT_BITCOIN_MAINNET_P2WSH_ACCOUNTS, + DEFAULT_BITCOIN_MAINNET_P2TR_ACCOUNTS, + DEFAULT_BITCOIN_TESTNET_P2PKH_ACCOUNTS, + DEFAULT_BITCOIN_TESTNET_P2SH_ACCOUNTS, + DEFAULT_BITCOIN_TESTNET_P2WPKH_ACCOUNTS, + DEFAULT_BITCOIN_TESTNET_P2WSH_ACCOUNTS, + DEFAULT_BITCOIN_TESTNET_P2TR_ACCOUNTS, + DEFAULT_BITCOIN_SIGNET_P2PKH_ACCOUNTS, + DEFAULT_BITCOIN_SIGNET_P2SH_ACCOUNTS, + DEFAULT_BITCOIN_SIGNET_P2WPKH_ACCOUNTS, + DEFAULT_BITCOIN_SIGNET_P2WSH_ACCOUNTS, + DEFAULT_BITCOIN_SIGNET_P2TR_ACCOUNTS, + DEFAULT_BITCOIN_REGTEST_P2PKH_ACCOUNTS, + DEFAULT_BITCOIN_REGTEST_P2SH_ACCOUNTS, + DEFAULT_BITCOIN_REGTEST_P2WPKH_ACCOUNTS, + DEFAULT_BITCOIN_REGTEST_P2WSH_ACCOUNTS, + DEFAULT_BITCOIN_REGTEST_P2TR_ACCOUNTS, + DEFAULT_DOGE_MAINNET_ACCOUNTS, + DEFAULT_DOGE_TESTNET_ACCOUNTS, + DEFAULT_SEI_ACCOUNTS, + DEFAULT_XRP_ACCOUNTS, + DEFAULT_SOLANA_ACCOUNTS, + DEFAULT_SUI_ACCOUNTS, + DEFAULT_APTOS_ACCOUNTS, + DEFAULT_XLM_ACCOUNTS, + DEFAULT_TON_V3R2_ACCOUNTS, + DEFAULT_TON_V4R2_ACCOUNTS, +} from "./turnkey-helpers"; +import { fromDerSignature } from "@turnkey/crypto"; +import { + decodeBase64urlToString, + uint8ArrayToHexString, +} from "@turnkey/encoding"; + +type AddressFormatConfig = { + encoding: v1PayloadEncoding; + hashFunction: v1HashFunction; + defaultAccounts: v1WalletAccountParams[] | null; + displayName: string; +}; + +export const addressFormatConfig: Record = + { + ADDRESS_FORMAT_UNCOMPRESSED: { + encoding: "PAYLOAD_ENCODING_HEXADECIMAL", + hashFunction: "HASH_FUNCTION_SHA256", + defaultAccounts: null, + displayName: "Uncompressed", + }, + ADDRESS_FORMAT_COMPRESSED: { + encoding: "PAYLOAD_ENCODING_HEXADECIMAL", + hashFunction: "HASH_FUNCTION_SHA256", + defaultAccounts: null, + displayName: "Compressed", + }, + ADDRESS_FORMAT_ETHEREUM: { + encoding: "PAYLOAD_ENCODING_HEXADECIMAL", + hashFunction: "HASH_FUNCTION_KECCAK256", + defaultAccounts: DEFAULT_ETHEREUM_ACCOUNTS, + displayName: "Ethereum", + }, + ADDRESS_FORMAT_SOLANA: { + encoding: "PAYLOAD_ENCODING_HEXADECIMAL", + hashFunction: "HASH_FUNCTION_NOT_APPLICABLE", + defaultAccounts: DEFAULT_SOLANA_ACCOUNTS, + displayName: "Solana", + }, + ADDRESS_FORMAT_COSMOS: { + encoding: "PAYLOAD_ENCODING_TEXT_UTF8", + hashFunction: "HASH_FUNCTION_SHA256", + defaultAccounts: DEFAULT_COSMOS_ACCOUNTS, + displayName: "Cosmos", + }, + ADDRESS_FORMAT_TRON: { + encoding: "PAYLOAD_ENCODING_HEXADECIMAL", + hashFunction: "HASH_FUNCTION_SHA256", + defaultAccounts: DEFAULT_TRON_ACCOUNTS, + displayName: "Tron", + }, + ADDRESS_FORMAT_SUI: { + encoding: "PAYLOAD_ENCODING_HEXADECIMAL", + hashFunction: "HASH_FUNCTION_NOT_APPLICABLE", + defaultAccounts: DEFAULT_SUI_ACCOUNTS, + displayName: "Sui", + }, + ADDRESS_FORMAT_APTOS: { + encoding: "PAYLOAD_ENCODING_HEXADECIMAL", + hashFunction: "HASH_FUNCTION_NOT_APPLICABLE", + defaultAccounts: DEFAULT_APTOS_ACCOUNTS, + displayName: "Aptos", + }, + ADDRESS_FORMAT_BITCOIN_MAINNET_P2PKH: { + encoding: "PAYLOAD_ENCODING_HEXADECIMAL", + hashFunction: "HASH_FUNCTION_SHA256", + defaultAccounts: DEFAULT_BITCOIN_MAINNET_P2PKH_ACCOUNTS, + displayName: "Bitcoin Mainnet P2PKH", + }, + ADDRESS_FORMAT_BITCOIN_MAINNET_P2SH: { + encoding: "PAYLOAD_ENCODING_HEXADECIMAL", + hashFunction: "HASH_FUNCTION_SHA256", + defaultAccounts: DEFAULT_BITCOIN_MAINNET_P2SH_ACCOUNTS, + displayName: "Bitcoin Mainnet P2SH", + }, + ADDRESS_FORMAT_BITCOIN_MAINNET_P2WPKH: { + encoding: "PAYLOAD_ENCODING_HEXADECIMAL", + hashFunction: "HASH_FUNCTION_SHA256", + defaultAccounts: DEFAULT_BITCOIN_MAINNET_P2WPKH_ACCOUNTS, + displayName: "Bitcoin Mainnet P2WPKH", + }, + ADDRESS_FORMAT_BITCOIN_MAINNET_P2WSH: { + encoding: "PAYLOAD_ENCODING_HEXADECIMAL", + hashFunction: "HASH_FUNCTION_SHA256", + defaultAccounts: DEFAULT_BITCOIN_MAINNET_P2WSH_ACCOUNTS, + displayName: "Bitcoin Mainnet P2WSH", + }, + ADDRESS_FORMAT_BITCOIN_MAINNET_P2TR: { + encoding: "PAYLOAD_ENCODING_HEXADECIMAL", + hashFunction: "HASH_FUNCTION_SHA256", + defaultAccounts: DEFAULT_BITCOIN_MAINNET_P2TR_ACCOUNTS, + displayName: "Bitcoin Mainnet P2TR", + }, + ADDRESS_FORMAT_BITCOIN_TESTNET_P2PKH: { + encoding: "PAYLOAD_ENCODING_HEXADECIMAL", + hashFunction: "HASH_FUNCTION_SHA256", + defaultAccounts: DEFAULT_BITCOIN_TESTNET_P2PKH_ACCOUNTS, + displayName: "Bitcoin Testnet P2PKH", + }, + ADDRESS_FORMAT_BITCOIN_TESTNET_P2SH: { + encoding: "PAYLOAD_ENCODING_HEXADECIMAL", + hashFunction: "HASH_FUNCTION_SHA256", + defaultAccounts: DEFAULT_BITCOIN_TESTNET_P2SH_ACCOUNTS, + displayName: "Bitcoin Testnet P2SH", + }, + ADDRESS_FORMAT_BITCOIN_TESTNET_P2WPKH: { + encoding: "PAYLOAD_ENCODING_HEXADECIMAL", + hashFunction: "HASH_FUNCTION_SHA256", + defaultAccounts: DEFAULT_BITCOIN_TESTNET_P2WPKH_ACCOUNTS, + displayName: "Bitcoin Testnet P2WPKH", + }, + ADDRESS_FORMAT_BITCOIN_TESTNET_P2WSH: { + encoding: "PAYLOAD_ENCODING_HEXADECIMAL", + hashFunction: "HASH_FUNCTION_SHA256", + defaultAccounts: DEFAULT_BITCOIN_TESTNET_P2WSH_ACCOUNTS, + displayName: "Bitcoin Testnet P2WSH", + }, + ADDRESS_FORMAT_BITCOIN_TESTNET_P2TR: { + encoding: "PAYLOAD_ENCODING_HEXADECIMAL", + hashFunction: "HASH_FUNCTION_SHA256", + defaultAccounts: DEFAULT_BITCOIN_TESTNET_P2TR_ACCOUNTS, + displayName: "Bitcoin Testnet P2TR", + }, + ADDRESS_FORMAT_BITCOIN_SIGNET_P2PKH: { + encoding: "PAYLOAD_ENCODING_HEXADECIMAL", + hashFunction: "HASH_FUNCTION_SHA256", + defaultAccounts: DEFAULT_BITCOIN_SIGNET_P2PKH_ACCOUNTS, + displayName: "Bitcoin Signet P2PKH", + }, + ADDRESS_FORMAT_BITCOIN_SIGNET_P2SH: { + encoding: "PAYLOAD_ENCODING_HEXADECIMAL", + hashFunction: "HASH_FUNCTION_SHA256", + defaultAccounts: DEFAULT_BITCOIN_SIGNET_P2SH_ACCOUNTS, + displayName: "Bitcoin Signet P2SH", + }, + ADDRESS_FORMAT_BITCOIN_SIGNET_P2WPKH: { + encoding: "PAYLOAD_ENCODING_HEXADECIMAL", + hashFunction: "HASH_FUNCTION_SHA256", + defaultAccounts: DEFAULT_BITCOIN_SIGNET_P2WPKH_ACCOUNTS, + displayName: "Bitcoin Signet P2WPKH", + }, + ADDRESS_FORMAT_BITCOIN_SIGNET_P2WSH: { + encoding: "PAYLOAD_ENCODING_HEXADECIMAL", + hashFunction: "HASH_FUNCTION_SHA256", + defaultAccounts: DEFAULT_BITCOIN_SIGNET_P2WSH_ACCOUNTS, + displayName: "Bitcoin Signet P2WSH", + }, + ADDRESS_FORMAT_BITCOIN_SIGNET_P2TR: { + encoding: "PAYLOAD_ENCODING_HEXADECIMAL", + hashFunction: "HASH_FUNCTION_SHA256", + defaultAccounts: DEFAULT_BITCOIN_SIGNET_P2TR_ACCOUNTS, + displayName: "Bitcoin Signet P2TR", + }, + ADDRESS_FORMAT_BITCOIN_REGTEST_P2PKH: { + encoding: "PAYLOAD_ENCODING_HEXADECIMAL", + hashFunction: "HASH_FUNCTION_SHA256", + defaultAccounts: DEFAULT_BITCOIN_REGTEST_P2PKH_ACCOUNTS, + displayName: "Bitcoin Regtest P2PKH", + }, + ADDRESS_FORMAT_BITCOIN_REGTEST_P2SH: { + encoding: "PAYLOAD_ENCODING_HEXADECIMAL", + hashFunction: "HASH_FUNCTION_SHA256", + defaultAccounts: DEFAULT_BITCOIN_REGTEST_P2SH_ACCOUNTS, + displayName: "Bitcoin Regtest P2SH", + }, + ADDRESS_FORMAT_BITCOIN_REGTEST_P2WPKH: { + encoding: "PAYLOAD_ENCODING_HEXADECIMAL", + hashFunction: "HASH_FUNCTION_SHA256", + defaultAccounts: DEFAULT_BITCOIN_REGTEST_P2WPKH_ACCOUNTS, + displayName: "Bitcoin Regtest P2WPKH", + }, + ADDRESS_FORMAT_BITCOIN_REGTEST_P2WSH: { + encoding: "PAYLOAD_ENCODING_HEXADECIMAL", + hashFunction: "HASH_FUNCTION_SHA256", + defaultAccounts: DEFAULT_BITCOIN_REGTEST_P2WSH_ACCOUNTS, + displayName: "Bitcoin Regtest P2WSH", + }, + ADDRESS_FORMAT_BITCOIN_REGTEST_P2TR: { + encoding: "PAYLOAD_ENCODING_HEXADECIMAL", + hashFunction: "HASH_FUNCTION_SHA256", + defaultAccounts: DEFAULT_BITCOIN_REGTEST_P2TR_ACCOUNTS, + displayName: "Bitcoin Regtest P2TR", + }, + ADDRESS_FORMAT_SEI: { + encoding: "PAYLOAD_ENCODING_TEXT_UTF8", + hashFunction: "HASH_FUNCTION_SHA256", + defaultAccounts: DEFAULT_SEI_ACCOUNTS, + displayName: "Sei", + }, + ADDRESS_FORMAT_XLM: { + encoding: "PAYLOAD_ENCODING_HEXADECIMAL", + hashFunction: "HASH_FUNCTION_NOT_APPLICABLE", + defaultAccounts: DEFAULT_XLM_ACCOUNTS, + displayName: "Xlm", + }, + ADDRESS_FORMAT_DOGE_MAINNET: { + encoding: "PAYLOAD_ENCODING_HEXADECIMAL", + hashFunction: "HASH_FUNCTION_SHA256", + defaultAccounts: DEFAULT_DOGE_MAINNET_ACCOUNTS, + displayName: "Doge Mainnet", + }, + ADDRESS_FORMAT_DOGE_TESTNET: { + encoding: "PAYLOAD_ENCODING_HEXADECIMAL", + hashFunction: "HASH_FUNCTION_SHA256", + defaultAccounts: DEFAULT_DOGE_TESTNET_ACCOUNTS, + displayName: "Doge Testnet", + }, + ADDRESS_FORMAT_TON_V3R2: { + encoding: "PAYLOAD_ENCODING_HEXADECIMAL", + hashFunction: "HASH_FUNCTION_NOT_APPLICABLE", + defaultAccounts: DEFAULT_TON_V3R2_ACCOUNTS, + displayName: "Ton V3R2", + }, + ADDRESS_FORMAT_TON_V4R2: { + encoding: "PAYLOAD_ENCODING_HEXADECIMAL", + hashFunction: "HASH_FUNCTION_NOT_APPLICABLE", + defaultAccounts: DEFAULT_TON_V4R2_ACCOUNTS, + displayName: "Ton V4R2", + }, + ADDRESS_FORMAT_TON_V5R1: { + encoding: "PAYLOAD_ENCODING_HEXADECIMAL", + hashFunction: "HASH_FUNCTION_NOT_APPLICABLE", + defaultAccounts: null, + displayName: "Ton V5R1", + }, + ADDRESS_FORMAT_XRP: { + encoding: "PAYLOAD_ENCODING_HEXADECIMAL", + hashFunction: "HASH_FUNCTION_SHA256", + defaultAccounts: DEFAULT_XRP_ACCOUNTS, + displayName: "XRP", + }, + }; + +export const googleISS = "https://accounts.google.com"; + +export const isReactNative = (): boolean => { + return ( + typeof navigator !== "undefined" && navigator.product === "ReactNative" + ); +}; + +export const isWeb = (): boolean => { + return typeof window !== "undefined" && typeof document !== "undefined"; +}; + +export const generateRandomBuffer = (): ArrayBuffer => { + const arr = new Uint8Array(32); + crypto.getRandomValues(arr); + return arr.buffer; +}; + +const hexByByte = Array.from({ length: 256 }, (_, i) => + i.toString(16).padStart(2, "0"), +); + +export const bytesToHex = (bytes: Uint8Array): string => { + let hex = "0x"; + if (bytes === undefined || bytes.length === 0) return hex; + for (const byte of bytes) { + hex += hexByByte[byte]; + } + return hex; +}; + +export const toExternalTimestamp = ( + date: Date = new Date(), +): externaldatav1Timestamp => { + const millis = date.getTime(); + const seconds = Math.floor(millis / 1000); + const nanos = (millis % 1000) * 1_000_000; + + return { + seconds: seconds.toString(), + nanos: nanos.toString(), + }; +}; + +export function parseSession(token: string | Session): Session { + if (typeof token !== "string") { + return token; + } + const [, payload] = token.split("."); + if (!payload) { + throw new Error("Invalid JWT: Missing payload"); + } + + const decoded = JSON.parse(atob(payload)); + const { + exp, + public_key: publicKey, + session_type: sessionType, + user_id: userId, + organization_id: organizationId, + } = decoded; + + if (!exp || !publicKey || !sessionType || !userId || !organizationId) { + throw new Error("JWT payload missing required fields"); + } + + const expSeconds = Math.ceil((exp * 1000 - Date.now()) / 1000); + + return { + sessionType, + userId, + organizationId, + expiry: exp, + expirationSeconds: expSeconds.toString(), + publicKey, + token, + }; +} + +export function getHashFunction(addressFormat: v1AddressFormat) { + const config = addressFormatConfig[addressFormat]; + if (!config) { + throw new TurnkeyError( + `Unsupported address format: ${addressFormat}`, + TurnkeyErrorCodes.INVALID_REQUEST, + ); + } + return config.hashFunction; +} + +export function getEncodingType(addressFormat: v1AddressFormat) { + const config = addressFormatConfig[addressFormat]; + if (!config) { + throw new TurnkeyError( + `Unsupported address format: ${addressFormat}`, + TurnkeyErrorCodes.INVALID_REQUEST, + ); + } + return config.encoding; +} + +export function getEncodedMessage( + addressFormat: v1AddressFormat, + rawMessage: string, +): string { + const config = addressFormatConfig[addressFormat]; + if (!config) { + throw new TurnkeyError( + `Unsupported address format: ${addressFormat}`, + TurnkeyErrorCodes.INVALID_REQUEST, + ); + } + if (config.encoding === "PAYLOAD_ENCODING_HEXADECIMAL") { + return ("0x" + + Array.from(new TextEncoder().encode(rawMessage)) + .map((b) => b.toString(16).padStart(2, "0")) + .join("")) as string; + } + return rawMessage; +} + +export const broadcastTransaction = async (params: { + signedTransaction: string; + rpcUrl: string; + transactionType: v1TransactionType; +}): Promise => { + const { signedTransaction, rpcUrl, transactionType } = params; + + switch (transactionType) { + case "TRANSACTION_TYPE_SOLANA": { + const response = await fetch(rpcUrl, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: 1, + method: "sendTransaction", + params: [signedTransaction], + }), + }); + + const json = await response.json(); + + if (json.error) { + throw new TurnkeyError( + `Solana RPC Error: ${json.error.message}`, + TurnkeyErrorCodes.SIGN_AND_SEND_TRANSACTION_ERROR, + ); + } + + return json.result; + } + + case "TRANSACTION_TYPE_ETHEREUM": { + const response = await fetch(rpcUrl, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: 1, + method: "eth_sendRawTransaction", + params: [signedTransaction], + }), + }); + + const json = await response.json(); + + if (json.error) { + throw new TurnkeyError( + `Ethereum RPC Error: ${json.error.message}`, + TurnkeyErrorCodes.SIGN_AND_SEND_TRANSACTION_ERROR, + ); + } + + return json.result; + } + + case "TRANSACTION_TYPE_TRON": { + const response = await fetch(`${rpcUrl}/wallet/broadcasthex`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ transaction: signedTransaction }), + }); + + const json = await response.json(); + + if (!json.result) { + throw new TurnkeyError( + `Tron RPC Error: ${json.message}`, + TurnkeyErrorCodes.SIGN_AND_SEND_TRANSACTION_ERROR, + ); + } + + return json.txid; + } + + default: + throw new TurnkeyError( + `Unsupported transaction type for broadcasting: ${transactionType}`, + TurnkeyErrorCodes.SIGN_AND_SEND_TRANSACTION_ERROR, + ); + } +}; + +export const getWalletAccountMethods = ( + sign: ( + message: string, + provider: WalletProvider, + intent: SignIntent, + ) => Promise, + provider: WalletProvider, +) => { + const signWithIntent = (intent: SignIntent) => { + return async (input: string) => { + return sign(input, provider, intent); + }; + }; + + switch (provider.chainInfo.namespace) { + case Chain.Ethereum: + return { + signMessage: signWithIntent(SignIntent.SignMessage), + signAndSendTransaction: signWithIntent( + SignIntent.SignAndSendTransaction, + ), + }; + + case Chain.Solana: + return { + signMessage: signWithIntent(SignIntent.SignMessage), + signTransaction: signWithIntent(SignIntent.SignTransaction), + }; + + default: + throw new Error( + `Unsupported wallet chain: ${provider.chainInfo}. Supported chains are Ethereum and Solana.`, + ); + } +}; + +export function splitSignature( + signature: string, + addressFormat: v1AddressFormat, +): v1SignRawPayloadResult { + const hex = signature.replace(/^0x/, ""); + + if (addressFormat === "ADDRESS_FORMAT_ETHEREUM") { + // this is a ECDSA signature + if (hex.length === 130) { + const r = hex.slice(0, 64); + const s = hex.slice(64, 128); + const v = hex.slice(128, 130); + return { r, s, v }; + } + + // this is a DER-encoded signatures (e.g., Ledger) + const raw = fromDerSignature(hex); + const r = uint8ArrayToHexString(raw.slice(0, 32)); + const s = uint8ArrayToHexString(raw.slice(32, 64)); + + // DER signatures do not have a v component + // so we return 00 to match what Turnkey does + const v = "00"; + return { r, s, v }; + } + + if (addressFormat === "ADDRESS_FORMAT_SOLANA") { + if (hex.length !== 128) { + throw new Error( + `Invalid Solana signature length: expected 64 bytes (128 hex), got ${hex.length}`, + ); + } + + // this is a Ed25519 signature + const r = hex.slice(0, 64); + const s = hex.slice(64, 128); + + // solana signatures do not have a v component + // so we return 00 to match what Turnkey does + return { r, s, v: "00" }; + } + + throw new Error( + `Unsupported address format or invalid signature length: ${hex.length}`, + ); +} + +// Type guard to check if accounts is WalletAccount[] +export function isWalletAccountArray( + arr: any[], +): arr is v1WalletAccountParams[] { + return ( + arr.length === 0 || + (typeof arr[0] === "object" && + "addressFormat" in arr[0] && + "curve" in arr[0] && + "path" in arr[0] && + "pathFormat" in arr[0]) + ); +} + +export function createWalletAccountFromAddressFormat( + addressFormat: v1AddressFormat, +): v1WalletAccountParams { + const walletAccount = addressFormatConfig[addressFormat].defaultAccounts; + if (!walletAccount) { + throw new Error(`Unsupported address format: ${addressFormat}`); + } + + if (walletAccount[0]) { + return walletAccount[0]; + } + + throw new Error( + `No default accounts defined for address format: ${addressFormat}`, + ); +} + +export function generateWalletAccountsFromAddressFormat(params: { + addresses: v1AddressFormat[]; + existingWalletAccounts?: v1WalletAccount[]; +}): v1WalletAccountParams[] { + const { addresses, existingWalletAccounts } = params; + const pathMap = new Map(); + + // Build a lookup for max index per (addressFormat, basePath) + const maxIndexMap = new Map(); + if (existingWalletAccounts && existingWalletAccounts.length > 0) { + for (const acc of existingWalletAccounts) { + // Normalize base path (remove account index) + const basePath = acc.path.replace(/^((?:[^\/]+\/){3})[^\/]+/, "$1"); + const key = `${acc.addressFormat}:${basePath}`; + const idxSegment = acc.path.split("/")[3]; + const idx = idxSegment ? parseInt(idxSegment.replace(/'/, ""), 10) : -1; + if (!isNaN(idx)) { + maxIndexMap.set(key, Math.max(maxIndexMap.get(key) ?? -1, idx)); + } + } + } + + return addresses.map((addressFormat) => { + const account = createWalletAccountFromAddressFormat(addressFormat); + const basePath = account.path.replace(/^((?:[^\/]+\/){3})[^\/]+/, "$1"); + const key = `${addressFormat}:${basePath}`; + let nextIndex = 0; + + if (maxIndexMap.has(key)) { + nextIndex = maxIndexMap.get(key)! + 1; + } else if (pathMap.has(account.path)) { + nextIndex = pathMap.get(account.path)!; + } + + const pathWithIndex = account.path.replace( + /^((?:[^\/]*\/){3})(\d+)/, + (_, prefix) => `${prefix}${nextIndex}`, + ); + pathMap.set(account.path, nextIndex + 1); + + return { + ...account, + path: pathWithIndex, + } as v1WalletAccountParams; + }); +} + +export function buildSignUpBody(params: { + createSubOrgParams: CreateSubOrgParams | undefined; +}): ProxyTSignupBody { + const { createSubOrgParams } = params; + const websiteName = window.location.hostname; + + let authenticators: v1AuthenticatorParamsV2[] = []; + if (createSubOrgParams?.authenticators?.length) { + authenticators = + createSubOrgParams?.authenticators?.map((authenticator) => ({ + authenticatorName: + authenticator.authenticatorName || `${websiteName}-${Date.now()}`, + challenge: authenticator.challenge, + attestation: authenticator.attestation, + })) || []; + } + + let apiKeys: v1ApiKeyParamsV2[] = []; + if (createSubOrgParams?.apiKeys?.length) { + apiKeys = createSubOrgParams.apiKeys + .filter((apiKey) => apiKey.curveType !== undefined) + .map((apiKey) => ({ + apiKeyName: apiKey.apiKeyName || `api-key-${Date.now()}`, + publicKey: apiKey.publicKey, + curveType: apiKey.curveType as v1ApiKeyCurve, + ...(apiKey?.expirationSeconds && { + expirationSeconds: apiKey.expirationSeconds, + }), + })); + } + + return { + userName: + createSubOrgParams?.userName || + createSubOrgParams?.userEmail || + `user-${Date.now()}`, + ...(createSubOrgParams?.userEmail && { + userEmail: createSubOrgParams?.userEmail, + }), + ...(createSubOrgParams?.authenticators?.length + ? { + authenticators, + } + : { authenticators: [] }), + ...(createSubOrgParams?.userPhoneNumber && { + userPhoneNumber: createSubOrgParams.userPhoneNumber, + }), + ...(createSubOrgParams?.userTag && { + userTag: createSubOrgParams?.userTag, + }), + organizationName: createSubOrgParams?.subOrgName || `sub-org-${Date.now()}`, + ...(createSubOrgParams?.verificationToken && { + verificationToken: createSubOrgParams?.verificationToken, + }), + ...(createSubOrgParams?.apiKeys?.length + ? { + apiKeys, + } + : { apiKeys: [] }), + ...(createSubOrgParams?.oauthProviders?.length + ? { + oauthProviders: createSubOrgParams.oauthProviders, + } + : { oauthProviders: [] }), + ...(createSubOrgParams?.customWallet && { + wallet: { + walletName: createSubOrgParams.customWallet.walletName, + accounts: createSubOrgParams.customWallet.walletAccounts, + }, + }), + }; +} + +/** + * Extracts the public key from a Turnkey stamp header value. + * @param stampHeaderValue - The base64url encoded stamp header value + * @returns The public key as a hex string + */ +export function getPublicKeyFromStampHeader(stampHeaderValue: string): string { + try { + // we decode the base64url string to get the JSON stamp + const stampJson = decodeBase64urlToString(stampHeaderValue); + + // we parse the JSON to get the stamp object + const stamp = JSON.parse(stampJson) as { + publicKey: string; + scheme: string; + signature: string; + }; + + return stamp.publicKey; + } catch (error) { + throw new Error( + `Failed to extract public key from stamp header: ${ + error instanceof Error ? error.message : String(error) + }`, + ); + } +} + +export function isEthereumWallet(wallet: WalletProvider): boolean { + const walletType = wallet.chainInfo.namespace; + return walletType === Chain.Ethereum; +} + +export function isSolanaWallet(wallet: WalletProvider): boolean { + const walletType = wallet.chainInfo.namespace; + return walletType === Chain.Solana; +} + +export async function getAuthProxyConfig( + authProxyConfigId: string, + authProxyUrl?: string | undefined, +): Promise { + const fullUrl = + (authProxyUrl ?? "https://authproxy.turnkey.com") + "/v1/wallet_kit_config"; + + var headers: Record = { + "Content-Type": "application/json", + "X-Auth-Proxy-Config-ID": authProxyConfigId, + }; + + const response = await fetch(fullUrl, { + method: "POST", + headers: headers, + }); + + if (!response.ok) { + let res: GrpcStatus; + try { + res = await response.json(); + } catch (_) { + throw new Error(`${response.status} ${response.statusText}`); + } + + throw new TurnkeyRequestError(res); + } + + const data = await response.json(); + return data as ProxyTGetWalletKitConfigResponse; +} + +/** + * Executes an async function with error handling. + * + * @param fn The async function to execute with error handling + * @param errorOptions Options for customizing error handling + * @param finallyFn Optional function to execute in the finally block + * @returns The result of the async function or throws an error + */ +export async function withTurnkeyErrorHandling( + fn: () => Promise, + catchOptions: { + catchFn?: () => Promise; + errorMessage: string; + errorCode: TurnkeyErrorCodes; + customMessageByCodes?: Partial< + Record + >; + customMessageByMessages?: Record< + string, + { message: string; code: TurnkeyErrorCodes } + >; + }, + finallyOptions?: { + finallyFn: () => Promise; + }, +): Promise { + const { + errorMessage, + errorCode, + customMessageByCodes, + customMessageByMessages, + catchFn, + } = catchOptions; + const finallyFn = finallyOptions?.finallyFn; + try { + return await fn(); + } catch (error) { + await catchFn?.(); + if (error instanceof TurnkeyError) { + const customCodeMessage = customMessageByCodes?.[error.code!]; + if (customCodeMessage) { + throw new TurnkeyError( + customCodeMessage.message, + customCodeMessage.code, + error, + ); + } + throwMatchingMessage(error.message, customMessageByMessages, error); + + throw error; + } else if (error instanceof TurnkeyRequestError) { + throwMatchingMessage(error.message, customMessageByMessages, error); + + throw new TurnkeyError(errorMessage, errorCode, error); + } else if (error instanceof Error) { + throwMatchingMessage(error.message, customMessageByMessages, error); + + // Wrap other errors in a TurnkeyError + throw new TurnkeyError(errorMessage, errorCode, error); + } else { + throwMatchingMessage(String(error), customMessageByMessages, error); + // Handle non-Error exceptions + throw new TurnkeyError(String(error), errorCode, error); + } + } finally { + await finallyFn?.(); + } +} + +const throwMatchingMessage = ( + errorMessage: string, + customMessageByMessages: + | Record + | undefined, + error: any, +) => { + if ( + customMessageByMessages && + Object.keys(customMessageByMessages).length > 0 + ) { + Object.keys(customMessageByMessages).forEach((key) => { + if (errorMessage.includes(key)) { + throw new TurnkeyError( + customMessageByMessages[key]!.message, + customMessageByMessages[key]!.code, + error, + ); + } + }); + } +}; diff --git a/packages/core/tsconfig.json b/packages/core/tsconfig.json new file mode 100644 index 000000000..436324848 --- /dev/null +++ b/packages/core/tsconfig.json @@ -0,0 +1,31 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "./dist", + "rootDir": "./src", + "tsBuildInfoFile": "./.cache/.tsbuildinfo", + "lib": ["dom"], + "skipLibCheck": true, + "allowJs": false, + "checkJs": false, + "paths": { + "@polyfills/*": ["./src/__polyfills__/*"], + "@types": ["./src/__types__/base"], + "@utils": ["./src/utils"] + } + }, + "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.json"], + "exclude": [ + "**/dist/**", + "node_modules", + "**/__tests__/**/*", + "**/__fixtures__/**/*" + ], + "references": [ + { "path": "../sdk-types" }, + { "path": "../api-key-stamper" }, + { "path": "../http" }, + { "path": "../iframe-stamper" }, + { "path": "../webauthn-stamper" } + ] +} diff --git a/packages/core/tsconfig.typecheck.json b/packages/core/tsconfig.typecheck.json new file mode 100644 index 000000000..2943b35ec --- /dev/null +++ b/packages/core/tsconfig.typecheck.json @@ -0,0 +1,15 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "noEmit": true, + "tsBuildInfoFile": "./.cache/.typecheck.tsbuildinfo", + "paths": { + "@polyfills/*": ["./src/__polyfills__/*"], + "@stampers": ["./src/__stampers__"], + "@storage": ["./src/__storage__"], + "@types": ["./src/__types__/base"], + "@utils": ["./src/utils"] + } + }, + "include": ["src/**/*.ts", "src/**/*.js", "src/**/*.json"] +} diff --git a/packages/core/typedoc.json b/packages/core/typedoc.json new file mode 100644 index 000000000..6fd3758c3 --- /dev/null +++ b/packages/core/typedoc.json @@ -0,0 +1,35 @@ +{ + "entryPoints": ["src/index.ts"], + "name": "core", + "exclude": [ + "src/turnkey-helpers.ts", + "**/__generated__/**", + "**/__inputs__/**", + "**/__types__/**", + "**/__storage__/**", + "**/__polyfills__/**", + "**/node_modules/**", + "src/__generated__/sdk_api_types.ts", + "src/__generated__/sdk-client-base.ts", + "src/__inputs__/public_api.types.ts", + "src/__inputs__/public_api.swagger.json", + "src/__types__/base.ts" + ], + "excludeInternal": true, + "includeVersion": true, + "fileExtension": ".mdx", + "alwaysCreateEntryPointModule": true, + "gitRevision": "main", + "router": "structure-dir", + "plugin": ["typedoc-plugin-markdown"], + "projectDocuments": ["documents/*.md", "CHANGELOG.md"], + "expandParameters": true, + "outputs": [ + { + // requires typedoc-plugin-markdown + "name": "markdown", + "path": "./generated-docs/sdks", + "fileExtension": ".mdx" + } + ] +} diff --git a/packages/cosmjs/CHANGELOG.md b/packages/cosmjs/CHANGELOG.md index d5cf5a69c..977b0f958 100644 --- a/packages/cosmjs/CHANGELOG.md +++ b/packages/cosmjs/CHANGELOG.md @@ -1,5 +1,55 @@ # @turnkey/cosmjs +## 0.7.25-beta.4 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/sdk-server@4.7.0-beta.1 + - @turnkey/http@3.10.0-beta.1 + - @turnkey/sdk-browser@5.7.1-beta.1 + - @turnkey/api-key-stamper@0.4.8-beta.4 + +## 0.7.25-beta.3 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/sdk-server@4.7.0-beta.0 + - @turnkey/http@3.10.0-beta.0 + - @turnkey/sdk-browser@5.7.1-beta.0 + - @turnkey/api-key-stamper@0.4.8-beta.3 + +## 0.7.25-beta.2 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/sdk-browser@5.6.1-beta.2 + - @turnkey/api-key-stamper@0.4.8-beta.2 + - @turnkey/http@3.8.1-beta.2 + - @turnkey/sdk-server@4.5.1-beta.2 + +## 0.7.25-beta.1 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/sdk-browser@5.6.1-beta.1 + - @turnkey/api-key-stamper@0.4.8-beta.1 + - @turnkey/http@3.8.1-beta.1 + - @turnkey/sdk-server@4.5.1-beta.1 + +## 0.7.25-beta.0 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/sdk-browser@5.6.1-beta.0 + - @turnkey/api-key-stamper@0.4.8-beta.0 + - @turnkey/http@3.8.1-beta.0 + - @turnkey/sdk-server@4.5.1-beta.0 + ## 0.7.25 ### Patch Changes diff --git a/packages/cosmjs/package.json b/packages/cosmjs/package.json index 15416fbd1..1d2156d19 100644 --- a/packages/cosmjs/package.json +++ b/packages/cosmjs/package.json @@ -1,6 +1,6 @@ { "name": "@turnkey/cosmjs", - "version": "0.7.25", + "version": "0.7.25-beta.4", "main": "./dist/index.js", "module": "./dist/index.mjs", "exports": { diff --git a/packages/crypto/CHANGELOG.md b/packages/crypto/CHANGELOG.md index 71c4889e3..19b25f275 100644 --- a/packages/crypto/CHANGELOG.md +++ b/packages/crypto/CHANGELOG.md @@ -1,5 +1,40 @@ # @turnkey/crypto +## 2.5.1-beta.4 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/encoding@0.6.0-beta.4 + +## 2.5.1-beta.3 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/encoding@0.6.0-beta.3 + +## 2.5.1-beta.2 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/encoding@0.6.0-beta.2 + +## 2.5.1-beta.1 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/encoding@0.6.0-beta.1 + +## 2.5.1-beta.0 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/encoding@0.6.0-beta.0 + ## 2.5.0 ### Minor Changes diff --git a/packages/crypto/package.json b/packages/crypto/package.json index 3a151bfab..26de07256 100644 --- a/packages/crypto/package.json +++ b/packages/crypto/package.json @@ -1,6 +1,6 @@ { "name": "@turnkey/crypto", - "version": "2.5.0", + "version": "2.5.1-beta.4", "main": "./dist/index.js", "module": "./dist/index.mjs", "exports": { diff --git a/packages/eip-1193-provider/CHANGELOG.md b/packages/eip-1193-provider/CHANGELOG.md index 36ff0da97..6343598aa 100644 --- a/packages/eip-1193-provider/CHANGELOG.md +++ b/packages/eip-1193-provider/CHANGELOG.md @@ -1,5 +1,58 @@ # @turnkey/eip-1193-provider +## 3.4.0-beta.4 + +### Minor Changes + +- @turnkey/react-wallet-kit and @turnkey/core beta-3 release + +### Patch Changes + +- Updated dependencies []: + - @turnkey/http@3.10.0-beta.1 + - @turnkey/sdk-browser@5.7.1-beta.1 + - @turnkey/api-key-stamper@0.4.8-beta.4 + +## 3.4.0-beta.3 + +### Minor Changes + +- @turnkey/react-wallet-kit and @turnkey/core beta-3 release + +### Patch Changes + +- Updated dependencies []: + - @turnkey/http@3.10.0-beta.0 + - @turnkey/sdk-browser@5.7.1-beta.0 + - @turnkey/api-key-stamper@0.4.8-beta.3 + +## 3.3.24-beta.2 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/sdk-browser@5.6.1-beta.2 + - @turnkey/api-key-stamper@0.4.8-beta.2 + - @turnkey/http@3.8.1-beta.2 + +## 3.3.24-beta.1 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/sdk-browser@5.6.1-beta.1 + - @turnkey/api-key-stamper@0.4.8-beta.1 + - @turnkey/http@3.8.1-beta.1 + +## 3.3.24-beta.0 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/sdk-browser@5.6.1-beta.0 + - @turnkey/api-key-stamper@0.4.8-beta.0 + - @turnkey/http@3.8.1-beta.0 + ## 3.3.24 ### Patch Changes diff --git a/packages/eip-1193-provider/package.json b/packages/eip-1193-provider/package.json index 5a8b5dd1b..4e753c85b 100644 --- a/packages/eip-1193-provider/package.json +++ b/packages/eip-1193-provider/package.json @@ -1,6 +1,6 @@ { "name": "@turnkey/eip-1193-provider", - "version": "3.3.24", + "version": "3.4.0-beta.4", "main": "./dist/index.js", "module": "./dist/index.mjs", "exports": { diff --git a/packages/eip-1193-provider/src/version.ts b/packages/eip-1193-provider/src/version.ts index 921ac2eb8..42c9f39ab 100644 --- a/packages/eip-1193-provider/src/version.ts +++ b/packages/eip-1193-provider/src/version.ts @@ -1 +1 @@ -export const VERSION = "@turnkey/eip-1193-provider@3.3.24"; +export const VERSION = "@turnkey/eip-1193-provider@3.4.0-beta.4"; diff --git a/packages/encoding/CHANGELOG.md b/packages/encoding/CHANGELOG.md index 0f54a755d..2cb80fab0 100644 --- a/packages/encoding/CHANGELOG.md +++ b/packages/encoding/CHANGELOG.md @@ -1,5 +1,35 @@ # @turnkey/encoding +## 0.6.0-beta.4 + +### Minor Changes + +- @turnkey/react-wallet-kit and @turnkey/core beta-3 release + +## 0.6.0-beta.3 + +### Minor Changes + +- @turnkey/react-wallet-kit and @turnkey/core beta-3 release + +## 0.6.0-beta.2 + +### Minor Changes + +- updating package versions + +## 0.6.0-beta.1 + +### Minor Changes + +- test build + +## 0.6.0-beta.0 + +### Minor Changes + +- beta for @turnkey/react-wallet-kit and @turnkey/core + ## 0.5.0 ### Minor Changes diff --git a/packages/encoding/package.json b/packages/encoding/package.json index a15e9837b..766395b43 100644 --- a/packages/encoding/package.json +++ b/packages/encoding/package.json @@ -1,6 +1,6 @@ { "name": "@turnkey/encoding", - "version": "0.5.0", + "version": "0.6.0-beta.4", "main": "./dist/index.js", "module": "./dist/index.mjs", "exports": { diff --git a/packages/encoding/src/index.ts b/packages/encoding/src/index.ts index 355509422..60d0f41ce 100644 --- a/packages/encoding/src/index.ts +++ b/packages/encoding/src/index.ts @@ -29,6 +29,17 @@ export function stringToBase64urlString(input: string): string { return base64StringToBase64UrlEncodedString(base64String); } +export function base64UrlToBase64(input: string): string { + let b64 = input.replace(/-/g, "+").replace(/_/g, "/"); + const padLen = (4 - (b64.length % 4)) % 4; + return b64 + "=".repeat(padLen); +} + +export function decodeBase64urlToString(input: string): string { + const b64 = base64UrlToBase64(input); + return atob(b64); +} + export function hexStringToBase64url(input: string, length?: number): string { // Add an extra 0 to the start of the string to get a valid hex string (even length) // (e.g. 0x0123 instead of 0x123) @@ -200,3 +211,57 @@ function btoaLookup(index: number) { // Throw INVALID_CHARACTER_ERR exception here -- won't be hit in the tests. return undefined; } + +// Pure JS implementation of atob. +export function atob(input: string): string { + if (arguments.length === 0) { + throw new TypeError("1 argument required, but only 0 present."); + } + + // convert to string and remove invalid characters upfront + const str = String(input).replace(/[^A-Za-z0-9+/=]/g, ""); + + // "The btoa() method must throw an "InvalidCharacterError" if + // the length of the string is not a multiple of 4 + if (str.length % 4 === 1) { + throw new Error( + "InvalidCharacterError: The string to be decoded is not correctly encoded.", + ); + } + + const keyStr = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + let output = ""; + let buffer = 0; + let bits = 0; + let i = 0; + + // process each character + while (i < str.length) { + const ch = str.charAt(i); + const index = keyStr.indexOf(ch); + + if (index < 0 || index > 64) { + i++; + continue; + } + + if (ch === "=") { + // we skip padding characters + bits = 0; + } else { + buffer = (buffer << 6) | index; + bits += 6; + } + + // output complete bytes + while (bits >= 8) { + bits -= 8; + output += String.fromCharCode((buffer >> bits) & 0xff); + } + + i++; + } + + return output; +} diff --git a/packages/ethers/CHANGELOG.md b/packages/ethers/CHANGELOG.md index 100e74edd..5b58084ca 100644 --- a/packages/ethers/CHANGELOG.md +++ b/packages/ethers/CHANGELOG.md @@ -1,5 +1,55 @@ # @turnkey/ethers +## 1.2.8-beta.4 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/sdk-server@4.7.0-beta.1 + - @turnkey/http@3.10.0-beta.1 + - @turnkey/sdk-browser@5.7.1-beta.1 + - @turnkey/api-key-stamper@0.4.8-beta.4 + +## 1.2.8-beta.3 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/sdk-server@4.7.0-beta.0 + - @turnkey/http@3.10.0-beta.0 + - @turnkey/sdk-browser@5.7.1-beta.0 + - @turnkey/api-key-stamper@0.4.8-beta.3 + +## 1.2.8-beta.2 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/sdk-browser@5.6.1-beta.2 + - @turnkey/api-key-stamper@0.4.8-beta.2 + - @turnkey/http@3.8.1-beta.2 + - @turnkey/sdk-server@4.5.1-beta.2 + +## 1.2.8-beta.1 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/sdk-browser@5.6.1-beta.1 + - @turnkey/api-key-stamper@0.4.8-beta.1 + - @turnkey/http@3.8.1-beta.1 + - @turnkey/sdk-server@4.5.1-beta.1 + +## 1.2.8-beta.0 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/sdk-browser@5.6.1-beta.0 + - @turnkey/api-key-stamper@0.4.8-beta.0 + - @turnkey/http@3.8.1-beta.0 + - @turnkey/sdk-server@4.5.1-beta.0 + ## 1.2.8 ### Patch Changes diff --git a/packages/ethers/package.json b/packages/ethers/package.json index f2ca0fa5e..b0e839fce 100644 --- a/packages/ethers/package.json +++ b/packages/ethers/package.json @@ -1,6 +1,6 @@ { "name": "@turnkey/ethers", - "version": "1.2.8", + "version": "1.2.8-beta.4", "main": "./dist/index.js", "module": "./dist/index.mjs", "exports": { diff --git a/packages/http/CHANGELOG.md b/packages/http/CHANGELOG.md index bcbb02f80..4c1320149 100644 --- a/packages/http/CHANGELOG.md +++ b/packages/http/CHANGELOG.md @@ -1,11 +1,59 @@ # @turnkey/http +## 3.10.0-beta.1 + +### Minor Changes + +- @turnkey/react-wallet-kit and @turnkey/core beta-3 release + +### Patch Changes + +- Updated dependencies []: + - @turnkey/encoding@0.6.0-beta.4 + - @turnkey/api-key-stamper@0.4.8-beta.4 + +## 3.10.0-beta.0 + +### Minor Changes + +- @turnkey/react-wallet-kit and @turnkey/core beta-3 release + +### Patch Changes + +- Updated dependencies []: + - @turnkey/encoding@0.6.0-beta.3 + - @turnkey/api-key-stamper@0.4.8-beta.3 + ## 3.9.0 ### Minor Changes - [#834](https://github.com/tkhq/sdk/pull/834) [`8b39dba`](https://github.com/tkhq/sdk/commit/8b39dbabf68d3e376b5b07f26960d5b61ae87fa9) Author [@moeodeh3](https://github.com/moeodeh3) - Update per mono release v2025.8.3-hotfix.0 +## 3.8.1-beta.2 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/encoding@0.6.0-beta.2 + - @turnkey/api-key-stamper@0.4.8-beta.2 + +## 3.8.1-beta.1 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/encoding@0.6.0-beta.1 + - @turnkey/api-key-stamper@0.4.8-beta.1 + +## 3.8.1-beta.0 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/encoding@1.0.0-beta.0 + - @turnkey/api-key-stamper@0.4.8-beta.0 + ## 3.8.0 ### Minor Changes diff --git a/packages/http/package.json b/packages/http/package.json index 5e9b0c3dc..fe335ae8a 100644 --- a/packages/http/package.json +++ b/packages/http/package.json @@ -1,6 +1,6 @@ { "name": "@turnkey/http", - "version": "3.9.0", + "version": "3.10.0-beta.1", "main": "./dist/index.js", "module": "./dist/index.mjs", "exports": { diff --git a/packages/http/src/version.ts b/packages/http/src/version.ts index 3e7f9a8a3..e846f9a28 100644 --- a/packages/http/src/version.ts +++ b/packages/http/src/version.ts @@ -1 +1 @@ -export const VERSION = "@turnkey/http@3.9.0"; +export const VERSION = "@turnkey/http@3.10.0-beta.1"; diff --git a/packages/indexed-db-stamper/CHANGELOG.md b/packages/indexed-db-stamper/CHANGELOG.md index 1b4cdc9f1..4cdcb53c9 100644 --- a/packages/indexed-db-stamper/CHANGELOG.md +++ b/packages/indexed-db-stamper/CHANGELOG.md @@ -1,5 +1,45 @@ # @turnkey/indexed-db-stamper +## 1.1.2-beta.4 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/encoding@0.6.0-beta.4 + - @turnkey/api-key-stamper@0.4.8-beta.4 + +## 1.1.2-beta.3 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/encoding@0.6.0-beta.3 + - @turnkey/api-key-stamper@0.4.8-beta.3 + +## 1.1.2-beta.2 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/encoding@0.6.0-beta.2 + - @turnkey/api-key-stamper@0.4.8-beta.2 + +## 1.1.2-beta.1 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/encoding@0.6.0-beta.1 + - @turnkey/api-key-stamper@0.4.8-beta.1 + +## 1.1.2-beta.0 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/encoding@0.6.0-beta.0 + - @turnkey/api-key-stamper@0.4.8-beta.0 + ## 1.1.1 ### Patch Changes diff --git a/packages/indexed-db-stamper/package.json b/packages/indexed-db-stamper/package.json index f10a43ae2..9c1db48d7 100644 --- a/packages/indexed-db-stamper/package.json +++ b/packages/indexed-db-stamper/package.json @@ -1,6 +1,6 @@ { "name": "@turnkey/indexed-db-stamper", - "version": "1.1.1", + "version": "1.1.2-beta.4", "main": "./dist/index.js", "module": "./dist/index.mjs", "exports": { diff --git a/packages/react-native-passkey-stamper/CHANGELOG.md b/packages/react-native-passkey-stamper/CHANGELOG.md index a0d1947fb..6561e64fe 100644 --- a/packages/react-native-passkey-stamper/CHANGELOG.md +++ b/packages/react-native-passkey-stamper/CHANGELOG.md @@ -1,5 +1,45 @@ # @turnkey/react-native-passkey-stamper +## 1.1.2-beta.4 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/encoding@0.6.0-beta.4 + - @turnkey/http@3.10.0-beta.1 + +## 1.1.2-beta.3 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/encoding@0.6.0-beta.3 + - @turnkey/http@3.10.0-beta.0 + +## 1.1.2-beta.2 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/encoding@0.6.0-beta.2 + - @turnkey/http@3.8.1-beta.2 + +## 1.1.2-beta.1 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/encoding@0.6.0-beta.1 + - @turnkey/http@3.8.1-beta.1 + +## 1.1.2-beta.0 + +### Patch Changes + +- Updated dependencies []: + - @turnkey/encoding@1.0.0-beta.0 + - @turnkey/http@3.8.1-beta.0 + ## 1.1.2 ### Patch Changes diff --git a/packages/react-native-passkey-stamper/package.json b/packages/react-native-passkey-stamper/package.json index bbb3cadec..cef6735c1 100644 --- a/packages/react-native-passkey-stamper/package.json +++ b/packages/react-native-passkey-stamper/package.json @@ -1,6 +1,6 @@ { "name": "@turnkey/react-native-passkey-stamper", - "version": "1.1.2", + "version": "1.1.2-beta.4", "main": "./dist/index.js", "module": "./dist/index.mjs", "exports": { diff --git a/packages/react-wallet-kit/CHANGELOG.md b/packages/react-wallet-kit/CHANGELOG.md new file mode 100644 index 000000000..3209831a3 --- /dev/null +++ b/packages/react-wallet-kit/CHANGELOG.md @@ -0,0 +1,85 @@ +# @turnkey/react-wallet-kit + +## 1.0.0-beta.4 + +### Minor Changes + +- @turnkey/react-wallet-kit and @turnkey/core beta-3 release + +### Patch Changes + +- Updated dependencies []: + - @turnkey/sdk-types@0.4.0-beta.4 + - @turnkey/core@1.0.0-beta.4 + +## 1.0.0-beta.3 + +### Minor Changes + +- @turnkey/react-wallet-kit and @turnkey/core beta-3 release + +### Patch Changes + +- Updated dependencies []: + - @turnkey/sdk-types@0.4.0-beta.3 + - @turnkey/core@1.0.0-beta.3 + +## 1.0.0-beta.2 + +### Minor Changes + +- updating package versions + +### Patch Changes + +- Updated dependencies []: + - @turnkey/sdk-types@0.4.0-beta.2 + - @turnkey/core@1.0.0-beta.2 + +## 1.0.0-beta.1 + +### Minor Changes + +- test build + +### Patch Changes + +- Updated dependencies []: + - @turnkey/sdk-types@0.4.0-beta.1 + - @turnkey/core@1.0.0-beta.1 + +## 1.0.0-beta.0 + +### Major Changes + +- beta for @turnkey/react-wallet-kit and @turnkey/core + +### Patch Changes + +- Updated dependencies []: + - @turnkey/core@1.0.0-beta.0 + - @turnkey/sdk-types@0.4.0-beta.0 + +## 1.0.0 + +### Major Changes + +- Initial beta release for react wallet kit + +### Patch Changes + +- Updated dependencies []: + - @turnkey/core@1.0.0 + - @turnkey/sdk-types@0.4.0 + +## 1.0.0 + +### Major Changes + +- Initial beta release for @turnkey/react-wallet-kit and @turnkey/core + +### Patch Changes + +- Updated dependencies []: + - @turnkey/core@1.0.0 + - @turnkey/sdk-types@0.4.0 diff --git a/packages/react-wallet-kit/README.MD b/packages/react-wallet-kit/README.MD new file mode 100644 index 000000000..0cda48814 --- /dev/null +++ b/packages/react-wallet-kit/README.MD @@ -0,0 +1,113 @@ +# @turnkey/react-wallet-kit + +The `@turnkey/react-wallet-kit` is a powerful SDK that allows you to integrate Turnkey's Embedded Wallets into your React applications. It provides a set of UI components and easy-to-use functions, all exported from a hook, enabling you to quickly build secure embedded wallet experiences. + + +## Installation + +You can use `@turnkey/react-wallet-kit` in any React based web application. + +For this guide, let's create a new `Next.js` app. If you already have an existing app, you don't need to do this. + +```bash npx +npx create-next-app@latest +``` + +Now, install the Turnkey React Wallet Kit package: + + + +```bash npm +npm install @turnkey/react-wallet-kit +``` + +```bash pnpm +pnpm add @turnkey/react-wallet-kit +``` + +```bash yarn +yarn add @turnkey/react-wallet-kit +``` + + + +## Provider + +Wrap your app with the `TurnkeyProvider` component, and import `"@turnkey/react-wallet-kit/styles.css"` to include styles for the UI components. + +With Next.js App Router, keep `app/layout.tsx` as a server component and create a separate `app/providers.tsx` client wrapper. This is necessary if you want to pass callbacks (e.g., onError), which must be defined in a client component. + +```tsx app/providers.tsx +"use client"; + +import { + TurnkeyProvider, + TurnkeyProviderConfig, +} from "@turnkey/react-wallet-kit"; + +const turnkeyConfig: TurnkeyProviderConfig = { + organizationId: process.env.NEXT_PUBLIC_ORGANIZATION_ID!, + authProxyConfigId: process.env.NEXT_PUBLIC_AUTH_PROXY_CONFIG_ID!, +}; + +export function Providers({ children }: { children: React.ReactNode }) { + return {children}; +} +``` + +In case anything goes wrong, let's add an `onError` callback to the `TurnkeyProvider` to catch any errors that may occur. + +```tsx app/providers.tsx + console.error("Turnkey error:", error), + }} +> +``` + +Then, use the `Providers` component to wrap your app in `app/layout.tsx`. + +```tsx app/layout.tsx +import "@turnkey/react-wallet-kit/styles.css"; +import "./globals.css"; +import Providers from "./providers"; + +export default function RootLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + + + {children} + + + ); +} +``` + +> **Why this pattern?** +> +> - Callbacks (and other interactive bits) must be declared in a client component. +> - Keeping layout.tsx as a server component maintains optimal rendering and avoids making your entire app client-side unnecessarily. +> - Centralizing Turnkey setup in app/providers.tsx keeps configuration, styles, and callbacks in one place. + + +## Quick Authentication + +The easiest way to handle authentication is using the `handleLogin` function from the `useTurnkey` hook. This will automatically show a modal with all the authentication methods you've enabled in your dashboard. + +```tsx +import { useTurnkey } from "@turnkey/react-wallet-kit"; + +function LoginButton() { + const { handleLogin } = useTurnkey(); + + return ; +} +``` + + +For more information, check out [our docs!](https://docs.turnkey.com) \ No newline at end of file diff --git a/packages/react-wallet-kit/package.json b/packages/react-wallet-kit/package.json new file mode 100644 index 000000000..f712434a2 --- /dev/null +++ b/packages/react-wallet-kit/package.json @@ -0,0 +1,78 @@ +{ + "name": "@turnkey/react-wallet-kit", + "version": "1.0.0-beta.4", + "description": "The easiest and most powerful way to integrate Turnkey's Embedded Wallets into your React applications.", + "main": "./dist/index.js", + "module": "./dist/index.mjs", + "types": "dist/index.d.ts", + "exports": { + ".": { + "import": "./dist/index.mjs", + "require": "./dist/index.js", + "types": "./dist/index.d.ts" + }, + "./styles.css": "./dist/styles.css" + }, + "files": [ + "dist", + "README.md" + ], + "scripts": { + "build": "rollup -c", + "clean": "rimraf ./dist ./.cache", + "typecheck": "tsc -p tsconfig.typecheck.json", + "prepublishOnly": "pnpm run clean && pnpm run build" + }, + "keywords": [ + "turnkey" + ], + "license": "MIT", + "dependencies": { + "@fortawesome/fontawesome-svg-core": "^6.7.2", + "@fortawesome/free-brands-svg-icons": "^6.7.2", + "@fortawesome/free-solid-svg-icons": "^6.7.2", + "@fortawesome/react-fontawesome": "^0.2.2", + "@headlessui/react": "^2.2.6", + "@lottiefiles/react-lottie-player": "^3.6.0", + "@noble/hashes": "^1.8.0", + "@turnkey/iframe-stamper": "workspace:^", + "@turnkey/core": "workspace:*", + "@turnkey/sdk-types": "workspace:*", + "buffer": "^6.0.3", + "clsx": "^2.1.1", + "libphonenumber-js": "^1.11.14", + "qrcode.react": "^4.2.0", + "react-international-phone": "^4.3.0" + }, + "devDependencies": { + "@rollup/plugin-babel": "5.3.0", + "@rollup/plugin-node-resolve": "16.0.0", + "@rollup/plugin-strip": "^3.0.4", + "@tailwindcss/postcss": "^4.1.10", + "@types/react": "^18.2.75", + "@types/react-dom": "^18.2.7", + "autoprefixer": "^10.0.1", + "glob": "^8.0.3", + "postcss": "^8.4.38", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "tailwindcss": "^4.1.10", + "typescript": "5.4.3" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + }, + "engines": { + "node": ">=18.0.0" + }, + "publishConfig": { + "access": "public", + "tag": "beta" + } +} diff --git a/packages/react-wallet-kit/postcss.config.js b/packages/react-wallet-kit/postcss.config.js new file mode 100644 index 000000000..483f37854 --- /dev/null +++ b/packages/react-wallet-kit/postcss.config.js @@ -0,0 +1,5 @@ +module.exports = { + plugins: { + "@tailwindcss/postcss": {}, + }, +}; diff --git a/packages/react-wallet-kit/rollup.config.mjs b/packages/react-wallet-kit/rollup.config.mjs new file mode 100644 index 000000000..01fb91c25 --- /dev/null +++ b/packages/react-wallet-kit/rollup.config.mjs @@ -0,0 +1,111 @@ +import postcss from "rollup-plugin-postcss"; +import typescript from "@rollup/plugin-typescript"; +import nodeExternals from "rollup-plugin-node-externals"; +import path from "node:path"; +import alias from "@rollup/plugin-alias"; +import url from "@rollup/plugin-url"; +import preserveDirectives from "rollup-preserve-directives"; +import strip from "@rollup/plugin-strip"; +import { nodeResolve } from "@rollup/plugin-node-resolve"; +import { babel } from "@rollup/plugin-babel"; + +const getFormatConfig = (format) => { + const pkgPath = path.join(process.cwd(), "package.json"); + const __dirname = path.dirname(new URL(import.meta.url).pathname); + const isCjs = format === "cjs"; + + /** @type {import('rollup').RollupOptions} */ + return { + input: "src/index.ts", + output: { + format, + dir: "dist", + entryFileNames: `[name].${format === "esm" ? "mjs" : "js"}`, + preserveModules: true, + preserveModulesRoot: "src", + sourcemap: true, + exports: "named", + }, + plugins: [ + // Handle assets like images and fonts + url({ + include: [ + "**/*.svg", + "**/*.png", + "**/*.jpg", + "**/*.gif", + "**/*.woff", + "**/*.woff2", + "**/*.ttf", + "**/*.eot", + ], + limit: 8192, + emitFiles: true, + fileName: "assets/fonts/[name].[hash][extname]", + }), + alias({ + entries: [ + { + find: "assets", + replacement: path.resolve(__dirname, "src/assets"), + }, + ], + }), + // Add nodeResolve to fix deep ESM import resolution + nodeResolve({ + extensions: [".js", ".jsx", ".ts", ".tsx", ".mjs"], + preferBuiltins: true, + mainFields: ["module", "main", "browser"], + }), + // Preserve directives such as "use client" or "use server" + preserveDirectives(), + strip({ + include: "**/*.(ts|tsx|js|jsx)", + functions: ['"use client"'], + }), + // Transpile using Babel and ensure ES module syntax is preserved + babel({ + babelHelpers: "bundled", + extensions: [".js", ".jsx", ".ts", ".tsx"], + include: ["src/**/*"], + presets: [ + [ + "@babel/preset-env", + { + // Disable module transformation so Rollup can handle imports/exports + modules: false, + targets: isCjs ? { node: "current" } : undefined, + }, + ], + "@babel/preset-react", + ], + }), + typescript({ + tsconfig: "./tsconfig.json", + outputToFilesystem: false, + compilerOptions: { + outDir: "dist", + composite: false, + declaration: format === "esm", + declarationMap: format === "esm", + sourceMap: true, + }, + }), + nodeExternals({ + packagePath: pkgPath, + builtinsPrefix: "ignore", + }), + postcss({ + extract: "styles.css", + minimize: true, + }), + ], + }; +}; + +export default () => { + const esm = getFormatConfig("esm"); + const cjs = getFormatConfig("cjs"); + + return [esm, cjs]; +}; diff --git a/packages/react-wallet-kit/src/assets/ring-resize.svg b/packages/react-wallet-kit/src/assets/ring-resize.svg new file mode 100644 index 000000000..f80e74deb --- /dev/null +++ b/packages/react-wallet-kit/src/assets/ring-resize.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/react-wallet-kit/src/components/auth/Action.tsx b/packages/react-wallet-kit/src/components/auth/Action.tsx new file mode 100644 index 000000000..d651ee3cc --- /dev/null +++ b/packages/react-wallet-kit/src/components/auth/Action.tsx @@ -0,0 +1,72 @@ +import { useRef, useState, useEffect } from "react"; +import { useModal } from "../../providers/modal/Hook"; +import { Spinner } from "../design/Spinners"; +import clsx from "clsx"; + +interface ActionPageProps { + title: string; + icon: React.ReactNode; + closeOnComplete?: boolean; + action?: () => Promise; +} + +export function ActionPage(props: ActionPageProps) { + const { title, icon, closeOnComplete = true, action } = props; + const { popPage, closeModal, isMobile } = useModal(); + const hasRun = useRef(false); + const iconRef = useRef(null); + const [spinnerSize, setSpinnerSize] = useState(40); + + useEffect(() => { + if (iconRef.current) { + const rect = iconRef.current.getBoundingClientRect(); + const size = Math.max(rect.width, rect.height); + setSpinnerSize(size + 50); + } + }, []); + + useEffect(() => { + if (hasRun.current) return; + hasRun.current = true; + const runAction = async () => { + if (action) { + try { + await action(); + } catch (error) { + popPage(); + throw new Error(`${error}`); + } + if (closeOnComplete) { + closeModal(); + } + } + }; + runAction(); + }, []); + + return ( +
+
+
+
+ {icon} +
+ +
+ {title} +
+
+ ); +} diff --git a/packages/react-wallet-kit/src/components/auth/Email.tsx b/packages/react-wallet-kit/src/components/auth/Email.tsx new file mode 100644 index 000000000..2d0cdedd9 --- /dev/null +++ b/packages/react-wallet-kit/src/components/auth/Email.tsx @@ -0,0 +1,97 @@ +import { useState } from "react"; +import { Input } from "@headlessui/react"; +import { ActionButton, IconButton } from "../design/Buttons"; +import { faArrowRight } from "@fortawesome/free-solid-svg-icons"; +import clsx from "clsx"; +import { useTurnkey } from "../../providers/client/Hook"; + +function isValidEmail(email: string): boolean { + return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); +} + +interface EmailInputProps { + onContinue?: (email: string) => void; +} + +export function EmailInput(props: EmailInputProps) { + const { onContinue } = props; + const { config } = useTurnkey(); + const [loading, setLoading] = useState(false); + const [email, setEmail] = useState(""); + const useContinueButton = config?.ui?.preferLargeActionButtons ?? false; + + const emailIsValid = isValidEmail(email); + + const handleContinue = async () => { + if (emailIsValid && onContinue) { + setLoading(true); + try { + await Promise.resolve(onContinue(email)); + } finally { + setLoading(false); + } + } + }; + + const handleKeyDown = (e: React.KeyboardEvent) => { + if (e.key === "Enter") { + handleContinue(); + } + }; + + const buttonDisabled = !emailIsValid; + + const buttonClass = clsx( + "transition-all duration-300", + (emailIsValid || useContinueButton) && + "bg-primary-light dark:bg-primary-dark hover:bg-primary-light/90 dark:hover:bg-primary-dark/90 text-primary-text-light dark:text-primary-text-dark", + ); + + return ( +
+
+ setEmail(e.target.value)} + onKeyDown={handleKeyDown} + className="w-full py-3 px-4 rounded-md text-inherit placeholder-icon-text-light dark:placeholder-icon-text-dark bg-button-light dark:bg-button-dark border border-modal-background-dark/20 dark:border-modal-background-light/20 focus:outline-primary-light focus:dark:outline-primary-dark focus:outline-[1px] focus:outline-offset-0 box-border" + /> + + {!useContinueButton && ( + + )} +
+ + {useContinueButton && ( + + Continue + + )} +
+ ); +} diff --git a/packages/react-wallet-kit/src/components/auth/OAuth.tsx b/packages/react-wallet-kit/src/components/auth/OAuth.tsx new file mode 100644 index 000000000..a27cfd87d --- /dev/null +++ b/packages/react-wallet-kit/src/components/auth/OAuth.tsx @@ -0,0 +1,43 @@ +import { useEffect, useRef, useState } from "react"; +import { ActionButton } from "../design/Buttons"; + +interface OAuthButtonProps { + name: string; + icon: React.ReactNode; + onClick: () => void; + className?: string; +} + +export function OAuthButton(props: OAuthButtonProps) { + const containerRef = useRef(null); + const [showText, setShowText] = useState(false); + const { name, icon, onClick, className } = props; + + useEffect(() => { + const observer = new ResizeObserver(([entry]) => { + if (!entry) return; + const width = entry.contentRect.width; + setShowText(width > 300); + }); + + if (containerRef.current) { + observer.observe(containerRef.current); + } + + return () => observer.disconnect(); + }, []); + + return ( +
+ + {icon} + {showText && ( + {`Continue with ${name}`} + )} + +
+ ); +} diff --git a/packages/react-wallet-kit/src/components/auth/OTP.tsx b/packages/react-wallet-kit/src/components/auth/OTP.tsx new file mode 100644 index 000000000..f0ea7a5dc --- /dev/null +++ b/packages/react-wallet-kit/src/components/auth/OTP.tsx @@ -0,0 +1,255 @@ +import { useRef, useState } from "react"; +import { useModal } from "../../providers/modal/Hook"; +import { useTurnkey } from "../../providers/client/Hook"; +import { Spinner } from "../design/Spinners"; +import { Input } from "@headlessui/react"; +import { BaseButton } from "../design/Buttons"; +import { OtpType } from "@turnkey/core"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faEnvelope, faPhone } from "@fortawesome/free-solid-svg-icons"; +import clsx from "clsx"; + +interface OtpVerificationProps { + contact: string; + otpId: string; + otpType: OtpType; + otpLength?: number; + alphanumeric?: boolean; + formattedContact?: string; // Optional formatted contact for display purposes + onContinue?: (optCode: string) => Promise; // Optional callback for continue action +} +export function OtpVerification(props: OtpVerificationProps) { + const { + contact, + otpType, + otpLength = 6, + alphanumeric = true, + formattedContact, + onContinue = null, // Default to null if not provided + } = props; + const { initOtp, completeOtp } = useTurnkey(); + const { closeModal, isMobile } = useModal(); + const [submitting, setSubmitting] = useState(false); + const [resending, setResending] = useState(false); + const [resent, setResent] = useState(false); + const [otpId, setOtpId] = useState(props.otpId); + const [error, setError] = useState(null); + const [shaking, setShaking] = useState(false); + + const shakeInput = () => { + setShaking(true); + setTimeout(() => setShaking(false), 250); + }; + + const handleContinue = async (otpCode: string) => { + try { + setSubmitting(true); + if (onContinue) { + await onContinue(otpCode); + } else { + await completeOtp({ + otpId, + otpCode, + contact, + otpType, + }); + closeModal(); + } + } catch (error) { + const niceError = (error as Error).message.includes("Invalid OTP") + ? "Invalid OTP code" + : "An error has occurred"; // eek! maybe this is bad! + setError(niceError); + shakeInput(); + throw new Error(`Error completing OTP: ${error}`); + } finally { + setSubmitting(false); + } + }; + + const handleResend = async () => { + setResending(true); + try { + const id = await initOtp({ otpType, contact }); + setOtpId(id); + setResent(true); + } catch (error) { + throw new Error(`Error resending OTP: ${error}`); + } finally { + setResending(false); + } + }; + + return ( +
+
+ + +
+ {`Enter the ${otpLength}-digit code we sent to`} + + {formattedContact ?? contact} + +
+ +
+ +
+ + {error && ( +
{error}
+ )} + + {resending ? ( + + + Resending... + + ) : resent ? ( + "Code sent!" + ) : ( + "Resend Code" + )} + +
+ {submitting && ( +
+ +
+ )} +
+ ); +} + +interface OtpInputProps { + otpLength: number; + onContinue: (otpCode: string) => void; + alphanumeric?: boolean; +} + +export function OtpInput(props: OtpInputProps) { + const { otpLength, onContinue, alphanumeric = false } = props; + const { isMobile } = useModal(); + const [values, setValues] = useState(Array(otpLength).fill("")); + const inputsRef = useRef>([]); + + const handleChange = (index: number, value: string) => { + if (!alphanumeric) value = value.replace(/[^0-9]/g, ""); + else value = value.replace(/[^a-zA-Z0-9]/g, ""); + + const newValues = [...values]; + newValues[index] = value.slice(-1); // only last char + setValues(newValues); + + if (value && index < otpLength - 1) { + inputsRef.current[index + 1]?.focus(); + } + if (value && newValues.every((v) => v)) { + onContinue(newValues.join("")); + } + }; + + const handleKeyDown = ( + e: React.KeyboardEvent, + index: number, + ) => { + if (e.key === "Backspace" && !values[index] && index > 0) { + inputsRef.current[index - 1]?.focus(); + } + + if (e.key === "ArrowLeft" && index > 0) { + inputsRef.current[index - 1]?.focus(); + } + + if (e.key === "ArrowRight" && index < otpLength - 1) { + inputsRef.current[index + 1]?.focus(); + } + + if (e.key === "Enter") { + onContinue(values.join("")); + } + }; + + const handlePaste = (e: React.ClipboardEvent) => { + e.preventDefault(); + const paste = e.clipboardData.getData("text").trim(); + + const cleaned = alphanumeric + ? paste.replace(/[^a-zA-Z0-9]/g, "") + : paste.replace(/[^0-9]/g, ""); + + const sliced = cleaned.slice(0, otpLength).split(""); + + const newValues = [...values]; + for (let i = 0; i < sliced.length; i++) { + newValues[i] = sliced[i] ?? ""; + if (inputsRef.current[i]) { + inputsRef.current[i]!.value = sliced[i] ?? ""; + } + } + + setValues(newValues); + + // Focus the last filled box + const lastIndex = Math.min(sliced.length, otpLength - 1); + inputsRef.current[lastIndex]?.focus(); + + onContinue(newValues.join("")); + }; + + return ( +
+ {Array.from({ length: otpLength }).map((_, i) => { + return ( + handleChange(i, e.target.value.toUpperCase())} + onKeyDown={(e) => handleKeyDown(e, i)} + onPaste={handlePaste} + ref={(el) => (inputsRef.current[i] = el as HTMLInputElement | null)} + className={clsx( + "text-center text-lg rounded-md border border-modal-background-dark/20 dark:border-modal-background-light/20 bg-button-light dark:bg-button-dark text-inherit focus:outline-primary-light focus:dark:outline-primary-dark focus:outline-[1px] focus:outline-offset-0 transition-all", + isMobile ? "w-full h-10" : "h-12 w-12", + )} + /> + ); + })} +
+ ); +} diff --git a/packages/react-wallet-kit/src/components/auth/OrSeparator.tsx b/packages/react-wallet-kit/src/components/auth/OrSeparator.tsx new file mode 100644 index 000000000..221fb0737 --- /dev/null +++ b/packages/react-wallet-kit/src/components/auth/OrSeparator.tsx @@ -0,0 +1,11 @@ +export function OrSeparator() { + return ( +
+
+ + OR + +
+
+ ); +} diff --git a/packages/react-wallet-kit/src/components/auth/Passkey.tsx b/packages/react-wallet-kit/src/components/auth/Passkey.tsx new file mode 100644 index 000000000..522e5af4e --- /dev/null +++ b/packages/react-wallet-kit/src/components/auth/Passkey.tsx @@ -0,0 +1,26 @@ +import { ActionButton } from "../design/Buttons"; + +interface PasskeyButtonsProps { + onLogin: () => void; + onSignUp: () => void; +} + +export function PasskeyButtons(props: PasskeyButtonsProps) { + const { onLogin, onSignUp } = props; + return ( +
+ + Log in with passkey + + + Sign up with passkey + +
+ ); +} diff --git a/packages/react-wallet-kit/src/components/auth/Phone.tsx b/packages/react-wallet-kit/src/components/auth/Phone.tsx new file mode 100644 index 000000000..b0d5d3c75 --- /dev/null +++ b/packages/react-wallet-kit/src/components/auth/Phone.tsx @@ -0,0 +1,88 @@ +import { useState } from "react"; +import { ActionButton, IconButton } from "../design/Buttons"; +import { PhoneInputBox } from "../design/Inputs"; +import { faArrowRight } from "@fortawesome/free-solid-svg-icons"; +import clsx from "clsx"; +import { useTurnkey } from "../../providers/client/Hook"; + +interface PhoneNumberInputProps { + onContinue?: (phone: string, formattedPhone: string) => void; +} + +export function PhoneNumberInput(props: PhoneNumberInputProps) { + const { config } = useTurnkey(); + const { onContinue } = props; + const [phone, setPhone] = useState(""); + const [formattedPhone, setFormattedPhone] = useState(""); + const [isValid, setIsValid] = useState(false); + const [loading, setLoading] = useState(false); + const useContinueButton = config?.ui?.preferLargeActionButtons ?? false; + + const handleContinue = async () => { + if (isValid && onContinue) { + setLoading(true); + try { + await Promise.resolve(onContinue(phone, formattedPhone)); + } finally { + setLoading(false); + } + } + }; + + const buttonDisabled = !isValid; + + const buttonClass = clsx( + "transition-all duration-300", + (isValid || useContinueButton) && + "bg-primary-light dark:bg-primary-dark hover:bg-primary-light/90 dark:hover:bg-primary-dark/90 text-primary-text-light dark:text-primary-text-dark", + ); + + return ( +
+
+ { + setPhone(raw); + setFormattedPhone(formatted); + setIsValid(valid); + }} + onEnter={handleContinue} + /> + + {!useContinueButton && ( + + )} +
+ + {useContinueButton && ( + + Continue + + )} +
+ ); +} diff --git a/packages/react-wallet-kit/src/components/auth/Wallet.tsx b/packages/react-wallet-kit/src/components/auth/Wallet.tsx new file mode 100644 index 000000000..118a522cb --- /dev/null +++ b/packages/react-wallet-kit/src/components/auth/Wallet.tsx @@ -0,0 +1,542 @@ +import { ActionButton } from "../design/Buttons"; +import { useModal } from "../../providers/modal/Hook"; +import { EthereumLogo, SolanaLogo } from "../design/Svg"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { + faChevronRight, + faClose, + faLaptop, + faMobileScreen, +} from "@fortawesome/free-solid-svg-icons"; +import { useEffect, useMemo, useRef, useState } from "react"; +import clsx from "clsx"; +import type { WalletProvider } from "@turnkey/core"; +import { QRCodeSVG as QRCode } from "qrcode.react"; +import { SuccessPage } from "../design/Success"; +import { isEthereumWallet } from "@turnkey/core"; +import { useTurnkey } from "../../providers/client/Hook"; + +interface WalletAuthButtonProps { + onContinue: () => Promise; +} +export function WalletAuthButton(props: WalletAuthButtonProps) { + const { onContinue } = props; + const [isLoading, setIsLoading] = useState(false); + + const handleContinue = async () => { + setIsLoading(true); + + try { + await Promise.resolve(onContinue()); + } finally { + setIsLoading(false); + } + }; + return ( +
+ + Continue with wallet + +
+ ); +} + +const canUnlink = (provider: WalletProvider, shouldShowUnlink?: boolean) => { + return ( + shouldShowUnlink && + provider.connectedAddresses && + provider.connectedAddresses.length > 0 + ); +}; + +export function ExternalWalletChainSelector( + props: ExternalWalletSelectorProps, +) { + const { providers, onSelect, onUnlink } = props; + const { isMobile } = useModal(); + const shouldShowUnlink = onUnlink !== undefined; + + const handleSelect = (provider: WalletProvider) => { + if (canUnlink(provider, shouldShowUnlink)) { + onUnlink!(provider); + } else { + onSelect(provider); + } + }; + + return ( +
+ + + {providers[0]?.info.name ?? "This wallet provider"} + {" supports multiple chains. Select which chain you would like to use."} + +
+ {providers.map((p) => { + const [isHovering, setIsHovering] = useState(false); + return ( + handleSelect(p)} + onMouseEnter={() => setIsHovering(true)} + onMouseLeave={() => setIsHovering(false)} + className="relative overflow-hidden flex items-center justify-start gap-2 w-full text-inherit bg-button-light dark:bg-button-dark" + > + {isEthereumWallet(p) ? ( +
+ + {canUnlink(p, shouldShowUnlink) && ( + + )} +
+ ) : ( +
+ + {canUnlink(p, shouldShowUnlink) && ( + + )} +
+ )} +
+ {isEthereumWallet(p) ? "EVM" : "Solana"} + {canUnlink(p, shouldShowUnlink) && ( + + Connected: {p.connectedAddresses[0]?.slice(0, 4)}... + {p.connectedAddresses[0]?.slice(-3)} + + )} +
+ +
+ ); + })} +
+
+ ); +} + +interface ExternalWalletSelectorProps { + providers: WalletProvider[]; + onUnlink?: ((provider: WalletProvider) => Promise) | undefined; + onSelect: (provider: WalletProvider) => Promise; +} +export function ExternalWalletSelector(props: ExternalWalletSelectorProps) { + const { providers, onUnlink, onSelect } = props; + const { pushPage, popPage, isMobile } = useModal(); + + const shouldShowUnlink = onUnlink !== undefined; + + // Group providers by name + const grouped = providers.reduce>( + (acc, provider) => { + const name = provider.info.name; + if (!acc[name]) acc[name] = []; + acc[name]!.push(provider); + return acc; + }, + {}, + ); + + const handleSelectGroup = (group: WalletProvider[]) => { + if (group.length === 1) { + if (canUnlink(group[0]!, shouldShowUnlink)) { + onUnlink!(group[0]!); + } else { + onSelect(group[0]!); + } + } else { + pushPage({ + key: `Select chain`, + content: ( + + ), + }); + } + }; + + useEffect(() => { + // Don't show the selector if there's only one wallet provider + const groupedValues = Object.values(grouped); + if (groupedValues.length === 1) { + popPage(); // Remove this page from the stack so user doesn't get stuck in an infinite loop when pressing back + handleSelectGroup(groupedValues[0]!); + } + }, [grouped]); + + return Object.keys(grouped).length === 0 ? ( +
+ + No wallet providers available. + + + Only wallets supporting EIP-1193 (Ethereum) or the Solana wallet + standard are supported. + +
+ ) : ( +
+
+ {Object.entries(grouped).map( + ([name, group]: [string, WalletProvider[]]) => { + const [isHovering, setIsHovering] = useState(false); + const first = group[0]; + + return ( + setIsHovering(true)} + onMouseLeave={() => setIsHovering(false)} + onClick={() => handleSelectGroup(group)} + className="relative flex items-center justify-between w-full text-inherit bg-button-light dark:bg-button-dark overflow-hidden" + > +
+ {first?.info.name} + {first?.info.name} +
+
+ {group.map((c, idx) => { + const Logo = isEthereumWallet(c) + ? EthereumLogo + : SolanaLogo; + const delay = 50 + idx * 30; // Staggered delay: leftmost has largest + return ( +
+ + {canUnlink(c, shouldShowUnlink) && ( + + )} +
+ ); + })} +
+ +
+ ); + }, + )} +
+
+ ); +} + +interface UnlinkWalletScreenProps { + provider: WalletProvider; + onUnlink: (provider: WalletProvider) => Promise; +} + +export function UnlinkWalletScreen(props: UnlinkWalletScreenProps) { + const { provider, onUnlink } = props; + const { isMobile } = useModal(); + const [isLoading, setIsLoading] = useState(false); + const [hasError, setHasError] = useState(false); + + const handleUnlink = async () => { + setIsLoading(true); + setHasError(false); + try { + await onUnlink(provider); + } catch (err) { + setHasError(true); + } finally { + setIsLoading(false); + } + }; + + return ( +
+
+ +
+ {hasError + ? "You can't unlink this wallet!" + : `Unlink ${provider.info.name}`} +
+
+ {hasError + ? `Try unlinking directly from the ${provider.info.name} app` + : "You can always link this wallet again later."} +
+
+ +
+ + Unlink Wallet + +
+
+ ); +} + +interface ConnectedIndicatorProps { + isPinging?: boolean; +} +export function ConnectedIndicator(props: ConnectedIndicatorProps) { + const { isPinging = false } = props; + return ( +
+ {isPinging && ( +
+ )} +
+
+ ); +} +export interface WalletConnectScreenProps { + provider: WalletProvider; + successPageDuration: number | undefined; + onAction: (provider: WalletProvider) => Promise; + onDisconnect?: (provider: WalletProvider) => Promise; +} + +export function WalletConnectScreen(props: WalletConnectScreenProps) { + const { provider, successPageDuration, onAction, onDisconnect } = props; + const { pushPage, closeModal, isMobile } = useModal(); + const { getWalletProviders } = useTurnkey(); + const hasRan = useRef(false); + + const [walletConnectProvider, setWalletConnectProvider] = + useState(); + const connectedAccount = walletConnectProvider?.connectedAddresses[0]; + + useEffect(() => { + setWalletConnectProvider(provider); + }, [provider]); + + const [isUnlinking, setIsUnlinking] = useState(false); + const [unlinkError, setUnlinkError] = useState(false); + + // kick off authentication/pairing or signing on mount or when URI changes + useMemo(() => { + (async () => { + if (hasRan.current) return; + try { + await onAction(walletConnectProvider ?? provider); + hasRan.current = true; + pushPage({ + key: "Link Success", + content: ( + + ), + preventBack: true, + showTitle: false, + }); + } catch (e) {} + })(); + }, [walletConnectProvider?.uri]); + + const handleUnlink = async () => { + setIsUnlinking(true); + setUnlinkError(false); + try { + await onDisconnect?.(walletConnectProvider ?? provider); + const newProviders = await getWalletProviders(); + setWalletConnectProvider( + newProviders.find((p) => p.interfaceType === provider.interfaceType), + ); + } catch (err) { + setUnlinkError(true); + } finally { + setIsUnlinking(false); + } + }; + return ( +
+ {connectedAccount ? ( +
+
+
+ +
+ +
+
+ Wallet connect logo + Wallet connect logo +
+ + + {connectedAccount?.slice(0, 3)}... + {connectedAccount?.slice(-3)} + +
+ +
+ +
+
+ +
+ Already connected +
+
+ + Please open the wallet app on your phone to sign the message. + + {isUnlinking ? ( + + Unlinking... + + ) : unlinkError ? ( + + Error unlinking wallet. + + ) : ( + + Need to connect a different wallet?{" "} + + Unlink + {" "} + this wallet first. + + )} +
+
+ ) : ( +
+ {walletConnectProvider?.uri && ( + // @ts-expect-error: qrcode.react uses a different React type version + + )} +
+ Use your phone +
+
+ Scan this QR code with your WalletConnect-compatible wallet to link +
+
+ )} +
+ ); +} diff --git a/packages/react-wallet-kit/src/components/auth/index.tsx b/packages/react-wallet-kit/src/components/auth/index.tsx new file mode 100644 index 000000000..718c55a92 --- /dev/null +++ b/packages/react-wallet-kit/src/components/auth/index.tsx @@ -0,0 +1,386 @@ +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { + faApple, + faFacebook, + faGoogle, +} from "@fortawesome/free-brands-svg-icons"; +import { OtpType, type WalletProvider } from "@turnkey/core"; +import { faFingerprint } from "@fortawesome/free-solid-svg-icons"; +import clsx from "clsx"; +import { OAuthButton } from "./OAuth"; +import { EmailInput } from "./Email"; +import { OrSeparator } from "./OrSeparator"; +import { OtpVerification } from "./OTP"; +import { PhoneNumberInput } from "./Phone"; +import { ActionPage } from "./Action"; +import { PasskeyButtons } from "./Passkey"; +import { Spinner } from "../design/Spinners"; +import { + ExternalWalletSelector, + WalletAuthButton, + WalletConnectScreen, +} from "./Wallet"; +import { DeveloperError } from "../design/Failure"; +import { useModal } from "../../providers/modal/Hook"; +import { useTurnkey } from "../../providers/client/Hook"; +import { ClientState } from "../../types/base"; +import { isWalletConnect } from "@utils"; + +export function AuthComponent() { + const { + config, + clientState, + handleGoogleOauth, + handleAppleOauth, + handleFacebookOauth, + initOtp, + loginWithPasskey, + signUpWithPasskey, + getWalletProviders, + loginOrSignupWithWallet, + disconnectWalletAccount, + } = useTurnkey(); + const { pushPage, isMobile } = useModal(); + + if (!config || clientState === ClientState.Loading) { + // Don't check ClientState.Error here. We already check in the modal root + return ( +
+ +
+ ); + } + + const { methods = {}, methodOrder = [], oauthOrder = [] } = config.auth || {}; + + const handleEmailSubmit = async (email: string) => { + try { + const otpId = await initOtp({ otpType: OtpType.Email, contact: email }); + pushPage({ + key: "Verify OTP", + content: ( + + ), + showTitle: false, + }); + } catch (error) { + throw new Error(`Error initializing OTP: ${error}`); + } + }; + + const handlePhoneSubmit = async (phone: string, formattedPhone: string) => { + try { + const otpId = await initOtp({ + otpType: OtpType.Sms, + contact: phone, + }); + pushPage({ + key: "Verify OTP", + content: ( + + ), + showTitle: false, + }); + } catch (error) { + throw new Error(`Error initializing OTP: ${error}`); + } + }; + + const handlePasskeyLogin = () => { + pushPage({ + key: "Passkey Login", + content: ( + { + await loginWithPasskey({}); + }} + icon={} + /> + ), + showTitle: false, + }); + }; + + const handlePasskeySignUp = () => { + pushPage({ + key: "Passkey Sign Up", + content: ( + { + await signUpWithPasskey({}); + }} + icon={} + /> + ), + showTitle: false, + }); + }; + + const handleGoogle = async () => { + pushPage({ + key: "Google OAuth", + content: ( + + handleGoogleOauth({ + additionalState: { openModal: "true" }, // Tell the provider to reopen the auth modal and show the loading state + }) + } + icon={} + /> + ), + showTitle: false, + }); + }; + + const handleApple = async () => { + pushPage({ + key: "Apple OAuth", + content: ( + + handleAppleOauth({ + additionalState: { openModal: "true" }, // Tell the provider to reopen the auth modal and show the loading state + }) + } + icon={} + /> + ), + showTitle: false, + }); + }; + + const handleFacebook = async () => { + pushPage({ + key: "Facebook OAuth", + content: ( + + handleFacebookOauth({ + additionalState: { openModal: "true" }, // Tell the provider to reopen the auth modal and show the loading state + }) + } + icon={} + /> + ), + showTitle: false, + }); + }; + + const handleWalletLoginOrSignup = async (provider: WalletProvider) => { + pushPage({ + key: "Wallet Login/Signup", + content: ( + { + await loginOrSignupWithWallet({ + walletProvider: provider, + }); + }} + icon={ + + } + /> + ), + showTitle: false, + }); + }; + + const handleSelect = async (provider: WalletProvider) => { + // this is a wallet connect provider, so we need to show the WalletConnect screen + if (isWalletConnect(provider)) { + // for WalletConnect we route to a dedicated screen + // to handle the connection process, as it requires a different flow (pairing via QR code or deep link) + pushPage({ + key: "Link WalletConnect", + content: ( + { + await loginOrSignupWithWallet({ walletProvider: provider }); + }} + onDisconnect={async (provider) => { + await disconnectWalletAccount(provider); + }} + successPageDuration={undefined} + /> + ), + }); + return; + } + + // this is a regular wallet provider, so we can just select it + await handleWalletLoginOrSignup(provider); + }; + + const handleShowWalletSelector = async () => { + try { + const walletProviders = await getWalletProviders(); + + pushPage({ + key: "Select wallet provider", + content: ( + + ), + }); + } catch (error) { + throw new Error(`Error fetching wallet providers: ${error}`); + } + }; + + const oauthButtonMap: Record = { + google: methods.googleOauthEnabled ? ( + } + onClick={handleGoogle} + /> + ) : null, + apple: methods.appleOauthEnabled ? ( + } + onClick={handleApple} + /> + ) : null, + facebook: methods.facebookOauthEnabled ? ( + } + onClick={handleFacebook} + /> + ) : null, + }; + + const oauthButtons = oauthOrder + .map((provider) => oauthButtonMap[provider]) + .filter(Boolean); + + const oauthBlock = + oauthButtons.length > 0 ? ( +
+ {oauthButtons} +
+ ) : null; + + // -- Individual Auth Method Components -- + const methodComponents: Record = { + socials: oauthBlock, + email: methods.emailOtpAuthEnabled ? ( + + ) : null, + sms: methods.smsOtpAuthEnabled ? ( + + ) : null, + passkey: methods.passkeyAuthEnabled ? ( + + ) : null, + wallet: methods.walletAuthEnabled ? ( + + ) : null, + }; + + // -- Final Rendering Order -- + const rendered = methodOrder + .map((key) => methodComponents[key]) + .filter(Boolean); + + return ( +
+ {config.authProxyConfigId ? ( + rendered.length > 0 ? ( + <> +
+ {rendered.map((component, index) => ( +
+ {index > 0 && } + {component} +
+ ))} + + ) : ( + + ) + ) : ( + + )} + +
+ + By continuing, you agree to our{" "} + + Terms of Service + {" "} + &{" "} + + Privacy Policy + + {"."} + +
+
+ ); +} diff --git a/packages/react-wallet-kit/src/components/design/Buttons.tsx b/packages/react-wallet-kit/src/components/design/Buttons.tsx new file mode 100644 index 000000000..5b264376b --- /dev/null +++ b/packages/react-wallet-kit/src/components/design/Buttons.tsx @@ -0,0 +1,103 @@ +import type { IconDefinition } from "@fortawesome/fontawesome-svg-core"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { _internal_ComponentButton } from "@headlessui/react"; +import clsx from "clsx"; +import { Spinner } from "./Spinners"; + +interface IconButtonProps { + icon: IconDefinition; + onClick?: () => void; + disabled?: boolean; + loading?: boolean; + className?: string; + spinnerClassName?: string; +} + +export function BaseButton( + props: React.ButtonHTMLAttributes, +) { + const { children, className, disabled, ...buttonProps } = props; + + return ( + + ); +} +export function IconButton(props: IconButtonProps) { + const { icon, onClick, disabled, loading, className, spinnerClassName } = + props; + return ( + + {loading ? ( +
+ +
+ ) : ( + + )} +
+ ); +} + +interface ActionButtonProps { + children: React.ReactNode; + onClick?: () => void; + onMouseEnter?: () => void; + onMouseLeave?: () => void; + disabled?: boolean; + loading?: boolean; + loadingText?: string; + className?: string; + spinnerClassName?: string; +} + +export function ActionButton(props: ActionButtonProps) { + const { + children, + onClick, + onMouseEnter, + onMouseLeave, + disabled, + loading, + loadingText, + className, + spinnerClassName, + } = props; + return ( + + {loading ? ( +
+ + {loadingText && ( + {loadingText} + )} +
+ ) : ( + children + )} +
+ ); +} diff --git a/packages/react-wallet-kit/src/components/design/Failure.tsx b/packages/react-wallet-kit/src/components/design/Failure.tsx new file mode 100644 index 000000000..94a15d874 --- /dev/null +++ b/packages/react-wallet-kit/src/components/design/Failure.tsx @@ -0,0 +1,37 @@ +interface DeveloperErrorProps { + developerTitle?: string; + developerMessages?: string[]; + userTitle?: string; + userMessages?: string[]; +} + +export function DeveloperError(props: DeveloperErrorProps) { + const { + developerTitle = "Developer Error", + developerMessages, + userTitle, + userMessages, + } = props; + + const isDev = process.env.NODE_ENV === "development"; + return ( +
+ + {isDev ? developerTitle : userTitle} + + {isDev + ? developerMessages?.map((msg, index) => ( +
+
+ {msg} +
+ )) + : userMessages?.map((msg, index) =>
{msg}
)} + {isDev && ( +
+ You will only see this error if you are a developer! +
+ )} +
+ ); +} diff --git a/packages/react-wallet-kit/src/components/design/Inputs.tsx b/packages/react-wallet-kit/src/components/design/Inputs.tsx new file mode 100644 index 000000000..311252e32 --- /dev/null +++ b/packages/react-wallet-kit/src/components/design/Inputs.tsx @@ -0,0 +1,261 @@ +import { + usePhoneInput, + parseCountry, + defaultCountries, + FlagImage as OriginalFlagImage, +} from "react-international-phone"; +import { + Input, + ListboxButton, + ListboxOption, + ListboxOptions, +} from "@headlessui/react"; +import { Listbox } from "@headlessui/react"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faChevronDown } from "@fortawesome/free-solid-svg-icons"; +import parsePhoneNumberFromString from "libphonenumber-js"; + +const FlagImage = OriginalFlagImage as React.ElementType; + +// Supported country dial codes +const supported_country_codes = [ + "+1", + "+33", + "+420", + "+358", + "+49", + "+30", + "+36", + "+354", + "+353", + "+39", + "+371", + "+370", + "+352", + "+356", + "+373", + "+382", + "+31", + "+47", + "+48", + "+351", + "+40", + "+381", + "+386", + "+34", + "+46", + "+41", + "+355", + "+376", + "+244", + "+54", + "+374", + "+61", + "+43", + "+994", + "+1242", + "+973", + "+880", + "+1246", + "+32", + "+501", + "+229", + "+591", + "+387", + "+267", + "+55", + "+1284", + "+673", + "+237", + "+238", + "+1345", + "+235", + "+56", + "+57", + "+506", + "+385", + "+599", + "+357", + "+243", + "+45", + "+253", + "+1767", + "+593", + "+503", + "+240", + "+372", + "+298", + "+679", + "+689", + "+220", + "+995", + "+233", + "+350", + "+1473", + "+502", + "+590", + "+224", + "+592", + "+509", + "+504", + "+852", + "+91", + "+62", + "+972", + "+225", + "+1876", + "+81", + "+383", + "+965", + "+996", + "+856", + "+961", + "+266", + "+231", + "+261", + "+60", + "+960", + "+223", + "+230", + "+52", + "+373", + "+976", + "+212", + "+258", + "+264", + "+977", + "+64", + "+505", + "+227", + "+234", + "+92", + "+507", + "+51", + "+63", + "+1787", + "+1939", + "+974", + "+262", + "+1758", + "+1784", + "+685", + "+966", + "+221", + "+248", + "+232", + "+65", + "+27", + "+82", + "+597", + "+268", + "+992", + "+255", + "+66", + "+228", + "+1868", + "+216", + "+598", + "+998", + "+58", +]; + +const countries = defaultCountries.filter((country) => { + const { dialCode } = parseCountry(country); + return supported_country_codes.includes(`+${dialCode}`); +}); + +export interface PhoneInputBoxProps { + value: string; + onChange: (phone: string, formattedPhone: string, isValid: boolean) => void; + onFocus?: () => void; + onBlur?: () => void; + onEnter?: () => void; +} + +const isValidPhone = (phone: string) => { + const phoneNumber = parsePhoneNumberFromString(phone); + return phoneNumber?.isValid() ?? false; +}; + +export function PhoneInputBox(props: PhoneInputBoxProps) { + const { value, onChange, onFocus, onBlur, onEnter } = props; + const { inputValue, handlePhoneValueChange, inputRef, country, setCountry } = + usePhoneInput({ + value, + defaultCountry: "us", + disableDialCodeAndPrefix: true, + countries, + onChange: (data) => { + onChange( + data.phone, + `+${data.country.dialCode} ${data.inputValue}`, + isValidPhone(data.phone), + ); + }, + }); + + return ( +
+ +
+ +
+ +
+ +{country.dialCode} +
+
+ + +
+ + + {countries.map((c) => { + const { iso2, name, dialCode } = parseCountry(c); + return ( + + `cursor-pointer select-none py-2 px-3 bg-button-light dark:bg-button-dark flex items-center gap-2 ${ + active + ? "bg-modal-background-light dark:bg-modal-background-dark" + : "" + }` + } + > + + {name} + + +{dialCode} + + + ); + })} + +
+
+ + { + if (e.key === "Enter") onEnter?.(); + }} + placeholder="Phone number" + className="w-full py-3 bg-transparent border-none text-inherit placeholder-icon-text-light dark:placeholder-icon-text-dark focus:outline-none focus:ring-0 focus:border-none" + /> +
+ ); +} diff --git a/packages/react-wallet-kit/src/components/design/Lottie/Dynamic.tsx b/packages/react-wallet-kit/src/components/design/Lottie/Dynamic.tsx new file mode 100644 index 000000000..fd82e809a --- /dev/null +++ b/packages/react-wallet-kit/src/components/design/Lottie/Dynamic.tsx @@ -0,0 +1,4 @@ +export async function getLottiePlayer() { + const mod = await import("@lottiefiles/react-lottie-player"); + return mod.Player; +} diff --git a/packages/react-wallet-kit/src/components/design/Lottie/Wrapper.tsx b/packages/react-wallet-kit/src/components/design/Lottie/Wrapper.tsx new file mode 100644 index 000000000..bed8ad5b6 --- /dev/null +++ b/packages/react-wallet-kit/src/components/design/Lottie/Wrapper.tsx @@ -0,0 +1,24 @@ +import { useEffect, useState } from "react"; + +export default function LottiePlayerWrapper(props: { + style?: React.CSSProperties; + src: string; + autoplay?: boolean; + loop?: boolean; +}) { + const [PlayerComponent, setPlayerComponent] = + useState | null>(null); + + useEffect(() => { + if (typeof window !== "undefined") { + import("./Dynamic").then(async (mod) => { + const Player = await mod.getLottiePlayer(); + //@ts-ignore + setPlayerComponent(() => Player); + }); + } + }, []); + + if (!PlayerComponent) return null; + return ; +} diff --git a/packages/react-wallet-kit/src/components/design/Spinners.tsx b/packages/react-wallet-kit/src/components/design/Spinners.tsx new file mode 100644 index 000000000..dada61296 --- /dev/null +++ b/packages/react-wallet-kit/src/components/design/Spinners.tsx @@ -0,0 +1,33 @@ +import clsx from "clsx"; + +interface SpinnerProps { + className?: string; + style?: React.CSSProperties; + strokeWidth?: number; +} + +export function Spinner(props: SpinnerProps) { + const { className, style, strokeWidth = 3, ...rest } = props; + return ( + + + + + + + ); +} diff --git a/packages/react-wallet-kit/src/components/design/Success.tsx b/packages/react-wallet-kit/src/components/design/Success.tsx new file mode 100644 index 000000000..8668e79c0 --- /dev/null +++ b/packages/react-wallet-kit/src/components/design/Success.tsx @@ -0,0 +1,80 @@ +import { faCheck } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import clsx from "clsx"; +import { useEffect, useState } from "react"; +import { useModal } from "../../providers/modal/Hook"; +import LottiePlayerWrapper from "./Lottie/Wrapper"; + +interface SuccessPageProps { + text?: string | undefined; + duration?: number | undefined; + onComplete: () => void; +} + +export function SuccessPage(props: SuccessPageProps) { + const { text = "Success", duration = 2000, onComplete } = props; + const [pulsing, setPulsing] = useState(false); + const { isMobile } = useModal(); + const [scale, setScale] = useState(0); + + useEffect(() => { + setScale(1); + const pulseTimer = setTimeout(() => { + setPulsing(true); + }, 300); + const totalTimer = setTimeout(() => { + onComplete(); + }, duration); + return () => { + clearTimeout(totalTimer); + clearTimeout(pulseTimer); + }; + }, [duration, onComplete]); + + return ( +
+
+
+ + {pulsing && ( + + )} +
+ + {/*@ts-ignore. I have no idea how to fix this error */} + +
+

{text}

+
+ ); +} diff --git a/packages/react-wallet-kit/src/components/design/Svg.tsx b/packages/react-wallet-kit/src/components/design/Svg.tsx new file mode 100644 index 000000000..cc5724062 --- /dev/null +++ b/packages/react-wallet-kit/src/components/design/Svg.tsx @@ -0,0 +1,169 @@ +interface SVGProps { + className?: string; + style?: React.CSSProperties; +} + +export function TurnkeyLogo(props: SVGProps) { + return ( + + + + + + + + + + + + + ); +} + +export function EthereumLogo(props: SVGProps) { + return ( + + + + + + + + + ); +} + +export function SolanaLogo(props: SVGProps) { + return ( + + + + + + + + + + + + + + + + + + ); +} diff --git a/packages/react-wallet-kit/src/components/export/Export.tsx b/packages/react-wallet-kit/src/components/export/Export.tsx new file mode 100644 index 000000000..b6fa1be60 --- /dev/null +++ b/packages/react-wallet-kit/src/components/export/Export.tsx @@ -0,0 +1,210 @@ +import { useEffect, useState } from "react"; +import { useModal } from "../../providers/modal/Hook"; +import { useTurnkey } from "../../providers/client/Hook"; +import { IframeStamper } from "@turnkey/iframe-stamper"; +import { TurnkeyError, TurnkeyErrorCodes } from "@turnkey/sdk-types"; +import { ExportWarning } from "./ExportWarning"; +import { ActionButton } from "../design/Buttons"; +import { + type Address, + type WalletId, + type PrivateKeyId, + ExportType, +} from "../../types/base"; +import clsx from "clsx"; +import type { StamperType } from "@turnkey/core"; + +const TurnkeyExportIframeContainerId = "turnkey-export-iframe-container-id"; +const TurnkeyIframeElementId = "turnkey-default-iframe-element-id"; +const TurnkeyIframeClassNames = + "w-full border-none !text-base bg-icon-background-light dark:bg-icon-background-dark"; + +// IMPORTANT: These colors need to match --icon-text-light, --icon-background-light, --icon-background-dark and --icon-text-dark in index.css +const iconBackgroundLight = "#e5e7eb"; +const iconBackgroundDark = "#333336"; +const iconTextLight = "#828282"; +const iconTextDark = "#a3a3a5"; + +export function ExportComponent(params: { + target: WalletId | PrivateKeyId | Address; + exportType: ExportType; + targetPublicKey?: string; + stampWith?: StamperType | undefined; +}) { + const { exportType, targetPublicKey, stampWith, target } = params; + const { config } = useTurnkey(); + + const [exportIframeVisible, setExportIframeVisible] = useState(false); + + const { closeModal, isMobile } = useModal(); + + const apiBaseUrl = config?.apiBaseUrl; + const exportIframeUrl = config?.exportIframeUrl; + + if (!exportIframeUrl || !apiBaseUrl) { + throw new TurnkeyError( + "Export iframe URL or API base URL is not configured. Please set them in the Turnkey configuration.", + TurnkeyErrorCodes.NOT_FOUND, + ); + } + + const [exportIframeClient, setExportIframeClient] = + useState(null); + + if (!apiBaseUrl) { + throw new TurnkeyError( + "API base URL is not configured. Please set it in the Turnkey configuration.", + TurnkeyErrorCodes.INVALID_CONFIGURATION, + ); + } + + useEffect(() => { + const initIframe = async () => { + try { + const newExportIframeClient = new IframeStamper({ + iframeUrl: exportIframeUrl, + iframeElementId: TurnkeyIframeElementId, + iframeContainer: document.getElementById( + TurnkeyExportIframeContainerId, + ), + }); + await newExportIframeClient.init(); + await newExportIframeClient.applySettings({ + styles: { + fontSize: "16px", + backgroundColor: config?.ui?.darkMode + ? config?.ui?.colors?.dark?.iconBackground || iconBackgroundDark + : config?.ui?.colors?.light?.iconBackground || + iconBackgroundLight, + color: config?.ui?.darkMode + ? config?.ui?.colors?.dark?.iconText || iconTextDark + : config?.ui?.colors?.light?.iconText || iconTextLight, + }, + }); + setExportIframeClient(newExportIframeClient); + } catch (error) { + throw new TurnkeyError( + `Error initializing IframeStamper`, + TurnkeyErrorCodes.INITIALIZE_IFRAME_ERROR, + error, + ); + } + }; + + const existingIframe = document.getElementById(TurnkeyIframeElementId); + if (!existingIframe) { + initIframe(); + } + + const iframeElement = document.getElementById(TurnkeyIframeElementId); + if (iframeElement) { + iframeElement.className = TurnkeyIframeClassNames; + } + return () => { + handleExportModalClose(); + }; + }, []); + + useEffect(() => { + const reapplyIframeStyles = async () => { + await exportIframeClient?.applySettings({ + styles: { + fontSize: "16px", + backgroundColor: config?.ui?.darkMode + ? config?.ui?.colors?.dark?.iconBackground || iconBackgroundDark + : config?.ui?.colors?.light?.iconBackground || iconBackgroundLight, + color: config?.ui?.darkMode + ? config?.ui?.colors?.dark?.iconText || iconTextDark + : config?.ui?.colors?.light?.iconText || iconTextLight, + }, + }); + }; + reapplyIframeStyles(); + }, [config.ui]); + + function handleExportModalClose() { + if (exportIframeClient) { + setExportIframeClient(null); + + const existingIframe = document.getElementById(TurnkeyIframeElementId); + if (existingIframe) { + existingIframe.remove(); + } + } + } + + return ( +
+ {!exportIframeVisible && ( + + )} +
+

+ {exportType === ExportType.Wallet ? ( + <> + Your seed phrase is the key to your wallet. Save it in a secure + location. + + ) : exportType === ExportType.WalletAccount ? ( + <> + Your private key is the key to your wallet account. Save it in a + secure location. + + ) : ( + <> + Your private key is the key to your account. Save it in a secure + location. + + )} +

+
+ +
+ + Done + +
+
+
+ ); +} diff --git a/packages/react-wallet-kit/src/components/export/ExportWarning.tsx b/packages/react-wallet-kit/src/components/export/ExportWarning.tsx new file mode 100644 index 000000000..00662d163 --- /dev/null +++ b/packages/react-wallet-kit/src/components/export/ExportWarning.tsx @@ -0,0 +1,165 @@ +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { + faTriangleExclamation, + IconDefinition, + faUnlock, + faEye, +} from "@fortawesome/free-solid-svg-icons"; +import type { StamperType } from "@turnkey/core"; +import { + type Address, + type WalletId, + type PrivateKeyId, + ExportType, +} from "../../types/base"; +import { useTurnkey } from "../../providers/client/Hook"; +import { TurnkeyError, TurnkeyErrorCodes } from "@turnkey/sdk-types"; +import { ActionButton } from "../design/Buttons"; +import type { IframeStamper } from "@turnkey/iframe-stamper"; +import { useState } from "react"; + +export function ExportWarning(props: { + target: WalletId | PrivateKeyId | Address; + exportIframeClient?: IframeStamper | null; // Replace with actual type if available + targetPublicKey?: string | undefined; + exportType: ExportType; + setExportIframeVisible?: (visible: boolean) => void; + stampWith?: StamperType | undefined; +}) { + const { target, exportIframeClient, targetPublicKey, exportType, stampWith } = + props; + + const [isLoading, setIsLoading] = useState(false); + + const { exportWallet, exportPrivateKey, exportWalletAccount, session } = + useTurnkey(); + + const warnings: Record = { + [ExportType.Wallet]: [ + "Keep your seed phrase private.", + "Anyone who has your seed phrase can access your wallet.", + "Make sure nobody can see your screen when viewing your seed phrase.", + ], + [ExportType.PrivateKey]: [ + "Keep your private key private.", + "Anyone who has your private key can access your wallet.", + "Make sure nobody can see your screen when viewing your private key.", + ], + [ExportType.WalletAccount]: [ + "Keep your account details private.", + "Anyone who has your account details can access your wallet.", + "Make sure nobody can see your screen when viewing your account details.", + ], + }; + + return ( +
+
+ + + +
+ { + setIsLoading(true); + try { + let exportBundle; + switch (exportType) { + case ExportType.Wallet: + exportBundle = await exportWallet({ + walletId: target, + targetPublicKey: + targetPublicKey || exportIframeClient?.iframePublicKey!, + ...(stampWith && { stampWith: stampWith }), + }); + if (!exportBundle) { + throw new TurnkeyError( + "Failed to retrieve export bundle", + TurnkeyErrorCodes.EXPORT_WALLET_ERROR, + ); + } + await exportIframeClient?.injectWalletExportBundle( + exportBundle, + session?.organizationId!, + ); + break; + case ExportType.PrivateKey: + exportBundle = await exportPrivateKey({ + privateKeyId: target, + targetPublicKey: + targetPublicKey || exportIframeClient?.iframePublicKey!, + ...(stampWith && { stampWith: stampWith }), + }); + if (!exportBundle) { + throw new TurnkeyError( + "Failed to retrieve export bundle", + TurnkeyErrorCodes.EXPORT_WALLET_ERROR, + ); + } + await exportIframeClient?.injectKeyExportBundle( + exportBundle, + session?.organizationId!, + ); + break; + case ExportType.WalletAccount: + exportBundle = await exportWalletAccount({ + address: target, + targetPublicKey: + targetPublicKey || exportIframeClient?.iframePublicKey!, + ...(stampWith && { stampWith: stampWith }), + }); + if (!exportBundle) { + throw new TurnkeyError( + "Failed to retrieve export bundle", + TurnkeyErrorCodes.EXPORT_WALLET_ERROR, + ); + } + await exportIframeClient?.injectKeyExportBundle( + exportBundle, + session?.organizationId!, + ); + break; + default: + throw new TurnkeyError( + "Invalid export type", + TurnkeyErrorCodes.EXPORT_WALLET_ERROR, + ); + } + if (props.setExportIframeVisible) { + props.setExportIframeVisible(true); + } + } catch (error) { + throw new TurnkeyError( + `Error exporting wallet`, + TurnkeyErrorCodes.EXPORT_WALLET_ERROR, + error, + ); + } finally { + setIsLoading(false); + } + }} + > + {exportType === ExportType.PrivateKey + ? "Export Private Key" + : "Export Wallet"} + +
+ ); +} + +function IconText(props: { icon: IconDefinition; text: string }) { + return ( +
+
+ +
+ {props.text} +
+ ); +} diff --git a/packages/react-wallet-kit/src/components/import/Import.tsx b/packages/react-wallet-kit/src/components/import/Import.tsx new file mode 100644 index 000000000..55ad04bf5 --- /dev/null +++ b/packages/react-wallet-kit/src/components/import/Import.tsx @@ -0,0 +1,326 @@ +import { useEffect, useState } from "react"; +import { useModal } from "../../providers/modal/Hook"; +import { useTurnkey } from "../../providers/client/Hook"; +import { IframeStamper } from "@turnkey/iframe-stamper"; +import { + TurnkeyError, + TurnkeyErrorCodes, + v1AddressFormat, + v1WalletAccountParams, +} from "@turnkey/sdk-types"; +import { ActionButton } from "../design/Buttons"; +import { Input } from "@headlessui/react"; +import { + type StamperType, + generateWalletAccountsFromAddressFormat, +} from "@turnkey/core"; +import { SuccessPage } from "../design/Success"; +import clsx from "clsx"; + +const TurnkeyImportIframeContainerId = "turnkey-import-iframe-container-id"; +const TurnkeyIframeElementId = "turnkey-default-iframe-element-id"; +const TurnkeyIframeClassNames = + "w-full h-full overflow-hidden border-none !text-base bg-icon-background-light dark:bg-icon-background-dark"; + +// IMPORTANT: These colors need to match --icon-text-light, --icon-background-light, --icon-background-dark and --icon-text-dark in index.css +const iconBackgroundLight = "#e5e7eb"; +const iconBackgroundDark = "#333336"; +const iconTextLight = "#828282"; +const iconTextDark = "#a3a3a5"; + +export function ImportComponent(params: { + defaultWalletAccounts?: v1AddressFormat[] | v1WalletAccountParams[]; + onSuccess: (walletId: string) => void; + onError: (error: TurnkeyError) => void; + successPageDuration?: number | undefined; // Duration in milliseconds for the success page to show. If 0, it will not show the success page. + stampWith?: StamperType | undefined; +}) { + const { + onSuccess, + onError, + defaultWalletAccounts, + successPageDuration, + stampWith, + } = params; + + const { config, session, importWallet, httpClient } = useTurnkey(); + const [walletName, setWalletName] = useState(""); + const [isLoading, setIsLoading] = useState(false); + const [error, setError] = useState(null); + + const [shaking, setShaking] = useState(false); + + const shakeInput = () => { + setShaking(true); + setTimeout(() => setShaking(false), 250); + }; + + const apiBaseUrl = config?.apiBaseUrl; + const importIframeUrl = config?.importIframeUrl!; + + const { closeModal, pushPage, isMobile } = useModal(); + + const [importIframeClient, setImportIframeClient] = + useState(null); + + if (!apiBaseUrl) { + throw new TurnkeyError( + "API base URL is not configured. Please set it in the Turnkey configuration.", + ); + } + + useEffect(() => { + const initIframe = async () => { + try { + const newImportIframeClient = new IframeStamper({ + iframeUrl: importIframeUrl, + iframeElementId: TurnkeyIframeElementId, + iframeContainer: document.getElementById( + TurnkeyImportIframeContainerId, + ), + }); + await newImportIframeClient.init(); + await newImportIframeClient.applySettings({ + styles: { + fontSize: "16px", + // IMPORTANT: These colors need to match --icon-text-light and --icon-text-dark in index.css + backgroundColor: config?.ui?.darkMode + ? config?.ui?.colors?.dark?.iconBackground || iconBackgroundDark + : config?.ui?.colors?.light?.iconBackground || + iconBackgroundLight, + color: config?.ui?.darkMode + ? config?.ui?.colors?.dark?.iconText || iconTextDark + : config?.ui?.colors?.light?.iconText || iconTextLight, + }, + }); + setImportIframeClient(newImportIframeClient); + } catch (error) { + throw new TurnkeyError( + `Error initializing IframeStamper`, + TurnkeyErrorCodes.INTERNAL_ERROR, + error, + ); + } + }; + + const existingIframe = document.getElementById(TurnkeyIframeElementId); + if (!existingIframe) { + initIframe(); + } + + const iframeElement = document.getElementById(TurnkeyIframeElementId); + + if (iframeElement) { + iframeElement.className = TurnkeyIframeClassNames; + } + + return () => { + handleImportModalClose(); + }; + }, []); + + useEffect(() => { + const reapplyIframeStyles = async () => { + await importIframeClient?.applySettings({ + styles: { + fontSize: "16px", + backgroundColor: config?.ui?.darkMode + ? config?.ui?.colors?.dark?.iconBackground || iconBackgroundDark + : config?.ui?.colors?.light?.iconBackground || iconBackgroundLight, + color: config?.ui?.darkMode + ? config?.ui?.colors?.dark?.iconText || iconTextDark + : config?.ui?.colors?.light?.iconText || iconTextLight, + }, + }); + }; + reapplyIframeStyles(); + }, [config.ui]); + + function handleImportModalClose() { + if (importIframeClient) { + setImportIframeClient(null); + + const existingIframe = document.getElementById(TurnkeyIframeElementId); + if (existingIframe) { + existingIframe.remove(); + } + } + } + + async function handleImport() { + setIsLoading(true); + try { + if (!importIframeClient) { + throw new TurnkeyError( + "Import iframe client not initialized", + TurnkeyErrorCodes.INTERNAL_ERROR, + ); + } + const initResult = await httpClient?.initImportWallet({ + organizationId: session?.organizationId!, + userId: session?.userId!, + }); + + if (!initResult || !initResult.importBundle) { + throw new TurnkeyError( + "Failed to retrieve import bundle", + TurnkeyErrorCodes.IMPORT_WALLET_ERROR, + ); + } + + const injected = await importIframeClient.injectImportBundle( + initResult.importBundle, + session?.organizationId!, + session?.userId!, + ); + + if (!injected) { + throw new TurnkeyError( + "Failed to inject import bundle", + TurnkeyErrorCodes.IMPORT_WALLET_ERROR, + ); + } + const encryptedBundle = + await importIframeClient.extractWalletEncryptedBundle(); + if (!encryptedBundle || encryptedBundle.trim() === "") { + throw new TurnkeyError( + "Encrypted bundle is empty", + TurnkeyErrorCodes.IMPORT_WALLET_ERROR, + ); + } + + let accounts: v1WalletAccountParams[] = []; + if ( + Array.isArray(defaultWalletAccounts) && + defaultWalletAccounts.length > 0 && + (defaultWalletAccounts as any[])[0]?.addressFormat === undefined + ) { + accounts = generateWalletAccountsFromAddressFormat({ + addresses: defaultWalletAccounts as v1AddressFormat[], + }); + } else if (Array.isArray(defaultWalletAccounts)) { + accounts = defaultWalletAccounts as v1WalletAccountParams[]; + } + + const response = await importWallet({ + walletName: walletName, + accounts, + encryptedBundle, + stampWith, + }); + + if (response) { + onSuccess(response); + if (successPageDuration && successPageDuration !== 0) { + pushPage({ + key: "success", + content: ( + { + handleImportModalClose(); + closeModal(); + }} + /> + ), + preventBack: true, + showTitle: false, + }); + } else { + handleImportModalClose(); + closeModal(); + } + handleImportModalClose(); + } else { + await importIframeClient.clear(); + throw new TurnkeyError( + "Failed to import wallet", + TurnkeyErrorCodes.IMPORT_WALLET_ERROR, + ); + } + } catch (error) { + shakeInput(); + setError( + error instanceof TurnkeyError + ? error + : new TurnkeyError( + `Error importing wallet`, + TurnkeyErrorCodes.IMPORT_WALLET_ERROR, + error, + ), + ); + + if (error instanceof TurnkeyError) onError(error); + throw new TurnkeyError( + `Error importing wallet`, + TurnkeyErrorCodes.IMPORT_WALLET_ERROR, + error, + ); + } finally { + setIsLoading(false); + } + } + + return ( +
+

+ Enter your seed phrase. Seed phrases are typically 12-24 words. +

+
+ setWalletName(e.target.value)} + className="placeholder:text-icon-text-light dark:placeholder:text-icon-text-dark w-full my-2 py-3 px-3 rounded-md text-inherit bg-icon-background-light dark:bg-icon-background-dark border border-modal-background-dark/20 dark:border-modal-background-light/20 focus:outline-primary-light focus:dark:outline-primary-dark focus:outline-[1px] focus:outline-offset-0 box-border" + /> + + Import + +

+ {error?.message}:{" "} + {error?.cause instanceof TurnkeyError + ? error?.cause.message + : error?.cause?.toString() || "Unknown error"} +

+
+ ); +} diff --git a/packages/react-wallet-kit/src/components/sign/Message.tsx b/packages/react-wallet-kit/src/components/sign/Message.tsx new file mode 100644 index 000000000..cfec063ba --- /dev/null +++ b/packages/react-wallet-kit/src/components/sign/Message.tsx @@ -0,0 +1,160 @@ +import { Textarea } from "@headlessui/react"; +import { + WalletSource, + type StamperType, + type WalletAccount, +} from "@turnkey/core"; +import { + TurnkeyError, + TurnkeyErrorCodes, + type v1HashFunction, + type v1PayloadEncoding, + type v1SignRawPayloadResult, +} from "@turnkey/sdk-types"; +import { ActionButton } from "../design/Buttons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faWallet } from "@fortawesome/free-solid-svg-icons"; +import { useRef, useEffect, useState } from "react"; +import { useModal } from "../../providers/modal/Hook"; +import { useTurnkey } from "../../providers/client/Hook"; +import { SuccessPage } from "../design/Success"; +import clsx from "clsx"; + +interface SignMessageModalProps { + message: string; + walletAccount: WalletAccount; + subText?: string | undefined; + stampWith?: StamperType | undefined; + successPageDuration?: number | undefined; // Duration in milliseconds for the success page to show. If 0, it will not show the success page. + onSuccess: (result: v1SignRawPayloadResult) => void; + onError: (error: any) => void; + encoding?: v1PayloadEncoding; + hashFunction?: v1HashFunction; + addEthereumPrefix?: boolean; +} + +export function SignMessageModal(props: SignMessageModalProps) { + const { + message, + walletAccount, + subText = "Use your wallet to sign this message", + stampWith, + successPageDuration, + onSuccess, + onError, + } = props; + + const { signMessage } = useTurnkey(); + const { pushPage, closeModal, isMobile } = useModal(); + const [loading, setLoading] = useState(false); + const textareaRef = useRef(null); + + useEffect(() => { + const textarea = textareaRef.current; + if (textarea) { + textarea.style.height = "auto"; // reset height + textarea.style.height = `${Math.min(textarea.scrollHeight, 288)}px`; // max-h-72 = 288px + } + }, [message]); + + const handleSign = async () => { + try { + setLoading(true); + const result = await signMessage({ + message, + walletAccount, + ...(props?.encoding && { encoding: props.encoding }), + ...(props?.hashFunction && { hashFunction: props.hashFunction }), + ...(props?.addEthereumPrefix && { + addEthereumPrefix: props.addEthereumPrefix, + }), + ...(stampWith && { stampWith }), + }); + handleSuccess(result); + } catch (error) { + if (error instanceof TurnkeyError) onError(error); + else { + const tkError = new TurnkeyError( + "Failed to sign message", + TurnkeyErrorCodes.SIGN_MESSAGE_ERROR, + ); + onError(tkError); + } + } finally { + setLoading(false); + } + }; + + const handleSuccess = (result: v1SignRawPayloadResult) => { + onSuccess(result); // Run the success callback first before showing the success page. + + if (!successPageDuration) { + closeModal(); + return; + } + + pushPage({ + key: "success", + content: ( + { + closeModal(); + }} + /> + ), + preventBack: true, + showTitle: false, + }); + }; + + return ( +
+

+ {subText} +

+
+
+ +
+ + {walletAccount.address?.length > 8 + ? `${walletAccount.address.slice(0, 4)}...${walletAccount.address.slice(-4)}` + : walletAccount.address} + {walletAccount.source === WalletSource.Connected && ( +
+ External +
+ )} +
+ +
+