@prism-ing/wallet 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/LICENSE +21 -0
  3. package/README.md +596 -0
  4. package/SPEC.md +192 -0
  5. package/dist/backends/squads-recovery-backend.d.ts +59 -0
  6. package/dist/backends/squads-recovery-backend.d.ts.map +1 -0
  7. package/dist/backends/squads-recovery-backend.js +81 -0
  8. package/dist/backends/squads-recovery-backend.js.map +1 -0
  9. package/dist/backends/squads-types.d.ts +74 -0
  10. package/dist/backends/squads-types.d.ts.map +1 -0
  11. package/dist/backends/squads-types.js +22 -0
  12. package/dist/backends/squads-types.js.map +1 -0
  13. package/dist/backends/zerodev-policy-mapper.d.ts +41 -0
  14. package/dist/backends/zerodev-policy-mapper.d.ts.map +1 -0
  15. package/dist/backends/zerodev-policy-mapper.js +127 -0
  16. package/dist/backends/zerodev-policy-mapper.js.map +1 -0
  17. package/dist/backends/zerodev-session-backend.d.ts +43 -0
  18. package/dist/backends/zerodev-session-backend.d.ts.map +1 -0
  19. package/dist/backends/zerodev-session-backend.js +63 -0
  20. package/dist/backends/zerodev-session-backend.js.map +1 -0
  21. package/dist/backends/zerodev-types.d.ts +104 -0
  22. package/dist/backends/zerodev-types.d.ts.map +1 -0
  23. package/dist/backends/zerodev-types.js +13 -0
  24. package/dist/backends/zerodev-types.js.map +1 -0
  25. package/dist/create-wallet.d.ts +89 -0
  26. package/dist/create-wallet.d.ts.map +1 -0
  27. package/dist/create-wallet.js +235 -0
  28. package/dist/create-wallet.js.map +1 -0
  29. package/dist/cross-chain.d.ts +64 -0
  30. package/dist/cross-chain.d.ts.map +1 -0
  31. package/dist/cross-chain.js +200 -0
  32. package/dist/cross-chain.js.map +1 -0
  33. package/dist/errors.d.ts +115 -0
  34. package/dist/errors.d.ts.map +1 -0
  35. package/dist/errors.js +97 -0
  36. package/dist/errors.js.map +1 -0
  37. package/dist/index.d.ts +55 -0
  38. package/dist/index.d.ts.map +1 -0
  39. package/dist/index.js +52 -0
  40. package/dist/index.js.map +1 -0
  41. package/dist/internal/base58.d.ts +8 -0
  42. package/dist/internal/base58.d.ts.map +1 -0
  43. package/dist/internal/base58.js +34 -0
  44. package/dist/internal/base58.js.map +1 -0
  45. package/dist/internal/eip712.d.ts +41 -0
  46. package/dist/internal/eip712.d.ts.map +1 -0
  47. package/dist/internal/eip712.js +182 -0
  48. package/dist/internal/eip712.js.map +1 -0
  49. package/dist/internal/file-spend-persistence.d.ts +9 -0
  50. package/dist/internal/file-spend-persistence.d.ts.map +1 -0
  51. package/dist/internal/file-spend-persistence.js +58 -0
  52. package/dist/internal/file-spend-persistence.js.map +1 -0
  53. package/dist/internal/onebalance-client.d.ts +59 -0
  54. package/dist/internal/onebalance-client.d.ts.map +1 -0
  55. package/dist/internal/onebalance-client.js +2 -0
  56. package/dist/internal/onebalance-client.js.map +1 -0
  57. package/dist/internal/onebalance-http-client.d.ts +25 -0
  58. package/dist/internal/onebalance-http-client.d.ts.map +1 -0
  59. package/dist/internal/onebalance-http-client.js +161 -0
  60. package/dist/internal/onebalance-http-client.js.map +1 -0
  61. package/dist/internal/onebalance-types.d.ts +201 -0
  62. package/dist/internal/onebalance-types.d.ts.map +1 -0
  63. package/dist/internal/onebalance-types.js +39 -0
  64. package/dist/internal/onebalance-types.js.map +1 -0
  65. package/dist/internal/platform.d.ts +14 -0
  66. package/dist/internal/platform.d.ts.map +1 -0
  67. package/dist/internal/platform.js +22 -0
  68. package/dist/internal/platform.js.map +1 -0
  69. package/dist/internal/quote-verifier.d.ts +71 -0
  70. package/dist/internal/quote-verifier.d.ts.map +1 -0
  71. package/dist/internal/quote-verifier.js +172 -0
  72. package/dist/internal/quote-verifier.js.map +1 -0
  73. package/dist/internal/recovery-manager.d.ts +29 -0
  74. package/dist/internal/recovery-manager.d.ts.map +1 -0
  75. package/dist/internal/recovery-manager.js +161 -0
  76. package/dist/internal/recovery-manager.js.map +1 -0
  77. package/dist/result.d.ts +132 -0
  78. package/dist/result.d.ts.map +1 -0
  79. package/dist/result.js +114 -0
  80. package/dist/result.js.map +1 -0
  81. package/dist/schemas.d.ts +184 -0
  82. package/dist/schemas.d.ts.map +1 -0
  83. package/dist/schemas.js +76 -0
  84. package/dist/schemas.js.map +1 -0
  85. package/dist/session-keys.d.ts +53 -0
  86. package/dist/session-keys.d.ts.map +1 -0
  87. package/dist/session-keys.js +345 -0
  88. package/dist/session-keys.js.map +1 -0
  89. package/dist/signers/node-signing-backend.d.ts +11 -0
  90. package/dist/signers/node-signing-backend.d.ts.map +1 -0
  91. package/dist/signers/node-signing-backend.js +120 -0
  92. package/dist/signers/node-signing-backend.js.map +1 -0
  93. package/dist/signers/ows-adapter.d.ts +70 -0
  94. package/dist/signers/ows-adapter.d.ts.map +1 -0
  95. package/dist/signers/ows-adapter.js +53 -0
  96. package/dist/signers/ows-adapter.js.map +1 -0
  97. package/dist/signers/ows-signing-backend.d.ts +25 -0
  98. package/dist/signers/ows-signing-backend.d.ts.map +1 -0
  99. package/dist/signers/ows-signing-backend.js +192 -0
  100. package/dist/signers/ows-signing-backend.js.map +1 -0
  101. package/dist/signers/secure-enclave-backend.d.ts +19 -0
  102. package/dist/signers/secure-enclave-backend.d.ts.map +1 -0
  103. package/dist/signers/secure-enclave-backend.js +201 -0
  104. package/dist/signers/secure-enclave-backend.js.map +1 -0
  105. package/dist/signers/secure-enclave-types.d.ts +98 -0
  106. package/dist/signers/secure-enclave-types.d.ts.map +1 -0
  107. package/dist/signers/secure-enclave-types.js +12 -0
  108. package/dist/signers/secure-enclave-types.js.map +1 -0
  109. package/dist/types.d.ts +371 -0
  110. package/dist/types.d.ts.map +1 -0
  111. package/dist/types.js +2 -0
  112. package/dist/types.js.map +1 -0
  113. package/package.json +85 -0
