Skip to content
505 changes: 505 additions & 0 deletions docs/superpowers/specs/2026-07-02-wallet-sdk-contract-proposal.md

Large diffs are not rendered by default.

22 changes: 18 additions & 4 deletions packages/wallet-sdk/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
// @agicash/wallet-sdk — public surface: domain types only.
// Repositories, services, and the wallet DB layer are SDK-internal; during the
// migration they're re-exported from '@agicash/wallet-sdk/temporary' instead,
// so that deleting /temporary at the end compiler-enforces the boundary.
// @agicash/wallet-sdk — public surface: the SDK contract (sdk.ts) + domain
// types + typed errors. Repositories, services, and the wallet DB layer are
// SDK-internal; during the migration they're re-exported from
// '@agicash/wallet-sdk/temporary' instead, so that deleting /temporary at the
// end compiler-enforces the boundary.
// The explicit domain-type exports below SHADOW the same-named contract
// projections from './sdk' (an explicit export beats `export *`); each slice
// deletes its names here when it flips the web imports, surfacing the
// projections.
export * from './sdk';
export {
ConcurrencyError,
DomainError,
NotFoundError,
SdkError,
UniqueConstraintError,
} from './lib/error';
export { WebAssemblyUnavailableError } from './lib/spark/errors';
export type { DestinationDetails } from './lib/send-destination';
export type { SparkNetwork } from './db/json-models/spark-account-details-db-data';
export type { FeatureFlag, FeatureFlags } from './lib/feature-flag-service';
Expand Down
15 changes: 11 additions & 4 deletions packages/wallet-sdk/lib/error.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,27 @@
export class UniqueConstraintError extends Error {}
/**
* Abstract base for everything the SDK throws — hosts get one `instanceof`
* check at the boundary. Subclass semantics are contract: `DomainError.message`
* is the only user-displayable message; `ConcurrencyError` always means retry.
*/

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Comment is redundant

export abstract class SdkError extends Error {}

export class NotFoundError extends Error {
export class UniqueConstraintError extends SdkError {}

export class NotFoundError extends SdkError {
constructor(message: string) {
super(message);
this.name = 'NotFoundError';
}
}

export class DomainError extends Error {
export class DomainError extends SdkError {
constructor(message: string) {
super(message);
this.name = 'DomainError';
}
}

export class ConcurrencyError extends Error {
export class ConcurrencyError extends SdkError {
constructor(
message: string,
public details: string | undefined = undefined,
Expand Down
14 changes: 14 additions & 0 deletions packages/wallet-sdk/lib/spark/errors.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
import { SdkError } from '../error';

/**
* Thrown when `WebAssembly` is not available in the current browser session.
* Most commonly caused by iOS Lockdown Mode disabling WASM in WebKit; can also
* occur in restricted in-app WebViews on Android.
*/
export class WebAssemblyUnavailableError extends SdkError {
constructor() {
super('WebAssembly is not available in this browser session');
this.name = 'WebAssemblyUnavailableError';
}
}

export const isInsufficentBalanceError = (error: unknown): error is Error => {
if (!(error instanceof Error)) {
return false;
Expand Down
13 changes: 1 addition & 12 deletions packages/wallet-sdk/lib/spark/wasm.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,8 @@
import initBreezWasm from '@agicash/breez-sdk-spark';
import { WebAssemblyUnavailableError } from './errors';

let wasmInitPromise: ReturnType<typeof initBreezWasm> | null = null;

/**
* Thrown when `WebAssembly` is not available in the current browser session.
* Most commonly caused by iOS Lockdown Mode disabling WASM in WebKit; can also
* occur in restricted in-app WebViews on Android.
*/
export class WebAssemblyUnavailableError extends Error {
constructor() {
super('WebAssembly is not available in this browser session');
this.name = 'WebAssemblyUnavailableError';
}
}

/**
* Initializes the Breez SDK WASM module exactly once, even across concurrent
* callers. The SDK's own init only short-circuits after completion, so parallel
Expand Down
Loading
Loading