@organigram/passkey-wallet 0.1.6

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 (79) hide show
  1. package/.organigram-docs-cache/passkey-wallet/api-extractor.json +35 -0
  2. package/.organigram-docs-cache/passkey-wallet/api-model/passkey-wallet.api.json +3166 -0
  3. package/.organigram-docs-cache/passkey-wallet/entry/index.d.ts +9 -0
  4. package/.organigram-docs-cache/passkey-wallet/tmp/node-compile-cache/v24.12.0-arm64-cf738c9d-501/05732508 +0 -0
  5. package/.organigram-docs-cache/passkey-wallet/tmp/node-compile-cache/v24.12.0-arm64-cf738c9d-501/166b6dbf +0 -0
  6. package/.organigram-docs-cache/passkey-wallet/tmp/node-compile-cache/v24.12.0-arm64-cf738c9d-501/41c20e23 +0 -0
  7. package/.organigram-docs-cache/passkey-wallet/tmp/node-compile-cache/v24.12.0-arm64-cf738c9d-501/7111ea58 +0 -0
  8. package/.organigram-docs-cache/passkey-wallet/tmp/tsx-501/17844-1822dfbab9819e9f6a93485fe3da5dbf3745311c +1 -0
  9. package/.organigram-docs-cache/passkey-wallet/tmp/tsx-501/17844-45a65cfdc7a50c53817c1dad3954ae3d2d2c35fb +1 -0
  10. package/.organigram-docs-cache/passkey-wallet/tmp/tsx-501/17844-fee5290b05398fe9e3b878deefd22383744f1526 +1 -0
  11. package/.organigram-docs-cache/passkey-wallet/yaml/passkey-wallet/createorganigrampasskeywalletinput.yml +17 -0
  12. package/.organigram-docs-cache/passkey-wallet/yaml/passkey-wallet/identitypasskeycapabilities.yml +16 -0
  13. package/.organigram-docs-cache/passkey-wallet/yaml/passkey-wallet/organigrampasskeycapabilities.yml +18 -0
  14. package/.organigram-docs-cache/passkey-wallet/yaml/passkey-wallet/organigrampasskeyprovider.yml +16 -0
  15. package/.organigram-docs-cache/passkey-wallet/yaml/passkey-wallet/organigrampasskeyprovideractions.yml +20 -0
  16. package/.organigram-docs-cache/passkey-wallet/yaml/passkey-wallet/passkeyprfunavailableerror.yml +28 -0
  17. package/.organigram-docs-cache/passkey-wallet/yaml/passkey-wallet/passkeyproviderevent.yml +11 -0
  18. package/.organigram-docs-cache/passkey-wallet/yaml/passkey-wallet/passkeyproviderlistener.yml +11 -0
  19. package/.organigram-docs-cache/passkey-wallet/yaml/passkey-wallet/passkeyregistrationresult.yml +15 -0
  20. package/.organigram-docs-cache/passkey-wallet/yaml/passkey-wallet/passkeyvaultdecrypterror.yml +28 -0
  21. package/.organigram-docs-cache/passkey-wallet/yaml/passkey-wallet/passkeyvaultenvelopedata.yml +18 -0
  22. package/.organigram-docs-cache/passkey-wallet/yaml/passkey-wallet/passkeyvaultenvelopeinput.yml +19 -0
  23. package/.organigram-docs-cache/passkey-wallet/yaml/passkey-wallet/passkeywalletapiclient.yml +33 -0
  24. package/.organigram-docs-cache/passkey-wallet/yaml/passkey-wallet/passkeywalletcapabilities.yml +11 -0
  25. package/.organigram-docs-cache/passkey-wallet/yaml/passkey-wallet/passkeywalletlogincapabilities.yml +14 -0
  26. package/.organigram-docs-cache/passkey-wallet/yaml/passkey-wallet/passkeywalletregistrationcapabilities.yml +18 -0
  27. package/.organigram-docs-cache/passkey-wallet/yaml/passkey-wallet/passkeywalletvaultpayload.yml +18 -0
  28. package/.organigram-docs-cache/passkey-wallet/yaml/passkey-wallet/unlockedpasskeywallet.yml +21 -0
  29. package/.organigram-docs-cache/passkey-wallet/yaml/passkey-wallet.yml +870 -0
  30. package/.organigram-docs-cache/passkey-wallet/yaml/toc.yml +43 -0
  31. package/.turbo/turbo-build.log +6 -0
  32. package/.turbo/turbo-docs$colon$generate.log +118 -0
  33. package/.turbo/turbo-lint.log +13 -0
  34. package/.turbo/turbo-test.log +152 -0
  35. package/.turbo/turbo-typecheck.log +5 -0
  36. package/CHANGELOG.md +8 -0
  37. package/LICENSE.md +21 -0
  38. package/README.md +427 -0
  39. package/__mocks__/organigram-js.ts +19 -0
  40. package/__mocks__/wagmi.ts +1 -0
  41. package/dist/crypto.d.ts +39 -0
  42. package/dist/crypto.js +95 -0
  43. package/dist/eip1193.d.ts +24 -0
  44. package/dist/eip1193.js +103 -0
  45. package/dist/errors.d.ts +7 -0
  46. package/dist/errors.js +13 -0
  47. package/dist/index.d.ts +4 -0
  48. package/dist/index.js +4 -0
  49. package/dist/rainbowkit.d.ts +14 -0
  50. package/dist/rainbowkit.js +128 -0
  51. package/dist/types.d.ts +45 -0
  52. package/dist/types.js +17 -0
  53. package/dist/vault.d.ts +10 -0
  54. package/dist/vault.js +41 -0
  55. package/dist/wallet.d.ts +15 -0
  56. package/dist/wallet.js +30 -0
  57. package/dist/webauthn-client.d.ts +73 -0
  58. package/dist/webauthn-client.js +234 -0
  59. package/dist/webauthn-server.d.ts +62 -0
  60. package/dist/webauthn-server.js +133 -0
  61. package/jest.config.ts +32 -0
  62. package/package.json +61 -0
  63. package/src/crypto.test.ts +69 -0
  64. package/src/crypto.ts +193 -0
  65. package/src/eip1193.ts +169 -0
  66. package/src/errors.ts +16 -0
  67. package/src/index.ts +4 -0
  68. package/src/rainbowkit.test.ts +42 -0
  69. package/src/rainbowkit.ts +171 -0
  70. package/src/types.ts +82 -0
  71. package/src/vault.test.ts +23 -0
  72. package/src/vault.ts +77 -0
  73. package/src/wallet.ts +61 -0
  74. package/src/webauthn-client.test.ts +103 -0
  75. package/src/webauthn-client.ts +430 -0
  76. package/src/webauthn-server.test.ts +43 -0
  77. package/src/webauthn-server.ts +258 -0
  78. package/tsconfig.build.json +15 -0
  79. package/tsconfig.json +27 -0
