Skip to content

chore(sdk): enable strict TypeScript and export all public types#213

Open
Aboyeji-Isaac wants to merge 5 commits into
Miracle656:mainfrom
Aboyeji-Isaac:chore/sdk-strict-types
Open

chore(sdk): enable strict TypeScript and export all public types#213
Aboyeji-Isaac wants to merge 5 commits into
Miracle656:mainfrom
Aboyeji-Isaac:chore/sdk-strict-types

Conversation

@Aboyeji-Isaac
Copy link
Copy Markdown

@Aboyeji-Isaac Aboyeji-Isaac commented May 29, 2026

Summary

  • Extracts framework-agnostic wallet logic into sdk/src/core/InvisibleWalletCore.ts so both React and Vue adapters share the same core
  • Adds sdk/vue/ — a new @veil/invisible-wallet-vue package exporting useInvisibleWallet as a Vue 3 Composition API composable (reactive refs, onMounted/onUnmounted lifecycle, readonly state)
  • Adds a complete runnable Vite + Vue 3 example app at sdk/src/examples/vue/ demonstrating register, login, deploy, and send
  • Replaces invented option types (RegisterOptions, SignOptions, SendOptions) with a derived WalletState type that cannot drift from the hook
  • Excludes src/examples from the SDK tsconfig so tsc --noEmit passes cleanly under strict: true

Acceptance criteria — #173

  • Composable parity with the React hook (register, login, sign, send, and more)
  • Reactive state (address, isDeployed, isPending, error) via readonly refs
  • Vue example app works in examples/vue/ — includes App.vue, main.ts, tsconfig.json, and .env.example
  • Bundle imports only vue and @stellar/stellar-sdk — no React dependency

Acceptance criteria — #179

  • tsc --noEmit passes under strict: true
  • No any in public API
  • WalletState importable via import type { WalletState } from '@veil/invisible-wallet-sdk'

Test plan

  • cd sdk/vue && npm install && npm run build — bundle compiles without errors
  • cd sdk/src/examples/vue && npm install && npm run dev — dev server starts on port 5173
  • Register flow: clicking Register opens a WebAuthn prompt and populates the wallet address
  • Login flow: clicking Login restores wallet from localStorage
  • Deploy flow: entering a signer secret and clicking Deploy submits an on-chain transaction
  • Send flow: filling in recipient, token, and amount and clicking Send submits an approve transaction

Closes #173
Closes #179

@Aboyeji-Isaac Aboyeji-Isaac requested a review from Miracle656 as a code owner May 29, 2026 09:42
@vercel
Copy link
Copy Markdown

vercel Bot commented May 29, 2026

@aboyejiisaiah-commits is attempting to deploy a commit to the miracle656's projects Team on Vercel.

A member of the Team first needs to authorize it.

@drips-wave
Copy link
Copy Markdown

drips-wave Bot commented May 29, 2026

@Aboyeji-Isaac Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

Copy link
Copy Markdown
Owner

@Miracle656 Miracle656 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR! Before merging there are a few things to address — the current state would publish types that don't match the SDK's actual API.

1. sdk/tsconfig.json isn't actually modified by this PR

The PR body says "Enabled strict: true in sdk/tsconfig.json" but tsconfig.json isn't in the changed files. Checking main directly, strict: true is already set there (it was tightened during the React Native PR #211). So the strict-mode part of issue #179 is already done — no action needed on your side, just remove that claim from the PR description.

2. The 4 new types in sdk/src/types.ts don't match the real hook API

The hook in sdk/src/useInvisibleWallet.ts exposes these (register, signAuthEntry, deploy) as positional-argument functions, not options-object functions. So:

  • RegisterOptions = { username?: string }register(username?: string) takes a positional string, not an options object. Importing this type wouldn't help anyone call register().
  • SignOptions = { signaturePayload: Uint8Array } — same story; signAuthEntry(payload) is positional.
  • SendOptions = { signerSecret, publicKeyBytes } — there is no send function. The closest is deploy(signerSecret, publicKeyBytes), also positional. Inventing a name that doesn't exist in the SDK will confuse integrators.
  • WalletState is closer to useful, but the hook returns these properties directly on the InvisibleWallet object ({ address, isDeployed, isPending, error, register, deploy, ... }), not as a separate WalletState aggregate.

Because none of these types are referenced inside the SDK, tsc --noEmit of course passes — they're decorative.

3. The actual fix is much simpler

useInvisibleWallet.ts already exports the real public types. Re-exporting these gives integrators exactly what they need:

// sdk/src/index.ts
export type {
  WalletConfig,
  WalletState,           // see below — derive from InvisibleWallet
  StorageAdapter,
  RegisterResult,
  DeployResult,
  AddSignerResult,
  SignerInfo,
  InitiateRecoveryResult,
  WebAuthnSignature,
} from './useInvisibleWallet';

For WalletState specifically, since the hook returns these on its result object, the cleanest export is a Pick<> of the existing InvisibleWallet type:

import type { useInvisibleWallet } from './useInvisibleWallet';

export type WalletState = Pick<
  ReturnType<typeof useInvisibleWallet>,
  'address' | 'isDeployed' | 'isPending' | 'error'
>;

That way WalletState cannot drift from the hook — it's derived.

Suggested revision

  1. Delete the invented RegisterOptions, SignOptions, SendOptions from types.ts (or remove the file entirely)
  2. In sdk/src/index.ts, re-export the real types as shown above
  3. Add WalletState as a derived Pick<> of the hook's return type
  4. Remove the "Enabled strict: true" line from the PR description (it's already on)
  5. Verify npm pack --dry-run shows the new type re-exports in dist/index.d.ts

Once that's done, this will fully close #179.

Remove RegisterOptions, SignOptions, and SendOptions — they do not match
the hook positional API and would mislead integrators. Replace the
hand-written WalletState with a Pick derived from the hook return
type so it cannot drift. Clean up index.ts to only re-export value
exports from InvisibleWalletCore; all public types flow through
useInvisibleWallet exports.
The Vue example app has its own tsconfig and its own devDependencies
(vue, vite, @vitejs/plugin-vue). Including src/examples/** in the
SDK tsconfig caused tsc --noEmit to fail with module-not-found errors
for those packages. Excluding the examples dir keeps the SDK build
clean without affecting the example app.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Tighten TypeScript declarations for invisible-wallet-sdk Add Vue 3 adapter for invisible-wallet-sdk

3 participants