@@ -0,0 +1,70 @@
1
+ /**
2
+ * OWS Signer Adapter — wraps platform-specific OWS APIs behind PrismSigner.
3
+ *
4
+ * @remarks
5
+ * On iOS, this calls the Swift bridge to the Secure Enclave.
6
+ * On Node.js, it uses OWS's software signing path.
7
+ * The interface is identical on all platforms.
8
+ *
9
+ * @packageDocumentation
10
+ */
11
+ import type { Address, Hex, Result } from '../result.js';
12
+ import type { PrismSigner, TypedDataPayload, Platform } from '../types.js';
13
+ import type { WalletError } from '../errors.js';
14
+ /**
15
+ * The OWS adapter implements PrismSigner for all platforms.
16
+ *
17
+ * @remarks
18
+ * Created via the platform-specific factory. Never instantiate directly.
19
+ */
20
+ export interface OWSAdapter extends PrismSigner {
21
+ /** The platform this adapter was created for. */
22
+ readonly platform: Platform;
23
+ /** Zero all key material held by the underlying backend. */
24
+ destroy?(): void;
25
+ }
26
+ /** Key material returned by OWS key generation. */
27
+ export interface OWSKeyPair {
28
+ readonly evmAddress: Address;
29
+ readonly solanaAddress: string;
30
+ readonly platform: Platform;
31
+ }
32
+ /**
33
+ * Platform-specific signing backend.
34
+ *
35
+ * @remarks
36
+ * Each platform provides its own implementation:
37
+ * - iOS: Swift bridge to Secure Enclave
38
+ * - Node: OWS CLI or npm package
39
+ * - Browser: Software signing fallback
40
+ */
41
+ export interface SigningBackend {
42
+ generateKeyPair(): Promise<Result<OWSKeyPair, WalletError>>;
43
+ signMessage(keys: OWSKeyPair, message: Hex): Promise<Result<Hex, WalletError>>;
44
+ signTypedData(keys: OWSKeyPair, payload: TypedDataPayload): Promise<Result<Hex, WalletError>>;
45
+ signTransaction<T>(keys: OWSKeyPair, tx: T): Promise<Result<T, WalletError>>;
46
+ /**
47
+ * Execute a function within a single authentication context.
48
+ * On Secure Enclave, this means one biometric prompt for all
49
+ * signing operations within fn(). On other backends, passthrough.
50
+ */
51
+ withAuthContext?<T>(prompt: string, fn: () => Promise<T>): Promise<Result<T, WalletError>>;
52
+ /** Zero all in-memory key material. No-op for hardware-backed backends. */
53
+ destroy?(): void;
54
+ /** Zero and remove a specific key pair by EVM address. */
55
+ removeKeyPair?(evmAddress: string): Result<void, WalletError>;
56
+ }
57
+ /**
58
+ * Create an OWSAdapter from a platform-specific SigningBackend.
59
+ *
60
+ * @remarks
61
+ * Generates a key pair via the backend, then wraps all signing operations
62
+ * behind the PrismSigner interface. The adapter is the "imperative shell" —
63
+ * Result errors from the backend are unwrapped and thrown here, since
64
+ * PrismSigner methods return plain `Promise<Hex>`.
65
+ *
66
+ * @param backend - The platform-specific signing backend.
67
+ * @returns A Result containing the OWSAdapter or a WalletError.
68
+ */
69
+ export declare function createOWSAdapter(backend: SigningBackend): Promise<Result<OWSAdapter, WalletError>>;
70
+ //# sourceMappingURL=ows-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ows-adapter.d.ts","sourceRoot":"","sources":["../../src/signers/ows-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEzD,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD;;;;;GAKG;AACH,MAAM,WAAW,UAAW,SAAQ,WAAW;IAC7C,iDAAiD;IACjD,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,4DAA4D;IAC5D,OAAO,CAAC,IAAI,IAAI,CAAC;CAClB;AAED,mDAAmD;AACnD,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;CAC7B;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,cAAc;IAC7B,eAAe,IAAI,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC,CAAC;IAC5D,WAAW,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC;IAC/E,aAAa,CACX,IAAI,EAAE,UAAU,EAChB,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC;IACrC,eAAe,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC;IAC7E;;;;OAIG;IACH,eAAe,CAAC,CAAC,CAAC,EAChB,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACnB,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC;IACnC,2EAA2E;IAC3E,OAAO,CAAC,IAAI,IAAI,CAAC;IACjB,0DAA0D;IAC1D,aAAa,CAAC,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;CAC/D;AAMD;;;;;;;;;;;GAWG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC,CAwC1C"}
@@ -0,0 +1,53 @@
1
+ import { Ok } from '../result.js';
2
+ // ---------------------------------------------------------------------------
3
+ // Factory
4
+ // ---------------------------------------------------------------------------
5
+ /**
6
+ * Create an OWSAdapter from a platform-specific SigningBackend.
7
+ *
8
+ * @remarks
9
+ * Generates a key pair via the backend, then wraps all signing operations
10
+ * behind the PrismSigner interface. The adapter is the "imperative shell" —
11
+ * Result errors from the backend are unwrapped and thrown here, since
12
+ * PrismSigner methods return plain `Promise<Hex>`.
13
+ *
14
+ * @param backend - The platform-specific signing backend.
15
+ * @returns A Result containing the OWSAdapter or a WalletError.
16
+ */
17
+ export async function createOWSAdapter(backend) {
18
+ const keyResult = await backend.generateKeyPair();
19
+ if (!keyResult.ok)
20
+ return keyResult;
21
+ const keys = keyResult.value;
22
+ const adapter = {
23
+ evmAddress: keys.evmAddress,
24
+ solanaAddress: keys.solanaAddress,
25
+ platform: keys.platform,
26
+ async signMessage(message) {
27
+ const result = await backend.signMessage(keys, message);
28
+ if (!result.ok) {
29
+ throw new Error(`Signing failed: ${result.error.code}`);
30
+ }
31
+ return result.value;
32
+ },
33
+ async signTypedData(payload) {
34
+ const result = await backend.signTypedData(keys, payload);
35
+ if (!result.ok) {
36
+ throw new Error(`Signing failed: ${result.error.code}`);
37
+ }
38
+ return result.value;
39
+ },
40
+ async signTransaction(tx) {
41
+ const result = await backend.signTransaction(keys, tx);
42
+ if (!result.ok) {
43
+ throw new Error(`Signing failed: ${result.error.code}`);
44
+ }
45
+ return result.value;
46
+ },
47
+ destroy() {
48
+ backend.destroy?.();
49
+ },
50
+ };
51
+ return Ok(adapter);
52
+ }
53
+ //# sourceMappingURL=ows-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ows-adapter.js","sourceRoot":"","sources":["../../src/signers/ows-adapter.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAwDlC,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,OAAuB;IAEvB,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,eAAe,EAAE,CAAC;IAClD,IAAI,CAAC,SAAS,CAAC,EAAE;QAAE,OAAO,SAAS,CAAC;IACpC,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC;IAE7B,MAAM,OAAO,GAAe;QAC1B,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,aAAa,EAAE,IAAI,CAAC,aAAa;QACjC,QAAQ,EAAE,IAAI,CAAC,QAAQ;QAEvB,KAAK,CAAC,WAAW,CAAC,OAAY;YAC5B,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YACxD,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;gBACf,MAAM,IAAI,KAAK,CAAC,mBAAmB,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;YAC1D,CAAC;YACD,OAAO,MAAM,CAAC,KAAK,CAAC;QACtB,CAAC;QAED,KAAK,CAAC,aAAa,CAAC,OAAyB;YAC3C,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YAC1D,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;gBACf,MAAM,IAAI,KAAK,CAAC,mBAAmB,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;YAC1D,CAAC;YACD,OAAO,MAAM,CAAC,KAAK,CAAC;QACtB,CAAC;QAED,KAAK,CAAC,eAAe,CAAI,EAAK;YAC5B,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,eAAe,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YACvD,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;gBACf,MAAM,IAAI,KAAK,CAAC,mBAAmB,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;YAC1D,CAAC;YACD,OAAO,MAAM,CAAC,KAAK,CAAC;QACtB,CAAC;QAED,OAAO;YACL,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;QACtB,CAAC;KACF,CAAC;IAEF,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC;AACrB,CAAC"}
@@ -0,0 +1,25 @@
1
+ import type { SigningBackend } from './ows-adapter.js';
2
+ /** Configuration for the OWS signing backend. */
3
+ export interface OWSBackendConfig {
4
+ /** OWS wallet name. Same name = same wallet across sessions. */
5
+ readonly walletName: string;
6
+ /** Owner passphrase for OWS vault. Omit to use OWS_PASSPHRASE env var or apiKey. */
7
+ readonly passphrase?: string;
8
+ /** Agent API key (ows_key_...). Enables policy-gated, scoped access. */
9
+ readonly apiKey?: string;
10
+ /** Custom vault path. Defaults to ~/.ows/. Useful for testing. */
11
+ readonly vaultPath?: string;
12
+ }
13
+ /**
14
+ * Create a persistent OWS signing backend.
15
+ *
16
+ * @remarks
17
+ * On first call with a given wallet name, creates a new OWS wallet
18
+ * (BIP-39 mnemonic → secp256k1 + ed25519 accounts, encrypted at rest).
19
+ * On subsequent calls, loads the existing wallet — same keys, same addresses.
20
+ *
21
+ * @param config - Wallet name, auth credentials, and optional vault path.
22
+ * @returns A `SigningBackend` backed by OWS persistent storage.
23
+ */
24
+ export declare function createOWSSigningBackend(config: OWSBackendConfig): SigningBackend;
25
+ //# sourceMappingURL=ows-signing-backend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ows-signing-backend.d.ts","sourceRoot":"","sources":["../../src/signers/ows-signing-backend.ts"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAE,cAAc,EAAc,MAAM,kBAAkB,CAAC;AAOnE,iDAAiD;AACjD,MAAM,WAAW,gBAAgB;IAC/B,gEAAgE;IAChE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,oFAAoF;IACpF,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,wEAAwE;IACxE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,kEAAkE;IAClE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAeD;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,gBAAgB,GAAG,cAAc,CAwGhF"}
@@ -0,0 +1,192 @@
1
+ /**
2
+ * OWS signing backend — persistent key storage via Open Wallet Standard.
3
+ *
4
+ * @remarks
5
+ * Uses `@open-wallet-standard/core` (native NAPI bindings) for encrypted
6
+ * key persistence at `~/.ows/`. Same wallet name = same keys across sessions.
7
+ *
8
+ * Two access modes:
9
+ * - **Owner mode**: passphrase decrypts the vault (scrypt + AES-256-GCM)
10
+ * - **Agent mode**: API key token (`ows_key_...`) enables policy-gated signing
11
+ *
12
+ * All OWS functions are synchronous (Rust NAPI). This module wraps them
13
+ * in the async `SigningBackend` interface with `Result` error handling.
14
+ *
15
+ * @packageDocumentation
16
+ */
17
+ import { createWallet as owsCreateWallet, getWallet as owsGetWallet, signMessage as owsSignMessage, signTypedData as owsSignTypedData, signTransaction as owsSignTransaction, } from '@open-wallet-standard/core';
18
+ import { Ok, Err, toAddress } from '../result.js';
19
+ import { walletErrors } from '../errors.js';
20
+ import { inferDomainType, isSolanaTransaction, hexToBytes } from '../internal/eip712.js';
21
+ // ---------------------------------------------------------------------------
22
+ // Constants
23
+ // ---------------------------------------------------------------------------
24
+ const EVM_CHAIN_ID = 'eip155:1';
25
+ const SOLANA_CHAIN_PREFIX = 'solana:';
26
+ const OWS_CHAIN_EVM = 'ethereum';
27
+ const OWS_CHAIN_SOLANA = 'solana';
28
+ // ---------------------------------------------------------------------------
29
+ // Factory
30
+ // ---------------------------------------------------------------------------
31
+ /**
32
+ * Create a persistent OWS signing backend.
33
+ *
34
+ * @remarks
35
+ * On first call with a given wallet name, creates a new OWS wallet
36
+ * (BIP-39 mnemonic → secp256k1 + ed25519 accounts, encrypted at rest).
37
+ * On subsequent calls, loads the existing wallet — same keys, same addresses.
38
+ *
39
+ * @param config - Wallet name, auth credentials, and optional vault path.
40
+ * @returns A `SigningBackend` backed by OWS persistent storage.
41
+ */
42
+ export function createOWSSigningBackend(config) {
43
+ const auth = resolveAuth(config);
44
+ const backend = {
45
+ async generateKeyPair() {
46
+ try {
47
+ const wallet = getOrCreateWallet(config);
48
+ return extractKeyPair(wallet);
49
+ }
50
+ catch (e) {
51
+ return Err(mapOWSError(e));
52
+ }
53
+ },
54
+ async signMessage(_keys, message) {
55
+ try {
56
+ // Strip 0x prefix — OWS expects raw hex
57
+ const hexMsg = message.startsWith('0x')
58
+ ? message.slice(2)
59
+ : message;
60
+ const result = owsSignMessage(config.walletName, OWS_CHAIN_EVM, hexMsg, auth, 'hex', null, config.vaultPath ?? null);
61
+ return Ok(formatEvmSignature(result.signature, result.recoveryId));
62
+ }
63
+ catch (e) {
64
+ return Err(mapOWSError(e));
65
+ }
66
+ },
67
+ async signTypedData(_keys, payload) {
68
+ try {
69
+ // OWS requires EIP712Domain in the types object
70
+ const typedDataWithDomain = {
71
+ ...payload,
72
+ types: {
73
+ ...payload.types,
74
+ EIP712Domain: inferDomainType(payload.domain),
75
+ },
76
+ };
77
+ const result = owsSignTypedData(config.walletName, OWS_CHAIN_EVM, JSON.stringify(typedDataWithDomain), auth, null, config.vaultPath ?? null);
78
+ return Ok(formatEvmSignature(result.signature, result.recoveryId));
79
+ }
80
+ catch (e) {
81
+ return Err(mapOWSError(e));
82
+ }
83
+ },
84
+ async signTransaction(_keys, tx) {
85
+ try {
86
+ if (!isSolanaTransaction(tx)) {
87
+ return Err(walletErrors.signingRejected('Unsupported transaction type'));
88
+ }
89
+ const messageBytes = tx.message.serialize();
90
+ const messageHex = bytesToHex(messageBytes);
91
+ const result = owsSignTransaction(config.walletName, OWS_CHAIN_SOLANA, messageHex, auth, null, config.vaultPath ?? null);
92
+ // OWS returns hex-encoded ed25519 signature (128 hex chars = 64 bytes)
93
+ tx.signatures[0] = hexToBytes(result.signature);
94
+ return Ok(tx);
95
+ }
96
+ catch (e) {
97
+ return Err(mapOWSError(e));
98
+ }
99
+ },
100
+ async withAuthContext(_prompt, fn) {
101
+ return Ok(await fn());
102
+ },
103
+ destroy() {
104
+ // OWS keys live in encrypted vault on disk, not in JS memory.
105
+ },
106
+ };
107
+ return backend;
108
+ }
109
+ // ---------------------------------------------------------------------------
110
+ // Wallet Management
111
+ // ---------------------------------------------------------------------------
112
+ /**
113
+ * Get an existing OWS wallet or create a new one.
114
+ * This is the persistence mechanism — same name = same wallet.
115
+ */
116
+ function getOrCreateWallet(config) {
117
+ try {
118
+ return owsGetWallet(config.walletName, config.vaultPath ?? null);
119
+ }
120
+ catch {
121
+ // Wallet doesn't exist yet — create it
122
+ const auth = resolveAuth(config);
123
+ return owsCreateWallet(config.walletName, auth, 12, // 12-word mnemonic
124
+ config.vaultPath ?? null);
125
+ }
126
+ }
127
+ /**
128
+ * Extract EVM and Solana addresses from OWS wallet accounts.
129
+ */
130
+ function extractKeyPair(wallet) {
131
+ const evmAccount = wallet.accounts.find((a) => a.chainId === EVM_CHAIN_ID);
132
+ const solanaAccount = wallet.accounts.find((a) => a.chainId.startsWith(SOLANA_CHAIN_PREFIX));
133
+ if (!evmAccount) {
134
+ return Err(walletErrors.keyNotFound('No EVM account in OWS wallet'));
135
+ }
136
+ const evmAddressResult = toAddress(evmAccount.address);
137
+ if (!evmAddressResult.ok) {
138
+ return Err(walletErrors.keyNotFound(evmAccount.address));
139
+ }
140
+ return Ok({
141
+ evmAddress: evmAddressResult.value,
142
+ solanaAddress: solanaAccount?.address ?? '',
143
+ platform: 'node',
144
+ });
145
+ }
146
+ // ---------------------------------------------------------------------------
147
+ // Auth Resolution
148
+ // ---------------------------------------------------------------------------
149
+ function resolveAuth(config) {
150
+ return config.apiKey ?? config.passphrase ?? process.env.OWS_PASSPHRASE ?? null;
151
+ }
152
+ // ---------------------------------------------------------------------------
153
+ // Signature Formatting
154
+ // ---------------------------------------------------------------------------
155
+ /**
156
+ * Format an OWS EVM signature as a 0x-prefixed 65-byte hex string.
157
+ *
158
+ * @remarks
159
+ * OWS returns the signature as a hex string (no 0x prefix) with v already
160
+ * encoded as the last byte. The recoveryId (27 or 28) confirms this.
161
+ */
162
+ function formatEvmSignature(sigHex, _recoveryId) {
163
+ // OWS signature is already r + s + v (65 bytes = 130 hex chars)
164
+ return `0x${sigHex}`;
165
+ }
166
+ // ---------------------------------------------------------------------------
167
+ // Hex Utilities
168
+ // ---------------------------------------------------------------------------
169
+ function bytesToHex(bytes) {
170
+ return Array.from(bytes)
171
+ .map((b) => b.toString(16).padStart(2, '0'))
172
+ .join('');
173
+ }
174
+ // ---------------------------------------------------------------------------
175
+ // Error Mapping
176
+ // ---------------------------------------------------------------------------
177
+ /**
178
+ * Map OWS errors to WalletError.
179
+ * OWS throws plain Error objects with descriptive messages.
180
+ */
181
+ function mapOWSError(e) {
182
+ const msg = e instanceof Error ? e.message : String(e);
183
+ const lower = msg.toLowerCase();
184
+ if (lower.includes('not found') || lower.includes('no such')) {
185
+ return walletErrors.keyNotFound(msg);
186
+ }
187
+ if (lower.includes('passphrase') || lower.includes('authentication') || lower.includes('decrypt')) {
188
+ return walletErrors.signingRejected(msg);
189
+ }
190
+ return walletErrors.signingRejected(`OWS error: ${msg}`);
191
+ }
192
+ //# sourceMappingURL=ows-signing-backend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ows-signing-backend.js","sourceRoot":"","sources":["../../src/signers/ows-signing-backend.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { SigningBackend } from './ows-adapter.js';
2
+ import type { SecureEnclaveConfig } from './secure-enclave-types.js';
3
+ /**
4
+ * Create an iOS Secure Enclave signing backend.
5
+ *
6
+ * @remarks
7
+ * Uses the iOS Secure Enclave for hardware-backed key protection.
8
+ * Private keys are encrypted by the Secure Enclave's P-256 key and stored
9
+ * in the iOS Keychain. All signing operations require biometric authentication.
10
+ *
11
+ * The backend delegates all cryptographic operations to the native bridge.
12
+ * TypeScript handles EIP-191/EIP-712 hash computation before passing the
13
+ * hash to the native layer for signing.
14
+ *
15
+ * @param config - Secure Enclave configuration including the native bridge.
16
+ * @returns A {@link SigningBackend} backed by the iOS Secure Enclave.
17
+ */
18
+ export declare function createSecureEnclaveBackend(config: SecureEnclaveConfig): SigningBackend;
19
+ //# sourceMappingURL=secure-enclave-backend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secure-enclave-backend.d.ts","sourceRoot":"","sources":["../../src/signers/secure-enclave-backend.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,cAAc,EAAc,MAAM,kBAAkB,CAAC;AACnE,OAAO,KAAK,EAAE,mBAAmB,EAA6B,MAAM,2BAA2B,CAAC;AAmFhG;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,mBAAmB,GAC1B,cAAc,CA6IhB"}
@@ -0,0 +1,201 @@
1
+ /**
2
+ * iOS Secure Enclave signing backend.
3
+ *
4
+ * @remarks
5
+ * Implements the {@link SigningBackend} interface using the iOS Secure Enclave
6
+ * for hardware-backed key protection. Private keys (secp256k1 for EVM,
7
+ * ed25519 for Solana) are encrypted by the Secure Enclave's P-256 key and
8
+ * stored in the iOS Keychain. Signing requires biometric authentication
9
+ * (Face ID / Touch ID) before the key is decrypted in-process.
10
+ *
11
+ * The TypeScript layer handles EVM address derivation, EIP-191/EIP-712
12
+ * hashing, and signature encoding. The native bridge handles key storage,
13
+ * encryption/decryption, and biometric gating.
14
+ *
15
+ * @internal
16
+ */
17
+ import { keccak_256 } from '@noble/hashes/sha3';
18
+ import { bytesToHex } from '@noble/hashes/utils';
19
+ import { Ok, Err, fromPromise } from '../result.js';
20
+ import { walletErrors } from '../errors.js';
21
+ import { base58Encode } from '../internal/base58.js';
22
+ import { hashTypedData, personalSignHash, isSolanaTransaction } from '../internal/eip712.js';
23
+ // ---------------------------------------------------------------------------
24
+ // Constants
25
+ // ---------------------------------------------------------------------------
26
+ const DEFAULT_KEY_TAG = 'prism-wallet-default';
27
+ const DEFAULT_BIOMETRIC_PROMPT = 'Authorize transaction';
28
+ // ---------------------------------------------------------------------------
29
+ // EVM Helpers
30
+ // ---------------------------------------------------------------------------
31
+ /** Derive an EVM address from an uncompressed secp256k1 public key. */
32
+ function deriveEvmAddress(publicKey) {
33
+ // Drop the 0x04 prefix byte if present, hash the remaining 64 bytes
34
+ const keyBytes = publicKey.length === 65 ? publicKey.subarray(1) : publicKey;
35
+ const hash = keccak_256(keyBytes);
36
+ return `0x${bytesToHex(hash.subarray(12))}`;
37
+ }
38
+ // ---------------------------------------------------------------------------
39
+ // Signature Encoding
40
+ // ---------------------------------------------------------------------------
41
+ /**
42
+ * Encode a raw secp256k1 signature (64 bytes: r || s) with recovery ID
43
+ * into the standard 65-byte Ethereum format (r || s || v).
44
+ *
45
+ * @remarks
46
+ * The native bridge returns a 65-byte signature with recovery ID appended,
47
+ * matching the format from `secp256k1.sign()`.
48
+ */
49
+ function encodeSignature(rawSig) {
50
+ // rawSig is expected to be 65 bytes: r(32) || s(32) || v(1)
51
+ return `0x${bytesToHex(rawSig)}`;
52
+ }
53
+ // ---------------------------------------------------------------------------
54
+ // Error Mapping
55
+ // ---------------------------------------------------------------------------
56
+ function mapNativeError(error) {
57
+ const message = error instanceof Error ? error.message : String(error);
58
+ // Biometric cancellation / failure patterns from iOS
59
+ const biometricPatterns = [
60
+ 'user cancel',
61
+ 'biometric',
62
+ 'authentication failed',
63
+ 'passcode',
64
+ 'LAError',
65
+ ];
66
+ if (biometricPatterns.some((p) => message.toLowerCase().includes(p))) {
67
+ return walletErrors.signingRejected(message);
68
+ }
69
+ // Secure Enclave unavailability
70
+ const enclavePatterns = [
71
+ 'secure enclave',
72
+ 'not available',
73
+ 'no hardware',
74
+ 'errSecUnimplemented',
75
+ ];
76
+ if (enclavePatterns.some((p) => message.toLowerCase().includes(p))) {
77
+ return walletErrors.enclaveUnavailable('ios');
78
+ }
79
+ // Key not found
80
+ if (message.toLowerCase().includes('key not found') || message.includes('errSecItemNotFound')) {
81
+ return walletErrors.keyNotFound('secure-enclave');
82
+ }
83
+ // Default: signing rejected
84
+ return walletErrors.signingRejected(message);
85
+ }
86
+ // ---------------------------------------------------------------------------
87
+ // Factory
88
+ // ---------------------------------------------------------------------------
89
+ /**
90
+ * Create an iOS Secure Enclave signing backend.
91
+ *
92
+ * @remarks
93
+ * Uses the iOS Secure Enclave for hardware-backed key protection.
94
+ * Private keys are encrypted by the Secure Enclave's P-256 key and stored
95
+ * in the iOS Keychain. All signing operations require biometric authentication.
96
+ *
97
+ * The backend delegates all cryptographic operations to the native bridge.
98
+ * TypeScript handles EIP-191/EIP-712 hash computation before passing the
99
+ * hash to the native layer for signing.
100
+ *
101
+ * @param config - Secure Enclave configuration including the native bridge.
102
+ * @returns A {@link SigningBackend} backed by the iOS Secure Enclave.
103
+ */
104
+ export function createSecureEnclaveBackend(config) {
105
+ const bridge = config.nativeBridge;
106
+ const keyTag = config.keyTag ?? DEFAULT_KEY_TAG;
107
+ const biometricPrompt = config.biometricPrompt ?? DEFAULT_BIOMETRIC_PROMPT;
108
+ let storedKeyPair;
109
+ const backend = {
110
+ async generateKeyPair() {
111
+ // Check if key already exists (idempotent)
112
+ const existsResult = await fromPromise(bridge.keyExists(keyTag), (e) => mapNativeError(e));
113
+ if (!existsResult.ok)
114
+ return existsResult;
115
+ if (existsResult.value && storedKeyPair !== undefined) {
116
+ return Ok(storedKeyPair);
117
+ }
118
+ // Generate or retrieve key pair via native bridge
119
+ const genResult = await fromPromise(bridge.generateKey(keyTag), (e) => mapNativeError(e));
120
+ if (!genResult.ok)
121
+ return genResult;
122
+ const { evmPublicKey, solanaPublicKey } = genResult.value;
123
+ const evmAddress = deriveEvmAddress(evmPublicKey);
124
+ const solanaAddress = base58Encode(solanaPublicKey);
125
+ const keyPair = {
126
+ evmAddress,
127
+ solanaAddress,
128
+ platform: 'ios',
129
+ };
130
+ storedKeyPair = keyPair;
131
+ return Ok(keyPair);
132
+ },
133
+ async signMessage(keys, message) {
134
+ if (storedKeyPair === undefined || keys.evmAddress !== storedKeyPair.evmAddress) {
135
+ return Err(walletErrors.keyNotFound(keys.evmAddress));
136
+ }
137
+ // Compute EIP-191 hash, then sign via native bridge
138
+ const hash = personalSignHash(message);
139
+ const signResult = await fromPromise(bridge.sign(keyTag, hash, biometricPrompt), (e) => mapNativeError(e));
140
+ if (!signResult.ok)
141
+ return signResult;
142
+ return Ok(encodeSignature(signResult.value.signature));
143
+ },
144
+ async signTypedData(keys, payload) {
145
+ if (storedKeyPair === undefined || keys.evmAddress !== storedKeyPair.evmAddress) {
146
+ return Err(walletErrors.keyNotFound(keys.evmAddress));
147
+ }
148
+ // Compute EIP-712 hash, then sign via native bridge
149
+ const hash = hashTypedData(payload);
150
+ const signResult = await fromPromise(bridge.sign(keyTag, hash, biometricPrompt), (e) => mapNativeError(e));
151
+ if (!signResult.ok)
152
+ return signResult;
153
+ return Ok(encodeSignature(signResult.value.signature));
154
+ },
155
+ async signTransaction(keys, tx) {
156
+ if (storedKeyPair === undefined || keys.evmAddress !== storedKeyPair.evmAddress) {
157
+ return Err(walletErrors.keyNotFound(keys.evmAddress));
158
+ }
159
+ if (!isSolanaTransaction(tx)) {
160
+ return Err(walletErrors.signingRejected('Unsupported transaction type'));
161
+ }
162
+ const messageBytes = tx.message.serialize();
163
+ const signResult = await fromPromise(bridge.signSolana(keyTag, messageBytes, biometricPrompt), (e) => mapNativeError(e));
164
+ if (!signResult.ok)
165
+ return signResult;
166
+ tx.signatures[0] = signResult.value.signature;
167
+ return Ok(tx);
168
+ },
169
+ async withAuthContext(prompt, fn) {
170
+ if (bridge.beginAuthContext === undefined || bridge.endAuthContext === undefined) {
171
+ // Bridge doesn't support auth context — passthrough
172
+ try {
173
+ return Ok(await fn());
174
+ }
175
+ catch (e) {
176
+ return Err(mapNativeError(e));
177
+ }
178
+ }
179
+ const contextResult = await fromPromise(bridge.beginAuthContext(prompt), (e) => mapNativeError(e));
180
+ if (!contextResult.ok)
181
+ return contextResult;
182
+ try {
183
+ const result = await fn();
184
+ return Ok(result);
185
+ }
186
+ catch (e) {
187
+ return Err(mapNativeError(e));
188
+ }
189
+ finally {
190
+ await bridge.endAuthContext(contextResult.value.contextId).catch(() => {
191
+ // Best-effort cleanup — context will expire naturally
192
+ });
193
+ }
194
+ },
195
+ destroy() {
196
+ storedKeyPair = undefined;
197
+ },
198
+ };
199
+ return backend;
200
+ }
201
+ //# sourceMappingURL=secure-enclave-backend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secure-enclave-backend.js","sourceRoot":"","sources":["../../src/signers/secure-enclave-backend.ts"],"names":[],"mappings":"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"}