@@ -0,0 +1,103 @@
1
+ import { createWalletClient, getAddress, hexToString, http, numberToHex } from 'viem';
2
+ const normalizePersonalSignMessage = (message) => {
3
+ if (typeof message !== 'string') {
4
+ throw new Error('Passkey wallet expected a string message.');
5
+ }
6
+ if (message.startsWith('0x')) {
7
+ return hexToString(message);
8
+ }
9
+ return message;
10
+ };
11
+ export const createPasskeyWalletProvider = ({ wallet, chain, rpcUrl, switchChain, actions }) => {
12
+ const listeners = new Map();
13
+ let currentChain = chain;
14
+ const emit = (event, ...args) => {
15
+ listeners.get(event)?.forEach(listener => {
16
+ listener(...args);
17
+ });
18
+ };
19
+ const getWalletClient = () => createWalletClient({
20
+ account: wallet.account,
21
+ chain: currentChain,
22
+ transport: http(rpcUrl)
23
+ });
24
+ const request = (async ({ method, params }) => {
25
+ const requestParams = Array.isArray(params) ? params : [];
26
+ switch (method) {
27
+ case 'eth_requestAccounts':
28
+ case 'eth_accounts':
29
+ return [wallet.address];
30
+ case 'eth_chainId':
31
+ return numberToHex(currentChain.id);
32
+ case 'wallet_switchEthereumChain': {
33
+ const chainId = Number.parseInt(String(requestParams[0]?.chainId), 16);
34
+ currentChain = switchChain(chainId);
35
+ emit('chainChanged', numberToHex(currentChain.id));
36
+ return null;
37
+ }
38
+ case 'personal_sign':
39
+ return await wallet.account.signMessage({
40
+ message: normalizePersonalSignMessage(requestParams[0])
41
+ });
42
+ case 'eth_sign':
43
+ return await wallet.account.signMessage({
44
+ message: normalizePersonalSignMessage(requestParams[1])
45
+ });
46
+ case 'eth_signTypedData':
47
+ case 'eth_signTypedData_v3':
48
+ case 'eth_signTypedData_v4': {
49
+ const typedData = typeof requestParams[1] === 'string'
50
+ ? JSON.parse(requestParams[1])
51
+ : requestParams[1];
52
+ return await wallet.account.signTypedData(typedData);
53
+ }
54
+ case 'eth_sendTransaction':
55
+ return await getWalletClient().sendTransaction(requestParams[0]);
56
+ case 'organigram_addPasskey': {
57
+ return await actions.registerAdditionalPasskeyCredential({
58
+ wallet,
59
+ name: typeof requestParams[0] === 'object' &&
60
+ requestParams[0] != null &&
61
+ 'name' in requestParams[0]
62
+ ? String(requestParams[0].name ?? '')
63
+ : undefined
64
+ });
65
+ }
66
+ case 'organigram_exportRecoveryPhrase':
67
+ return await actions.exportPasskeyWalletRecoveryPhrase({
68
+ expectedAddress: wallet.address
69
+ });
70
+ default: {
71
+ const response = await fetch(rpcUrl, {
72
+ method: 'POST',
73
+ headers: {
74
+ 'Content-Type': 'application/json'
75
+ },
76
+ body: JSON.stringify({
77
+ jsonrpc: '2.0',
78
+ id: 1,
79
+ method,
80
+ params: requestParams
81
+ })
82
+ });
83
+ const body = (await response.json());
84
+ if (body.error != null) {
85
+ throw new Error(body.error.message ?? 'RPC request failed.');
86
+ }
87
+ return body.result;
88
+ }
89
+ }
90
+ });
91
+ return {
92
+ request,
93
+ on: (event, listener) => {
94
+ const eventListeners = listeners.get(event) ?? new Set();
95
+ eventListeners.add(listener);
96
+ listeners.set(event, eventListeners);
97
+ },
98
+ removeListener: (event, listener) => {
99
+ listeners.get(event)?.delete(listener);
100
+ }
101
+ };
102
+ };
103
+ export const normalizePasskeyWalletAddress = (address) => getAddress(address);
@@ -0,0 +1,7 @@
1
+ export declare const passkeyPrfUnavailableErrorMessage = "This password manager is not compatible with Organigram's passkey wallet. Please use a different password manager to unlock your wallet.";
2
+ export declare class PasskeyPrfUnavailableError extends Error {
3
+ constructor(message?: string);
4
+ }
5
+ export declare class PasskeyVaultDecryptError extends Error {
6
+ constructor(message?: string);
7
+ }
package/dist/errors.js ADDED
@@ -0,0 +1,13 @@
1
+ export const passkeyPrfUnavailableErrorMessage = "This password manager is not compatible with Organigram's passkey wallet. Please use a different password manager to unlock your wallet.";
2
+ export class PasskeyPrfUnavailableError extends Error {
3
+ constructor(message = passkeyPrfUnavailableErrorMessage) {
4
+ super(message);
5
+ this.name = 'PasskeyPrfUnavailableError';
6
+ }
7
+ }
8
+ export class PasskeyVaultDecryptError extends Error {
9
+ constructor(message = 'Unable to decrypt passkey wallet.') {
10
+ super(message);
11
+ this.name = 'PasskeyVaultDecryptError';
12
+ }
13
+ }
@@ -0,0 +1,4 @@
1
+ export * from './crypto';
2
+ export * from './types';
3
+ export * from './vault';
4
+ export * from './wallet';
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export * from './crypto';
2
+ export * from './types';
3
+ export * from './vault';
4
+ export * from './wallet';
@@ -0,0 +1,14 @@
1
+ import type { Wallet } from '@rainbow-me/rainbowkit';
2
+ import { type OrganigramPasskeyProviderActions } from './eip1193';
3
+ import { type OrganigramPasskeyCapabilities, type UnlockedPasskeyWallet } from './types';
4
+ export { organigramPasskeyWalletIcon, organigramPasskeyWalletId } from './types';
5
+ export declare const isOrganigramPasskeyConnector: ({ id }: {
6
+ id: string;
7
+ }) => boolean;
8
+ export type CreateOrganigramPasskeyWalletInput = OrganigramPasskeyProviderActions & {
9
+ unlockOrCreatePasskeyWallet: (input: {
10
+ capabilities: OrganigramPasskeyCapabilities;
11
+ targetChainId: number;
12
+ }) => Promise<UnlockedPasskeyWallet>;
13
+ };
14
+ export declare const createOrganigramPasskeyWallet: ({ unlockOrCreatePasskeyWallet, registerAdditionalPasskeyCredential, exportPasskeyWalletRecoveryPhrase }: CreateOrganigramPasskeyWalletInput) => Wallet;
@@ -0,0 +1,128 @@
1
+ import { getAddress } from 'viem';
2
+ import { createConnector } from 'wagmi';
3
+ import { createPasskeyWalletProvider } from './eip1193';
4
+ import { organigramPasskeyWalletIcon, organigramPasskeyWalletId } from './types';
5
+ export { organigramPasskeyWalletIcon, organigramPasskeyWalletId } from './types';
6
+ const walletName = 'Passkey Wallet';
7
+ const passkeyConnectorIds = new Set([organigramPasskeyWalletId]);
8
+ export const isOrganigramPasskeyConnector = ({ id }) => passkeyConnectorIds.has(id);
9
+ export const createOrganigramPasskeyWallet = ({ unlockOrCreatePasskeyWallet, registerAdditionalPasskeyCredential, exportPasskeyWalletRecoveryPhrase }) => ({
10
+ id: organigramPasskeyWalletId,
11
+ name: walletName,
12
+ shortName: 'Passkey',
13
+ rdns: 'ai.organigram.passkey',
14
+ iconUrl: organigramPasskeyWalletIcon,
15
+ iconAccent: '#00C2A8',
16
+ iconBackground: '#18272B',
17
+ installed: true,
18
+ createConnector: (walletDetails) => createConnector(config => {
19
+ let provider = null;
20
+ let wallet = null;
21
+ let activeChain = config.chains[0];
22
+ const resolveChain = (chainId) => {
23
+ const chain = chainId == null
24
+ ? activeChain
25
+ : config.chains.find(candidate => candidate.id === chainId);
26
+ if (chain == null) {
27
+ throw new Error('Unsupported network for Passkey Wallet.');
28
+ }
29
+ return chain;
30
+ };
31
+ const getRpcUrl = (chain) => chain.rpcUrls.default.http[0] ?? chain.rpcUrls.public?.http[0] ?? '';
32
+ return {
33
+ ...walletDetails,
34
+ id: organigramPasskeyWalletId,
35
+ name: walletName,
36
+ type: 'passkey-wallet',
37
+ async connect(parameters) {
38
+ activeChain = resolveChain(parameters?.chainId);
39
+ const unlockedWallet = await unlockOrCreatePasskeyWallet({
40
+ capabilities: parameters
41
+ ?.capabilities ?? {},
42
+ targetChainId: activeChain.id
43
+ });
44
+ wallet = {
45
+ ...unlockedWallet,
46
+ address: getAddress(unlockedWallet.address)
47
+ };
48
+ provider = createPasskeyWalletProvider({
49
+ wallet,
50
+ chain: activeChain,
51
+ rpcUrl: getRpcUrl(activeChain),
52
+ switchChain: chainId => {
53
+ activeChain = resolveChain(chainId);
54
+ config.emitter.emit('change', {
55
+ chainId: activeChain.id
56
+ });
57
+ return activeChain;
58
+ },
59
+ actions: {
60
+ registerAdditionalPasskeyCredential,
61
+ exportPasskeyWalletRecoveryPhrase
62
+ }
63
+ });
64
+ config.emitter.emit('connect', {
65
+ accounts: [wallet.address],
66
+ chainId: activeChain.id
67
+ });
68
+ if (parameters?.withCapabilities === true) {
69
+ return {
70
+ accounts: [
71
+ {
72
+ address: wallet.address,
73
+ capabilities: {}
74
+ }
75
+ ],
76
+ chainId: activeChain.id
77
+ };
78
+ }
79
+ return {
80
+ accounts: [wallet.address],
81
+ chainId: activeChain.id
82
+ };
83
+ },
84
+ async disconnect() {
85
+ wallet = null;
86
+ provider = null;
87
+ config.emitter.emit('disconnect');
88
+ },
89
+ async getAccounts() {
90
+ return wallet == null ? [] : [wallet.address];
91
+ },
92
+ async getChainId() {
93
+ return activeChain.id;
94
+ },
95
+ async getProvider() {
96
+ if (provider == null) {
97
+ throw new Error('Passkey Wallet is locked.');
98
+ }
99
+ return provider;
100
+ },
101
+ async isAuthorized() {
102
+ return wallet != null && wallet.expiresAt > Date.now();
103
+ },
104
+ async switchChain({ chainId }) {
105
+ activeChain = resolveChain(chainId);
106
+ config.emitter.emit('change', {
107
+ chainId
108
+ });
109
+ return activeChain;
110
+ },
111
+ onAccountsChanged(accounts) {
112
+ config.emitter.emit('change', {
113
+ accounts: accounts.map(account => getAddress(account))
114
+ });
115
+ },
116
+ onChainChanged(chainId) {
117
+ config.emitter.emit('change', {
118
+ chainId: Number.parseInt(chainId, 16)
119
+ });
120
+ },
121
+ onDisconnect() {
122
+ wallet = null;
123
+ provider = null;
124
+ config.emitter.emit('disconnect');
125
+ }
126
+ };
127
+ })
128
+ });
@@ -0,0 +1,45 @@
1
+ import type { HDAccount } from 'viem/accounts';
2
+ export declare const organigramPasskeyWalletId = "organigram-passkeys";
3
+ export declare const organigramPasskeyWalletIcon = "/png/logo-gradient.png";
4
+ export type OrganigramPasskeyCapabilities = {
5
+ method?: 'login' | 'register';
6
+ name?: string;
7
+ identity?: {
8
+ email: string;
9
+ };
10
+ };
11
+ export type PasskeyWalletLoginCapabilities = {
12
+ method: 'login';
13
+ };
14
+ export type PasskeyWalletRegistrationCapabilities = {
15
+ method: 'register';
16
+ name: string;
17
+ identity?: {
18
+ email: string;
19
+ };
20
+ };
21
+ export type PasskeyWalletCapabilities = PasskeyWalletLoginCapabilities | PasskeyWalletRegistrationCapabilities;
22
+ export type IdentityPasskeyCapabilities = PasskeyWalletRegistrationCapabilities & {
23
+ identity: {
24
+ email: string;
25
+ };
26
+ };
27
+ export declare const buildIdentityPasskeyCapabilities: (email: string) => IdentityPasskeyCapabilities;
28
+ export declare const buildPasskeyWalletCapabilities: () => PasskeyWalletCapabilities;
29
+ export declare const buildEmailPasskeyCapabilities: (email: string) => IdentityPasskeyCapabilities;
30
+ export type UnlockedPasskeyWallet = {
31
+ address: `0x${string}`;
32
+ account: HDAccount;
33
+ recoveryPhrase: string;
34
+ userEncryptionPrivateKey: JsonWebKey;
35
+ userEncryptionPublicKey: JsonWebKey;
36
+ userEncryptionKeyVersion: number;
37
+ credentialId: string;
38
+ expiresAt: number;
39
+ };
40
+ export type PasskeyRegistrationResult = {
41
+ address: `0x${string}`;
42
+ credentialId: string;
43
+ };
44
+ export type PasskeyProviderEvent = 'accountsChanged' | 'chainChanged' | 'disconnect';
45
+ export type PasskeyProviderListener = (...args: unknown[]) => void;
package/dist/types.js ADDED
@@ -0,0 +1,17 @@
1
+ export const organigramPasskeyWalletId = 'organigram-passkeys';
2
+ export const organigramPasskeyWalletIcon = '/png/logo-gradient.png';
3
+ const normalizePasskeyIdentityEmail = (email) => email.trim().toLowerCase();
4
+ export const buildIdentityPasskeyCapabilities = (email) => {
5
+ const normalizedEmail = normalizePasskeyIdentityEmail(email);
6
+ return {
7
+ method: 'register',
8
+ name: normalizedEmail,
9
+ identity: {
10
+ email: normalizedEmail
11
+ }
12
+ };
13
+ };
14
+ export const buildPasskeyWalletCapabilities = () => ({
15
+ method: 'login'
16
+ });
17
+ export const buildEmailPasskeyCapabilities = buildIdentityPasskeyCapabilities;
@@ -0,0 +1,10 @@
1
+ export type PasskeyWalletVaultPayload = {
2
+ version: 1;
3
+ recoveryPhrase: string;
4
+ userEncryptionPrivateKey: JsonWebKey;
5
+ userEncryptionPublicKey: JsonWebKey;
6
+ userEncryptionKeyVersion: number;
7
+ };
8
+ export declare const serializePasskeyWalletVaultPayload: ({ recoveryPhrase, userEncryptionPrivateKey, userEncryptionPublicKey, userEncryptionKeyVersion }: Omit<PasskeyWalletVaultPayload, "version">) => string;
9
+ export declare const parsePasskeyWalletVaultPayload: (plaintext: string) => PasskeyWalletVaultPayload;
10
+ export declare const createPasskeyWalletVaultPayload: (recoveryPhrase: string) => Promise<PasskeyWalletVaultPayload>;
package/dist/vault.js ADDED
@@ -0,0 +1,41 @@
1
+ import { createEncryptionKeyVersion, exportUserPrivateKey, exportUserPublicKey, generateUserEncryptionKeyPair } from '@organigram/js';
2
+ export const serializePasskeyWalletVaultPayload = ({ recoveryPhrase, userEncryptionPrivateKey, userEncryptionPublicKey, userEncryptionKeyVersion }) => JSON.stringify({
3
+ version: 1,
4
+ recoveryPhrase,
5
+ userEncryptionPrivateKey,
6
+ userEncryptionPublicKey,
7
+ userEncryptionKeyVersion
8
+ });
9
+ export const parsePasskeyWalletVaultPayload = (plaintext) => {
10
+ const payload = JSON.parse(plaintext);
11
+ if (payload.version !== 1) {
12
+ throw new Error('Unsupported passkey wallet vault payload version.');
13
+ }
14
+ if (typeof payload.recoveryPhrase !== 'string' ||
15
+ payload.recoveryPhrase.trim() === '') {
16
+ throw new Error('Passkey wallet vault is missing its recovery phrase.');
17
+ }
18
+ if (payload.userEncryptionPrivateKey == null) {
19
+ throw new Error('Passkey wallet vault is missing its IPFS private key.');
20
+ }
21
+ if (payload.userEncryptionPublicKey == null) {
22
+ throw new Error('Passkey wallet vault is missing its IPFS public key.');
23
+ }
24
+ if (!Number.isInteger(payload.userEncryptionKeyVersion) ||
25
+ payload.userEncryptionKeyVersion == null) {
26
+ throw new Error('Passkey wallet vault has an invalid IPFS key version.');
27
+ }
28
+ return payload;
29
+ };
30
+ export const createPasskeyWalletVaultPayload = async (recoveryPhrase) => {
31
+ const userEncryptionKeyPair = await generateUserEncryptionKeyPair();
32
+ const userEncryptionPrivateKey = await exportUserPrivateKey(userEncryptionKeyPair);
33
+ const userEncryptionPublicKey = await exportUserPublicKey(userEncryptionKeyPair);
34
+ return {
35
+ version: 1,
36
+ recoveryPhrase,
37
+ userEncryptionPrivateKey,
38
+ userEncryptionPublicKey,
39
+ userEncryptionKeyVersion: createEncryptionKeyVersion()
40
+ };
41
+ };
@@ -0,0 +1,15 @@
1
+ import type { OrganigramPasskeyCapabilities, UnlockedPasskeyWallet } from './types';
2
+ import { type PasskeyWalletVaultPayload } from './vault';
3
+ export declare const unlockedPasskeyWalletTtlMs: number;
4
+ export declare const createUnlockedPasskeyWallet: ({ address, credentialId, vaultPayload, now }: {
5
+ address: `0x${string}`;
6
+ credentialId: string;
7
+ vaultPayload: PasskeyWalletVaultPayload;
8
+ now?: number;
9
+ }) => UnlockedPasskeyWallet;
10
+ export declare const createNewPasskeyWalletVault: ({ capabilities }: {
11
+ capabilities: OrganigramPasskeyCapabilities;
12
+ }) => Promise<{
13
+ address: `0x${string}`;
14
+ vaultPayload: PasskeyWalletVaultPayload;
15
+ }>;
package/dist/wallet.js ADDED
@@ -0,0 +1,30 @@
1
+ import { english, generateMnemonic, mnemonicToAccount } from 'viem/accounts';
2
+ import { createPasskeyWalletVaultPayload } from './vault';
3
+ export const unlockedPasskeyWalletTtlMs = 15 * 60 * 1000;
4
+ export const createUnlockedPasskeyWallet = ({ address, credentialId, vaultPayload, now = Date.now() }) => {
5
+ const account = mnemonicToAccount(vaultPayload.recoveryPhrase);
6
+ return {
7
+ address,
8
+ account,
9
+ recoveryPhrase: vaultPayload.recoveryPhrase,
10
+ userEncryptionPrivateKey: vaultPayload.userEncryptionPrivateKey,
11
+ userEncryptionPublicKey: vaultPayload.userEncryptionPublicKey,
12
+ userEncryptionKeyVersion: vaultPayload.userEncryptionKeyVersion,
13
+ credentialId,
14
+ expiresAt: now + unlockedPasskeyWalletTtlMs
15
+ };
16
+ };
17
+ export const createNewPasskeyWalletVault = async ({ capabilities }) => {
18
+ const recoveryPhrase = generateMnemonic(english, 128);
19
+ const vaultPayload = await createPasskeyWalletVaultPayload(recoveryPhrase);
20
+ const account = mnemonicToAccount(recoveryPhrase);
21
+ return {
22
+ address: account.address,
23
+ vaultPayload: {
24
+ ...vaultPayload,
25
+ recoveryPhrase: capabilities.method === 'register'
26
+ ? vaultPayload.recoveryPhrase
27
+ : vaultPayload.recoveryPhrase
28
+ }
29
+ };
30
+ };
@@ -0,0 +1,73 @@
1
+ import { startAuthentication, startRegistration } from '@simplewebauthn/browser';
2
+ import { type PasskeyVaultEnvelopeData } from './crypto';
3
+ import type { OrganigramPasskeyCapabilities, PasskeyRegistrationResult, UnlockedPasskeyWallet } from './types';
4
+ import { parsePasskeyWalletVaultPayload, serializePasskeyWalletVaultPayload, type PasskeyWalletVaultPayload } from './vault';
5
+ export { parsePasskeyWalletVaultPayload, serializePasskeyWalletVaultPayload };
6
+ export type { OrganigramPasskeyCapabilities, UnlockedPasskeyWallet } from './types';
7
+ type PasskeyRegisterOptionsResponse = {
8
+ options: Parameters<typeof startRegistration>[0]['optionsJSON'];
9
+ };
10
+ type PasskeyUnlockOptionsResponse = {
11
+ options: Parameters<typeof startAuthentication>[0]['optionsJSON'];
12
+ hasCredentials: boolean;
13
+ };
14
+ type PasskeyUnlockVerifyResponse = {
15
+ address: `0x${string}`;
16
+ credentialId: string;
17
+ envelope: PasskeyVaultEnvelopeData;
18
+ };
19
+ export type PasskeyWalletApiClient = {
20
+ registerOptions: (input: {
21
+ address: `0x${string}`;
22
+ email?: string | null;
23
+ name?: string | null;
24
+ }) => Promise<PasskeyRegisterOptionsResponse>;
25
+ registerVerify: (input: {
26
+ response: unknown;
27
+ envelope: {
28
+ address: `0x${string}`;
29
+ encryptedMnemonic: string;
30
+ salt: string;
31
+ nonce: string;
32
+ algorithm: string;
33
+ keyVersion: number;
34
+ };
35
+ }) => Promise<PasskeyRegistrationResult>;
36
+ unlockOptions: () => Promise<PasskeyUnlockOptionsResponse>;
37
+ unlockVerify: (input: {
38
+ response: unknown;
39
+ }) => Promise<PasskeyUnlockVerifyResponse>;
40
+ };
41
+ export declare const createFetchPasskeyWalletApiClient: (basePath?: string) => PasskeyWalletApiClient;
42
+ export declare const hydratePasskeyPrfOptions: <T extends {
43
+ extensions?: unknown;
44
+ }>(options: T) => T;
45
+ export declare function registerPasskeyCredentialEnvelope({ api, address, vaultPayload, email, name }: {
46
+ api: PasskeyWalletApiClient;
47
+ address: `0x${string}`;
48
+ vaultPayload: PasskeyWalletVaultPayload;
49
+ email?: string | null;
50
+ name?: string | null;
51
+ }): Promise<PasskeyRegistrationResult>;
52
+ export declare const registerPasskeyWallet: ({ api, capabilities }: {
53
+ api: PasskeyWalletApiClient;
54
+ capabilities: OrganigramPasskeyCapabilities;
55
+ }) => Promise<UnlockedPasskeyWallet>;
56
+ export declare const unlockPasskeyWallet: ({ api }: {
57
+ api: PasskeyWalletApiClient;
58
+ }) => Promise<UnlockedPasskeyWallet | null>;
59
+ export declare const exportPasskeyWalletRecoveryPhrase: ({ api, expectedAddress }: {
60
+ api: PasskeyWalletApiClient;
61
+ expectedAddress: `0x${string}`;
62
+ }) => Promise<string>;
63
+ export declare const registerAdditionalPasskeyCredential: ({ api, wallet, name }: {
64
+ api: PasskeyWalletApiClient;
65
+ wallet: UnlockedPasskeyWallet;
66
+ name?: string;
67
+ }) => Promise<PasskeyRegistrationResult>;
68
+ export declare const isPasskeyCredentialUnavailableError: (error: unknown) => boolean;
69
+ export declare const unlockOrCreatePasskeyWallet: ({ api, capabilities }: {
70
+ api: PasskeyWalletApiClient;
71
+ capabilities: OrganigramPasskeyCapabilities;
72
+ targetChainId: number;
73
+ }) => Promise<UnlockedPasskeyWallet>;