@thru/passkey 0.2.22 → 0.2.24

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.
@@ -24,6 +24,7 @@ __export(add_device_exports, {
24
24
  });
25
25
  module.exports = __toCommonJS(add_device_exports);
26
26
  var import_passkey_manager = require("@thru/programs/passkey-manager");
27
+ var import_multicall = require("@thru/programs/multicall");
27
28
  async function addDeviceToAccount(params) {
28
29
  const status = params.onStatus ?? (() => {
29
30
  });
@@ -43,14 +44,13 @@ async function addDeviceToAccount(params) {
43
44
  );
44
45
  }
45
46
  const newAuthorityIdx = parsed.authorities.length;
46
- const addAuthorityInstruction = (0, import_passkey_manager.encodeAddAuthorityInstruction)({
47
- authority: params.newAuthority
48
- });
49
- let trailingInstructionData = addAuthorityInstruction;
50
47
  let readWriteAccounts = [];
48
+ let lookupSeed;
49
+ let lookupAddressBytes;
50
+ let lookupProof;
51
51
  if (params.credentialId) {
52
- const lookupSeed = await (0, import_passkey_manager.createCredentialLookupSeed)(params.credentialId);
53
- const lookupAddressBytes = await (0, import_passkey_manager.deriveWalletAddress)(
52
+ lookupSeed = await (0, import_passkey_manager.createCredentialLookupSeed)(params.credentialId);
53
+ lookupAddressBytes = await (0, import_passkey_manager.deriveWalletAddress)(
54
54
  lookupSeed,
55
55
  params.programAddress
56
56
  );
@@ -59,55 +59,76 @@ async function addDeviceToAccount(params) {
59
59
  proofType: 1,
60
60
  address: lookupAddressBytes
61
61
  });
62
- const ctx2 = (0, import_passkey_manager.buildAccountContext)({
63
- walletAddress: params.walletAddress,
64
- readWriteAccounts: [lookupAddressBytes],
65
- readOnlyAccounts: []
66
- });
67
- const registerCredentialInstruction = (0, import_passkey_manager.encodeRegisterCredentialInstruction)({
68
- walletAccountIdx: ctx2.walletAccountIdx,
69
- lookupAccountIdx: ctx2.getAccountIndex(lookupAddressBytes),
70
- seed: lookupSeed,
71
- stateProof: proofResult.proof
72
- });
73
- trailingInstructionData = (0, import_passkey_manager.concatenateInstructions)([
74
- addAuthorityInstruction,
75
- registerCredentialInstruction
76
- ]);
62
+ lookupProof = proofResult.proof;
77
63
  readWriteAccounts = [lookupAddressBytes];
78
64
  }
79
65
  const ctx = (0, import_passkey_manager.buildAccountContext)({
80
66
  walletAddress: params.walletAddress,
81
67
  readWriteAccounts,
82
- readOnlyAccounts: []
68
+ readOnlyAccounts: params.credentialId ? [import_multicall.MULTICALL_PROGRAM_PUBKEY] : [],
69
+ programAddress: params.programAddress
70
+ });
71
+ const passkeyProgramPubkey = (0, import_passkey_manager.decodeAddress)(params.programAddress);
72
+ const addAuthorityInstruction = (0, import_passkey_manager.encodeAddAuthorityInstruction)({
73
+ walletAccountIdx: ctx.walletAccountIdx,
74
+ authority: params.newAuthority
83
75
  });
76
+ let targetProgramIdx = ctx.getAccountIndex(passkeyProgramPubkey);
77
+ let targetInstructionData = addAuthorityInstruction;
78
+ if (params.credentialId) {
79
+ if (!lookupSeed || !lookupAddressBytes || !lookupProof) {
80
+ throw new Error("Credential lookup proof data missing");
81
+ }
82
+ const registerCredentialInstruction = (0, import_passkey_manager.encodeRegisterCredentialInstruction)({
83
+ walletAccountIdx: ctx.walletAccountIdx,
84
+ lookupAccountIdx: ctx.getAccountIndex(lookupAddressBytes),
85
+ seed: lookupSeed,
86
+ stateProof: lookupProof
87
+ });
88
+ targetProgramIdx = ctx.getAccountIndex(import_multicall.MULTICALL_PROGRAM_PUBKEY);
89
+ targetInstructionData = (0, import_multicall.buildMulticallInstruction)([
90
+ {
91
+ programIdx: ctx.getAccountIndex(passkeyProgramPubkey),
92
+ instructionData: addAuthorityInstruction
93
+ },
94
+ {
95
+ programIdx: ctx.getAccountIndex(passkeyProgramPubkey),
96
+ instructionData: registerCredentialInstruction
97
+ }
98
+ ]);
99
+ }
84
100
  const challenge = await (0, import_passkey_manager.createValidateChallenge)(
85
101
  parsed.nonce,
86
102
  ctx.accountAddresses,
87
- trailingInstructionData
103
+ ctx.walletAccountIdx,
104
+ params.authIdx,
105
+ {
106
+ programIdx: targetProgramIdx,
107
+ instructionData: targetInstructionData
108
+ }
88
109
  );
89
110
  status("Waiting for passkey approval...");
90
111
  const signature = await params.passkey.signChallenge(challenge);
91
112
  const validateInstruction = (0, import_passkey_manager.encodeValidateInstruction)({
92
113
  walletAccountIdx: ctx.walletAccountIdx,
93
114
  authIdx: params.authIdx,
115
+ targetInstruction: {
116
+ programIdx: targetProgramIdx,
117
+ instructionData: targetInstructionData
118
+ },
94
119
  signatureR: signature.signatureR,
95
120
  signatureS: signature.signatureS,
96
121
  authenticatorData: signature.authenticatorData,
97
122
  clientDataJSON: signature.clientDataJSON
98
123
  });
99
- const instructionData = (0, import_passkey_manager.concatenateInstructions)([
100
- validateInstruction,
101
- trailingInstructionData
102
- ]);
103
124
  status("Sending transaction...");
104
125
  const result = await params.executor({
105
126
  thru: params.thru,
106
127
  walletSigner: params.walletSigner,
107
- instructionData,
128
+ instructionData: validateInstruction,
108
129
  readWriteAddresses: ctx.readWriteAddresses,
109
130
  readOnlyAddresses: ctx.readOnlyAddresses,
110
- label: params.credentialId ? "VALIDATE + ADD_AUTHORITY + REGISTER_CREDENTIAL" : "VALIDATE + ADD_AUTHORITY"
131
+ label: params.credentialId ? "VALIDATE -> MULTICALL(ADD_AUTHORITY, REGISTER_CREDENTIAL)" : "VALIDATE -> ADD_AUTHORITY"
111
132
  });
112
133
  return { ...result, newAuthorityIdx };
113
134
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/auth/add-device.ts"],"sourcesContent":["/* Add-passkey-to-account transaction builder, lifted from\n `web/wallet-auth-manager/app/page.tsx` (`runValidateThen`,\n `handleSubmitAddPasskey`) so the wallet's `/embedded` post-connect\n step can reuse the exact same flow.\n\n Builds the on-chain transaction:\n VALIDATE(existingAuthority) + ADD_AUTHORITY(newPasskey) [+ REGISTER_CREDENTIAL]\n asks the caller's existing passkey to sign the challenge, then asks\n the caller's wallet signer to sign the assembled transaction, sends\n it, and returns the result. */\n\nimport {\n type Authority,\n buildAccountContext,\n concatenateInstructions,\n createValidateChallenge,\n createCredentialLookupSeed,\n deriveWalletAddress,\n encodeAddAuthorityInstruction,\n encodeRegisterCredentialInstruction,\n encodeValidateInstruction,\n parseWalletAuthorities,\n type ParsedAuthority,\n type WalletSigner,\n} from \"@thru/programs/passkey-manager\";\n\n/** Minimal shape required from a passkey signer. Both web's\n `signWithDiscoverablePasskey`/`signWithPasskey` and mobile's\n counterparts conform. */\nexport interface PasskeyChallengeSigner {\n signChallenge: (challenge: Uint8Array) => Promise<{\n signatureR: Uint8Array;\n signatureS: Uint8Array;\n authenticatorData: Uint8Array;\n clientDataJSON: Uint8Array;\n }>;\n}\n\n/** Minimal shape required from a Thru chain client. Loosely-typed\n because @thru/sdk's DTS emit is currently broken in this\n repo. The caller passes the real Thru and we narrow operationally. */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyThruClient = any;\n\nexport interface AddDeviceParams {\n /** Loosely-typed Thru chain client (`@thru/sdk/client`). */\n thru: AnyThruClient;\n /** Wallet (the on-chain WalletAccount) to attach the passkey to. */\n walletAddress: string;\n /** Index of the existing authority that approves this change. Must\n currently be a passkey authority. */\n authIdx: number;\n /** New passkey to attach. tag = 1 (passkey). */\n newAuthority: Authority;\n /** Optional credential-lookup registration so the new passkey is\n discoverable on subsequent sign-ins. */\n credentialId?: Uint8Array;\n walletName?: string;\n /** Existing-passkey challenge signer (web or mobile). */\n passkey: PasskeyChallengeSigner;\n /** Wallet transaction signer that returns base64(signed bytes). */\n walletSigner: WalletSigner;\n /** Passkey program address (base58). */\n programAddress: string;\n /** Sign-and-send executor (lifted from passkey-transaction.ts in the\n wallet-auth-manager - wallet apps own this because it depends on\n the `Thru` client's transaction builder). */\n executor: TxExecutor;\n /** Optional status callback so UIs can show progress. */\n onStatus?: (message: string) => void;\n}\n\nexport interface TxExecutorParams {\n thru: AnyThruClient;\n walletSigner: WalletSigner;\n instructionData: Uint8Array;\n readWriteAddresses: string[];\n readOnlyAddresses: string[];\n label: string;\n}\n\nexport interface TxExecutorResult {\n signature: string;\n /** Loosely-typed because @thru/sdk types aren't available. */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n execution: any;\n}\n\nexport type TxExecutor = (\n params: TxExecutorParams,\n) => Promise<TxExecutorResult>;\n\nexport interface AddDeviceResult extends TxExecutorResult {\n /** The new passkey's authority index after the transaction lands. */\n newAuthorityIdx: number;\n}\n\n/**\n * Run VALIDATE + ADD_AUTHORITY [+ REGISTER_CREDENTIAL] to attach a new\n * passkey to an on-chain WalletAccount.\n */\nexport async function addDeviceToAccount(\n params: AddDeviceParams,\n): Promise<AddDeviceResult> {\n const status = params.onStatus ?? (() => {});\n\n const walletAccount = await params.thru.accounts.get(params.walletAddress);\n const walletData: Uint8Array | undefined = walletAccount?.data?.data;\n if (!walletData) {\n throw new Error(\"Wallet account data missing\");\n }\n\n const parsed = parseWalletAuthorities(walletData);\n const authorizing: ParsedAuthority | undefined =\n parsed.authorities[params.authIdx];\n if (!authorizing) {\n throw new Error(\"Authorization index out of bounds\");\n }\n if (authorizing.kind !== \"passkey\") {\n throw new Error(\n \"addDeviceToAccount currently requires a passkey authority for VALIDATE\",\n );\n }\n\n /* The new authority will land at the next free slot. */\n const newAuthorityIdx = parsed.authorities.length;\n\n /* Build the instruction sequence after the VALIDATE. */\n const addAuthorityInstruction = encodeAddAuthorityInstruction({\n authority: params.newAuthority,\n });\n\n let trailingInstructionData = addAuthorityInstruction;\n let readWriteAccounts: Uint8Array[] = [];\n\n if (params.credentialId) {\n const lookupSeed = await createCredentialLookupSeed(params.credentialId);\n const lookupAddressBytes = await deriveWalletAddress(\n lookupSeed,\n params.programAddress,\n );\n\n status(\"Fetching state proof for credential lookup...\");\n const proofResult = await params.thru.proofs.generate({\n proofType: 1 /* StateProofType.CREATING */,\n address: lookupAddressBytes,\n });\n\n const ctx = buildAccountContext({\n walletAddress: params.walletAddress,\n readWriteAccounts: [lookupAddressBytes],\n readOnlyAccounts: [],\n });\n\n const registerCredentialInstruction = encodeRegisterCredentialInstruction({\n walletAccountIdx: ctx.walletAccountIdx,\n lookupAccountIdx: ctx.getAccountIndex(lookupAddressBytes),\n seed: lookupSeed,\n stateProof: proofResult.proof,\n });\n\n trailingInstructionData = concatenateInstructions([\n addAuthorityInstruction,\n registerCredentialInstruction,\n ]);\n readWriteAccounts = [lookupAddressBytes];\n }\n\n /* Build the VALIDATE challenge over (nonce, account_addresses,\n trailing_instruction_data) and ask the caller's passkey to sign. */\n const ctx = buildAccountContext({\n walletAddress: params.walletAddress,\n readWriteAccounts,\n readOnlyAccounts: [],\n });\n\n const challenge = await createValidateChallenge(\n parsed.nonce,\n ctx.accountAddresses,\n trailingInstructionData,\n );\n\n status(\"Waiting for passkey approval...\");\n const signature = await params.passkey.signChallenge(challenge);\n\n const validateInstruction = encodeValidateInstruction({\n walletAccountIdx: ctx.walletAccountIdx,\n authIdx: params.authIdx,\n signatureR: signature.signatureR,\n signatureS: signature.signatureS,\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n });\n\n const instructionData = concatenateInstructions([\n validateInstruction,\n trailingInstructionData,\n ]);\n\n status(\"Sending transaction...\");\n const result = await params.executor({\n thru: params.thru,\n walletSigner: params.walletSigner,\n instructionData,\n readWriteAddresses: ctx.readWriteAddresses,\n readOnlyAddresses: ctx.readOnlyAddresses,\n label: params.credentialId\n ? \"VALIDATE + ADD_AUTHORITY + REGISTER_CREDENTIAL\"\n : \"VALIDATE + ADD_AUTHORITY\",\n });\n\n return { ...result, newAuthorityIdx };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAWA,6BAaO;AA6EP,eAAsB,mBACpB,QAC0B;AAC1B,QAAM,SAAS,OAAO,aAAa,MAAM;AAAA,EAAC;AAE1C,QAAM,gBAAgB,MAAM,OAAO,KAAK,SAAS,IAAI,OAAO,aAAa;AACzE,QAAM,aAAqC,eAAe,MAAM;AAChE,MAAI,CAAC,YAAY;AACf,UAAM,IAAI,MAAM,6BAA6B;AAAA,EAC/C;AAEA,QAAM,aAAS,+CAAuB,UAAU;AAChD,QAAM,cACJ,OAAO,YAAY,OAAO,OAAO;AACnC,MAAI,CAAC,aAAa;AAChB,UAAM,IAAI,MAAM,mCAAmC;AAAA,EACrD;AACA,MAAI,YAAY,SAAS,WAAW;AAClC,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAGA,QAAM,kBAAkB,OAAO,YAAY;AAG3C,QAAM,8BAA0B,sDAA8B;AAAA,IAC5D,WAAW,OAAO;AAAA,EACpB,CAAC;AAED,MAAI,0BAA0B;AAC9B,MAAI,oBAAkC,CAAC;AAEvC,MAAI,OAAO,cAAc;AACvB,UAAM,aAAa,UAAM,mDAA2B,OAAO,YAAY;AACvE,UAAM,qBAAqB,UAAM;AAAA,MAC/B;AAAA,MACA,OAAO;AAAA,IACT;AAEA,WAAO,+CAA+C;AACtD,UAAM,cAAc,MAAM,OAAO,KAAK,OAAO,SAAS;AAAA,MACpD,WAAW;AAAA,MACX,SAAS;AAAA,IACX,CAAC;AAED,UAAMA,WAAM,4CAAoB;AAAA,MAC9B,eAAe,OAAO;AAAA,MACtB,mBAAmB,CAAC,kBAAkB;AAAA,MACtC,kBAAkB,CAAC;AAAA,IACrB,CAAC;AAED,UAAM,oCAAgC,4DAAoC;AAAA,MACxE,kBAAkBA,KAAI;AAAA,MACtB,kBAAkBA,KAAI,gBAAgB,kBAAkB;AAAA,MACxD,MAAM;AAAA,MACN,YAAY,YAAY;AAAA,IAC1B,CAAC;AAED,kCAA0B,gDAAwB;AAAA,MAChD;AAAA,MACA;AAAA,IACF,CAAC;AACD,wBAAoB,CAAC,kBAAkB;AAAA,EACzC;AAIA,QAAM,UAAM,4CAAoB;AAAA,IAC9B,eAAe,OAAO;AAAA,IACtB;AAAA,IACA,kBAAkB,CAAC;AAAA,EACrB,CAAC;AAED,QAAM,YAAY,UAAM;AAAA,IACtB,OAAO;AAAA,IACP,IAAI;AAAA,IACJ;AAAA,EACF;AAEA,SAAO,iCAAiC;AACxC,QAAM,YAAY,MAAM,OAAO,QAAQ,cAAc,SAAS;AAE9D,QAAM,0BAAsB,kDAA0B;AAAA,IACpD,kBAAkB,IAAI;AAAA,IACtB,SAAS,OAAO;AAAA,IAChB,YAAY,UAAU;AAAA,IACtB,YAAY,UAAU;AAAA,IACtB,mBAAmB,UAAU;AAAA,IAC7B,gBAAgB,UAAU;AAAA,EAC5B,CAAC;AAED,QAAM,sBAAkB,gDAAwB;AAAA,IAC9C;AAAA,IACA;AAAA,EACF,CAAC;AAED,SAAO,wBAAwB;AAC/B,QAAM,SAAS,MAAM,OAAO,SAAS;AAAA,IACnC,MAAM,OAAO;AAAA,IACb,cAAc,OAAO;AAAA,IACrB;AAAA,IACA,oBAAoB,IAAI;AAAA,IACxB,mBAAmB,IAAI;AAAA,IACvB,OAAO,OAAO,eACV,mDACA;AAAA,EACN,CAAC;AAED,SAAO,EAAE,GAAG,QAAQ,gBAAgB;AACtC;","names":["ctx"]}
1
+ {"version":3,"sources":["../../src/auth/add-device.ts"],"sourcesContent":["/* Add-passkey-to-account transaction builder, lifted from\n `web/wallet-auth-manager/app/page.tsx` (`runValidateThen`,\n `handleSubmitAddPasskey`) so the wallet's `/embedded` post-connect\n step can reuse the exact same flow.\n\n Builds the on-chain transaction:\n VALIDATE(existingAuthority -> ADD_AUTHORITY(newPasskey))\n or VALIDATE(existingAuthority -> multicall[ADD_AUTHORITY, REGISTER_CREDENTIAL])\n asks the caller's existing passkey to sign the challenge, then asks\n the caller's wallet signer to sign the assembled transaction, sends\n it, and returns the result. */\n\nimport {\n type Authority,\n buildAccountContext,\n createValidateChallenge,\n createCredentialLookupSeed,\n decodeAddress,\n deriveWalletAddress,\n encodeAddAuthorityInstruction,\n encodeRegisterCredentialInstruction,\n encodeValidateInstruction,\n parseWalletAuthorities,\n type ParsedAuthority,\n type WalletSigner,\n} from \"@thru/programs/passkey-manager\";\nimport {\n MULTICALL_PROGRAM_PUBKEY,\n buildMulticallInstruction,\n} from \"@thru/programs/multicall\";\n\n/** Minimal shape required from a passkey signer. Both web's\n `signWithDiscoverablePasskey`/`signWithPasskey` and mobile's\n counterparts conform. */\nexport interface PasskeyChallengeSigner {\n signChallenge: (challenge: Uint8Array) => Promise<{\n signatureR: Uint8Array;\n signatureS: Uint8Array;\n authenticatorData: Uint8Array;\n clientDataJSON: Uint8Array;\n }>;\n}\n\n/** Minimal shape required from a Thru chain client. Loosely-typed\n because @thru/sdk's DTS emit is currently broken in this\n repo. The caller passes the real Thru and we narrow operationally. */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyThruClient = any;\n\nexport interface AddDeviceParams {\n /** Loosely-typed Thru chain client (`@thru/sdk/client`). */\n thru: AnyThruClient;\n /** Wallet (the on-chain WalletAccount) to attach the passkey to. */\n walletAddress: string;\n /** Index of the existing authority that approves this change. Must\n currently be a passkey authority. */\n authIdx: number;\n /** New passkey to attach. tag = 1 (passkey). */\n newAuthority: Authority;\n /** Optional credential-lookup registration so the new passkey is\n discoverable on subsequent sign-ins. */\n credentialId?: Uint8Array;\n walletName?: string;\n /** Existing-passkey challenge signer (web or mobile). */\n passkey: PasskeyChallengeSigner;\n /** Wallet transaction signer that returns base64(signed bytes). */\n walletSigner: WalletSigner;\n /** Passkey program address (base58). */\n programAddress: string;\n /** Sign-and-send executor (lifted from passkey-transaction.ts in the\n wallet-auth-manager - wallet apps own this because it depends on\n the `Thru` client's transaction builder). */\n executor: TxExecutor;\n /** Optional status callback so UIs can show progress. */\n onStatus?: (message: string) => void;\n}\n\nexport interface TxExecutorParams {\n thru: AnyThruClient;\n walletSigner: WalletSigner;\n instructionData: Uint8Array;\n readWriteAddresses: string[];\n readOnlyAddresses: string[];\n label: string;\n}\n\nexport interface TxExecutorResult {\n signature: string;\n /** Loosely-typed because @thru/sdk types aren't available. */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n execution: any;\n}\n\nexport type TxExecutor = (\n params: TxExecutorParams,\n) => Promise<TxExecutorResult>;\n\nexport interface AddDeviceResult extends TxExecutorResult {\n /** The new passkey's authority index after the transaction lands. */\n newAuthorityIdx: number;\n}\n\n/**\n * Run VALIDATE + ADD_AUTHORITY [+ REGISTER_CREDENTIAL] to attach a new\n * passkey to an on-chain WalletAccount.\n */\nexport async function addDeviceToAccount(\n params: AddDeviceParams,\n): Promise<AddDeviceResult> {\n const status = params.onStatus ?? (() => {});\n\n const walletAccount = await params.thru.accounts.get(params.walletAddress);\n const walletData: Uint8Array | undefined = walletAccount?.data?.data;\n if (!walletData) {\n throw new Error(\"Wallet account data missing\");\n }\n\n const parsed = parseWalletAuthorities(walletData);\n const authorizing: ParsedAuthority | undefined =\n parsed.authorities[params.authIdx];\n if (!authorizing) {\n throw new Error(\"Authorization index out of bounds\");\n }\n if (authorizing.kind !== \"passkey\") {\n throw new Error(\n \"addDeviceToAccount currently requires a passkey authority for VALIDATE\",\n );\n }\n\n /* The new authority will land at the next free slot. */\n const newAuthorityIdx = parsed.authorities.length;\n\n let readWriteAccounts: Uint8Array[] = [];\n let lookupSeed: Uint8Array | undefined;\n let lookupAddressBytes: Uint8Array | undefined;\n let lookupProof: Uint8Array | undefined;\n\n if (params.credentialId) {\n lookupSeed = await createCredentialLookupSeed(params.credentialId);\n lookupAddressBytes = await deriveWalletAddress(\n lookupSeed,\n params.programAddress,\n );\n\n status(\"Fetching state proof for credential lookup...\");\n const proofResult = await params.thru.proofs.generate({\n proofType: 1 /* StateProofType.CREATING */,\n address: lookupAddressBytes,\n });\n lookupProof = proofResult.proof;\n readWriteAccounts = [lookupAddressBytes];\n }\n\n const ctx = buildAccountContext({\n walletAddress: params.walletAddress,\n readWriteAccounts,\n readOnlyAccounts: params.credentialId ? [MULTICALL_PROGRAM_PUBKEY] : [],\n programAddress: params.programAddress,\n });\n\n const passkeyProgramPubkey = decodeAddress(params.programAddress);\n const addAuthorityInstruction = encodeAddAuthorityInstruction({\n walletAccountIdx: ctx.walletAccountIdx,\n authority: params.newAuthority,\n });\n\n let targetProgramIdx = ctx.getAccountIndex(passkeyProgramPubkey);\n let targetInstructionData = addAuthorityInstruction;\n\n if (params.credentialId) {\n if (!lookupSeed || !lookupAddressBytes || !lookupProof) {\n throw new Error(\"Credential lookup proof data missing\");\n }\n\n const registerCredentialInstruction = encodeRegisterCredentialInstruction({\n walletAccountIdx: ctx.walletAccountIdx,\n lookupAccountIdx: ctx.getAccountIndex(lookupAddressBytes),\n seed: lookupSeed,\n stateProof: lookupProof,\n });\n\n targetProgramIdx = ctx.getAccountIndex(MULTICALL_PROGRAM_PUBKEY);\n targetInstructionData = buildMulticallInstruction([\n {\n programIdx: ctx.getAccountIndex(passkeyProgramPubkey),\n instructionData: addAuthorityInstruction,\n },\n {\n programIdx: ctx.getAccountIndex(passkeyProgramPubkey),\n instructionData: registerCredentialInstruction,\n },\n ]);\n }\n\n /* Build the VALIDATE challenge over the target CPI and ask the caller's passkey to sign. */\n const challenge = await createValidateChallenge(\n parsed.nonce,\n ctx.accountAddresses,\n ctx.walletAccountIdx,\n params.authIdx,\n {\n programIdx: targetProgramIdx,\n instructionData: targetInstructionData,\n },\n );\n\n status(\"Waiting for passkey approval...\");\n const signature = await params.passkey.signChallenge(challenge);\n\n const validateInstruction = encodeValidateInstruction({\n walletAccountIdx: ctx.walletAccountIdx,\n authIdx: params.authIdx,\n targetInstruction: {\n programIdx: targetProgramIdx,\n instructionData: targetInstructionData,\n },\n signatureR: signature.signatureR,\n signatureS: signature.signatureS,\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n });\n\n status(\"Sending transaction...\");\n const result = await params.executor({\n thru: params.thru,\n walletSigner: params.walletSigner,\n instructionData: validateInstruction,\n readWriteAddresses: ctx.readWriteAddresses,\n readOnlyAddresses: ctx.readOnlyAddresses,\n label: params.credentialId\n ? \"VALIDATE -> MULTICALL(ADD_AUTHORITY, REGISTER_CREDENTIAL)\"\n : \"VALIDATE -> ADD_AUTHORITY\",\n });\n\n return { ...result, newAuthorityIdx };\n}\n"],"mappings":"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","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  addDeviceToAccount
3
- } from "../chunk-QAQNRQ7G.js";
3
+ } from "../chunk-KASTJBBY.js";
4
4
  export {
5
5
  addDeviceToAccount
6
6
  };
package/dist/auth.cjs CHANGED
@@ -304,6 +304,7 @@ async function executePasskeyTransaction(opts) {
304
304
 
305
305
  // src/auth/add-device.ts
306
306
  var import_passkey_manager3 = require("@thru/programs/passkey-manager");
307
+ var import_multicall = require("@thru/programs/multicall");
307
308
  async function addDeviceToAccount(params) {
308
309
  const status = params.onStatus ?? (() => {
309
310
  });
@@ -323,14 +324,13 @@ async function addDeviceToAccount(params) {
323
324
  );
324
325
  }
325
326
  const newAuthorityIdx = parsed.authorities.length;
326
- const addAuthorityInstruction = (0, import_passkey_manager3.encodeAddAuthorityInstruction)({
327
- authority: params.newAuthority
328
- });
329
- let trailingInstructionData = addAuthorityInstruction;
330
327
  let readWriteAccounts = [];
328
+ let lookupSeed;
329
+ let lookupAddressBytes;
330
+ let lookupProof;
331
331
  if (params.credentialId) {
332
- const lookupSeed = await (0, import_passkey_manager3.createCredentialLookupSeed)(params.credentialId);
333
- const lookupAddressBytes = await (0, import_passkey_manager3.deriveWalletAddress)(
332
+ lookupSeed = await (0, import_passkey_manager3.createCredentialLookupSeed)(params.credentialId);
333
+ lookupAddressBytes = await (0, import_passkey_manager3.deriveWalletAddress)(
334
334
  lookupSeed,
335
335
  params.programAddress
336
336
  );
@@ -339,55 +339,76 @@ async function addDeviceToAccount(params) {
339
339
  proofType: 1,
340
340
  address: lookupAddressBytes
341
341
  });
342
- const ctx2 = (0, import_passkey_manager3.buildAccountContext)({
343
- walletAddress: params.walletAddress,
344
- readWriteAccounts: [lookupAddressBytes],
345
- readOnlyAccounts: []
346
- });
347
- const registerCredentialInstruction = (0, import_passkey_manager3.encodeRegisterCredentialInstruction)({
348
- walletAccountIdx: ctx2.walletAccountIdx,
349
- lookupAccountIdx: ctx2.getAccountIndex(lookupAddressBytes),
350
- seed: lookupSeed,
351
- stateProof: proofResult.proof
352
- });
353
- trailingInstructionData = (0, import_passkey_manager3.concatenateInstructions)([
354
- addAuthorityInstruction,
355
- registerCredentialInstruction
356
- ]);
342
+ lookupProof = proofResult.proof;
357
343
  readWriteAccounts = [lookupAddressBytes];
358
344
  }
359
345
  const ctx = (0, import_passkey_manager3.buildAccountContext)({
360
346
  walletAddress: params.walletAddress,
361
347
  readWriteAccounts,
362
- readOnlyAccounts: []
348
+ readOnlyAccounts: params.credentialId ? [import_multicall.MULTICALL_PROGRAM_PUBKEY] : [],
349
+ programAddress: params.programAddress
350
+ });
351
+ const passkeyProgramPubkey = (0, import_passkey_manager3.decodeAddress)(params.programAddress);
352
+ const addAuthorityInstruction = (0, import_passkey_manager3.encodeAddAuthorityInstruction)({
353
+ walletAccountIdx: ctx.walletAccountIdx,
354
+ authority: params.newAuthority
363
355
  });
356
+ let targetProgramIdx = ctx.getAccountIndex(passkeyProgramPubkey);
357
+ let targetInstructionData = addAuthorityInstruction;
358
+ if (params.credentialId) {
359
+ if (!lookupSeed || !lookupAddressBytes || !lookupProof) {
360
+ throw new Error("Credential lookup proof data missing");
361
+ }
362
+ const registerCredentialInstruction = (0, import_passkey_manager3.encodeRegisterCredentialInstruction)({
363
+ walletAccountIdx: ctx.walletAccountIdx,
364
+ lookupAccountIdx: ctx.getAccountIndex(lookupAddressBytes),
365
+ seed: lookupSeed,
366
+ stateProof: lookupProof
367
+ });
368
+ targetProgramIdx = ctx.getAccountIndex(import_multicall.MULTICALL_PROGRAM_PUBKEY);
369
+ targetInstructionData = (0, import_multicall.buildMulticallInstruction)([
370
+ {
371
+ programIdx: ctx.getAccountIndex(passkeyProgramPubkey),
372
+ instructionData: addAuthorityInstruction
373
+ },
374
+ {
375
+ programIdx: ctx.getAccountIndex(passkeyProgramPubkey),
376
+ instructionData: registerCredentialInstruction
377
+ }
378
+ ]);
379
+ }
364
380
  const challenge = await (0, import_passkey_manager3.createValidateChallenge)(
365
381
  parsed.nonce,
366
382
  ctx.accountAddresses,
367
- trailingInstructionData
383
+ ctx.walletAccountIdx,
384
+ params.authIdx,
385
+ {
386
+ programIdx: targetProgramIdx,
387
+ instructionData: targetInstructionData
388
+ }
368
389
  );
369
390
  status("Waiting for passkey approval...");
370
391
  const signature = await params.passkey.signChallenge(challenge);
371
392
  const validateInstruction = (0, import_passkey_manager3.encodeValidateInstruction)({
372
393
  walletAccountIdx: ctx.walletAccountIdx,
373
394
  authIdx: params.authIdx,
395
+ targetInstruction: {
396
+ programIdx: targetProgramIdx,
397
+ instructionData: targetInstructionData
398
+ },
374
399
  signatureR: signature.signatureR,
375
400
  signatureS: signature.signatureS,
376
401
  authenticatorData: signature.authenticatorData,
377
402
  clientDataJSON: signature.clientDataJSON
378
403
  });
379
- const instructionData = (0, import_passkey_manager3.concatenateInstructions)([
380
- validateInstruction,
381
- trailingInstructionData
382
- ]);
383
404
  status("Sending transaction...");
384
405
  const result = await params.executor({
385
406
  thru: params.thru,
386
407
  walletSigner: params.walletSigner,
387
- instructionData,
408
+ instructionData: validateInstruction,
388
409
  readWriteAddresses: ctx.readWriteAddresses,
389
410
  readOnlyAddresses: ctx.readOnlyAddresses,
390
- label: params.credentialId ? "VALIDATE + ADD_AUTHORITY + REGISTER_CREDENTIAL" : "VALIDATE + ADD_AUTHORITY"
411
+ label: params.credentialId ? "VALIDATE -> MULTICALL(ADD_AUTHORITY, REGISTER_CREDENTIAL)" : "VALIDATE -> ADD_AUTHORITY"
391
412
  });
392
413
  return { ...result, newAuthorityIdx };
393
414
  }
package/dist/auth.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/auth/index.ts","../src/auth/execute-tx.ts","../src/mobile/passkey.ts","../src/mobile/storage.ts","../src/auth/add-device.ts","../src/auth/use-passkey-auth.ts","../src/mobile/errors.ts"],"sourcesContent":["export type {\n PasskeyApiUser,\n PasskeyAuthApiResponse,\n PasskeyUser,\n PasskeyAuthConfig,\n PasskeyAuthState,\n PasskeyAuthActions,\n PasskeyAuthStore,\n PasskeyAuthBoundStore,\n} from './types';\n\nexport { executePasskeyTransaction } from './execute-tx';\n\nexport { addDeviceToAccount } from './add-device';\nexport type {\n AddDeviceParams,\n AddDeviceResult,\n AnyThruClient,\n PasskeyChallengeSigner,\n TxExecutor,\n TxExecutorParams,\n TxExecutorResult,\n} from './add-device';\n\nexport {\n createPasskeyAuthStore,\n getPasskeyAuthStore,\n usePasskeyAuth,\n} from './use-passkey-auth';\n","import { base64UrlToBytes, bytesToBase64, bytesToHex } from '@thru/programs/passkey-manager';\nimport { signWithPasskey } from '../mobile/passkey';\nimport { touchPasskeyLastUsedAt } from '../mobile/storage';\n\nasync function readJson(response: Response): Promise<Record<string, unknown>> {\n try {\n return (await response.json()) as Record<string, unknown>;\n } catch {\n throw new Error(`Non-JSON response (HTTP ${response.status})`);\n }\n}\n\nexport async function executePasskeyTransaction<\n P extends Record<string, unknown>,\n R\n>(opts: {\n challengeUrl: string;\n submitUrl: string;\n params: P;\n credentialId: string;\n rpId: string;\n}): Promise<R> {\n let challengeRes: Response;\n try {\n challengeRes = await fetch(opts.challengeUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(opts.params),\n });\n } catch {\n throw new Error('Network request failed (challenge)');\n }\n\n const challengeData = await readJson(challengeRes);\n if (!challengeRes.ok || challengeData.success !== true) {\n throw new Error(\n typeof challengeData.error === 'string'\n ? challengeData.error\n : 'Failed to get challenge'\n );\n }\n\n if (typeof challengeData.challenge !== 'string') {\n throw new Error('Challenge response did not include a challenge');\n }\n\n const challengeBytes = base64UrlToBytes(challengeData.challenge);\n const signature = await signWithPasskey(\n opts.credentialId,\n challengeBytes,\n opts.rpId\n );\n await touchPasskeyLastUsedAt().catch((error) => {\n console.warn('Failed to update passkey last-used timestamp:', error);\n });\n\n const { success: _success, error: _error, ...challengeFields } = challengeData;\n\n let submitRes: Response;\n try {\n submitRes = await fetch(opts.submitUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n ...opts.params,\n ...challengeFields,\n signatureR: bytesToHex(signature.signatureR),\n signatureS: bytesToHex(signature.signatureS),\n authenticatorData: bytesToBase64(signature.authenticatorData),\n clientDataJSON: bytesToBase64(signature.clientDataJSON),\n }),\n });\n } catch {\n throw new Error('Network request failed (submit)');\n }\n\n const submitData = await readJson(submitRes);\n if (!submitRes.ok || submitData.success !== true) {\n throw new Error(\n typeof submitData.error === 'string'\n ? submitData.error\n : 'Failed to submit transaction'\n );\n }\n\n return submitData as R;\n}\n","import { create as passkeyCreate, get as passkeyGet } from 'react-native-passkeys';\nimport {\n bytesToBase64Url,\n base64UrlToBytes,\n normalizeLowS,\n parseDerSignature,\n type PasskeySigningResult,\n} from '@thru/programs/passkey-manager';\nimport type {\n DiscoverablePasskeyResult,\n PasskeyMobileConfig,\n PasskeyRegistrationResult,\n} from './types';\n\ntype ProcessLike = typeof globalThis & {\n process?: {\n env?: Record<string, string | undefined>;\n };\n};\n\nfunction getDefaultConfig(config?: PasskeyMobileConfig): Required<PasskeyMobileConfig> {\n const env = (globalThis as ProcessLike).process?.env ?? {};\n\n return {\n rpId: config?.rpId ?? env.EXPO_PUBLIC_PASSKEY_RP_ID ?? 'wallet.thru.org',\n rpName: config?.rpName ?? env.EXPO_PUBLIC_PASSKEY_RP_NAME ?? 'Thru Wallet',\n };\n}\n\nexport async function registerPasskey(\n alias: string,\n userId: string,\n config?: PasskeyMobileConfig\n): Promise<PasskeyRegistrationResult> {\n const { rpId, rpName } = getDefaultConfig(config);\n const challenge = bytesToBase64Url(crypto.getRandomValues(new Uint8Array(32)));\n const userIdB64 = bytesToBase64Url(new TextEncoder().encode(userId));\n\n const result = await passkeyCreate({\n challenge,\n rp: { id: rpId, name: rpName },\n user: { id: userIdB64, name: alias, displayName: alias },\n pubKeyCredParams: [{ type: 'public-key', alg: -7 }],\n authenticatorSelection: {\n authenticatorAttachment: 'platform',\n userVerification: 'required',\n residentKey: 'required',\n },\n attestation: 'none',\n timeout: 60000,\n });\n\n if (!result) {\n throw new Error('Passkey registration was cancelled');\n }\n\n const publicKeyB64 = result.response.getPublicKey?.();\n if (!publicKeyB64) {\n throw new Error('Failed to retrieve public key from registration');\n }\n\n const keyBytes = base64UrlToBytes(publicKeyB64);\n const { x, y } = extractP256Coordinates(keyBytes);\n\n return {\n credentialId: result.id,\n publicKeyX: x,\n publicKeyY: y,\n rpId,\n };\n}\n\nexport async function signWithPasskey(\n credentialId: string,\n challenge: Uint8Array,\n rpId?: string\n): Promise<PasskeySigningResult> {\n const resolvedRpId = rpId ?? getDefaultConfig().rpId;\n const challengeB64 = bytesToBase64Url(challenge);\n\n const result = await passkeyGet({\n challenge: challengeB64,\n rpId: resolvedRpId,\n allowCredentials: [{ type: 'public-key', id: credentialId }],\n userVerification: 'required',\n timeout: 60000,\n });\n\n if (!result) {\n throw new Error('Passkey authentication was cancelled');\n }\n\n const derSignature = base64UrlToBytes(result.response.signature);\n let { r, s } = parseDerSignature(derSignature);\n s = normalizeLowS(s);\n\n return {\n signature: new Uint8Array([...r, ...s]),\n authenticatorData: base64UrlToBytes(result.response.authenticatorData),\n clientDataJSON: base64UrlToBytes(result.response.clientDataJSON),\n signatureR: r,\n signatureS: s,\n };\n}\n\nexport async function authenticateWithDiscoverablePasskey(\n config?: Pick<PasskeyMobileConfig, 'rpId'>\n): Promise<DiscoverablePasskeyResult | null> {\n const { rpId } = getDefaultConfig(config);\n\n try {\n const challenge = bytesToBase64Url(crypto.getRandomValues(new Uint8Array(32)));\n const result = await passkeyGet({\n challenge,\n rpId,\n userVerification: 'required',\n timeout: 60000,\n });\n\n return result ? { credentialId: result.id, rpId } : null;\n } catch {\n return null;\n }\n}\n\nexport function extractP256Coordinates(\n keyBytes: Uint8Array\n): { x: Uint8Array; y: Uint8Array } {\n if (keyBytes.length === 64) {\n return {\n x: keyBytes.slice(0, 32),\n y: keyBytes.slice(32, 64),\n };\n }\n\n if (keyBytes.length === 65 && keyBytes[0] === 0x04) {\n return {\n x: keyBytes.slice(1, 33),\n y: keyBytes.slice(33, 65),\n };\n }\n\n const pointStart = keyBytes.length - 65;\n if (pointStart > 0 && keyBytes[pointStart] === 0x04) {\n return {\n x: keyBytes.slice(pointStart + 1, pointStart + 33),\n y: keyBytes.slice(pointStart + 33, pointStart + 65),\n };\n }\n\n throw new Error(\n `Unsupported public key format (${keyBytes.length} bytes). Expected raw X||Y (64), uncompressed point (65), or SPKI DER (91).`\n );\n}\n","import * as SecureStore from 'expo-secure-store';\nimport type { PasskeyMetadata } from '@thru/programs/passkey-manager';\n\nconst SECURE_STORE_OPTS = {\n keychainAccessible: SecureStore.WHEN_UNLOCKED_THIS_DEVICE_ONLY,\n} as const;\n\nconst PASSKEY_CREDENTIAL_ID_KEY = 'thru_passkey_credential_id';\nconst PASSKEY_PUBLIC_KEY_X_KEY = 'thru_passkey_pubkey_x';\nconst PASSKEY_PUBLIC_KEY_Y_KEY = 'thru_passkey_pubkey_y';\nconst PASSKEY_RP_ID_KEY = 'thru_passkey_rp_id';\nconst PASSKEY_LABEL_KEY = 'thru_passkey_label';\nconst PASSKEY_CREATED_AT_KEY = 'thru_passkey_created_at';\nconst PASSKEY_LAST_USED_AT_KEY = 'thru_passkey_last_used_at';\n\nconst ADDRESS_KEY = 'thru_address';\nconst USER_ID_KEY = 'thru_user_id';\nconst TOKEN_ACCOUNT_KEY = 'thru_token_account';\n\nexport async function storePasskeyMetadata(metadata: PasskeyMetadata): Promise<void> {\n await Promise.all([\n SecureStore.setItemAsync(PASSKEY_CREDENTIAL_ID_KEY, metadata.credentialId, SECURE_STORE_OPTS),\n SecureStore.setItemAsync(PASSKEY_PUBLIC_KEY_X_KEY, metadata.publicKeyX, SECURE_STORE_OPTS),\n SecureStore.setItemAsync(PASSKEY_PUBLIC_KEY_Y_KEY, metadata.publicKeyY, SECURE_STORE_OPTS),\n SecureStore.setItemAsync(PASSKEY_RP_ID_KEY, metadata.rpId, SECURE_STORE_OPTS),\n SecureStore.setItemAsync(PASSKEY_LABEL_KEY, metadata.label ?? '', SECURE_STORE_OPTS),\n SecureStore.setItemAsync(PASSKEY_CREATED_AT_KEY, metadata.createdAt, SECURE_STORE_OPTS),\n SecureStore.setItemAsync(PASSKEY_LAST_USED_AT_KEY, metadata.lastUsedAt, SECURE_STORE_OPTS),\n ]);\n}\n\nexport async function getStoredPasskeyMetadata(): Promise<PasskeyMetadata | null> {\n const credentialId = await SecureStore.getItemAsync(PASSKEY_CREDENTIAL_ID_KEY);\n if (!credentialId) return null;\n\n const [publicKeyX, publicKeyY, rpId, label, createdAt, lastUsedAt] = await Promise.all([\n SecureStore.getItemAsync(PASSKEY_PUBLIC_KEY_X_KEY),\n SecureStore.getItemAsync(PASSKEY_PUBLIC_KEY_Y_KEY),\n SecureStore.getItemAsync(PASSKEY_RP_ID_KEY),\n SecureStore.getItemAsync(PASSKEY_LABEL_KEY),\n SecureStore.getItemAsync(PASSKEY_CREATED_AT_KEY),\n SecureStore.getItemAsync(PASSKEY_LAST_USED_AT_KEY),\n ]);\n\n if (!rpId || !createdAt) return null;\n\n return {\n credentialId,\n publicKeyX: publicKeyX ?? '',\n publicKeyY: publicKeyY ?? '',\n rpId,\n label: label || undefined,\n createdAt,\n lastUsedAt: lastUsedAt ?? createdAt,\n };\n}\n\nexport async function touchPasskeyLastUsedAt(lastUsedAt = new Date().toISOString()): Promise<string> {\n await SecureStore.setItemAsync(PASSKEY_LAST_USED_AT_KEY, lastUsedAt, SECURE_STORE_OPTS);\n return lastUsedAt;\n}\n\nexport async function hasStoredPasskey(): Promise<boolean> {\n return (await SecureStore.getItemAsync(PASSKEY_CREDENTIAL_ID_KEY)) !== null;\n}\n\nexport async function clearPasskeyMetadata(): Promise<void> {\n await Promise.all([\n SecureStore.deleteItemAsync(PASSKEY_CREDENTIAL_ID_KEY),\n SecureStore.deleteItemAsync(PASSKEY_PUBLIC_KEY_X_KEY),\n SecureStore.deleteItemAsync(PASSKEY_PUBLIC_KEY_Y_KEY),\n SecureStore.deleteItemAsync(PASSKEY_RP_ID_KEY),\n SecureStore.deleteItemAsync(PASSKEY_LABEL_KEY),\n SecureStore.deleteItemAsync(PASSKEY_CREATED_AT_KEY),\n SecureStore.deleteItemAsync(PASSKEY_LAST_USED_AT_KEY),\n ]);\n}\n\nexport async function storeWalletInfo(\n address: string,\n userId: string,\n tokenAccountAddress?: string\n): Promise<void> {\n await Promise.all([\n SecureStore.setItemAsync(ADDRESS_KEY, address, SECURE_STORE_OPTS),\n SecureStore.setItemAsync(USER_ID_KEY, userId, SECURE_STORE_OPTS),\n tokenAccountAddress\n ? SecureStore.setItemAsync(TOKEN_ACCOUNT_KEY, tokenAccountAddress, SECURE_STORE_OPTS)\n : SecureStore.deleteItemAsync(TOKEN_ACCOUNT_KEY),\n ]);\n}\n\nexport async function hasStoredWallet(): Promise<boolean> {\n return (await SecureStore.getItemAsync(ADDRESS_KEY)) !== null;\n}\n\nexport async function getStoredAddress(): Promise<string | null> {\n return SecureStore.getItemAsync(ADDRESS_KEY);\n}\n\nexport async function getStoredUserId(): Promise<string | null> {\n return SecureStore.getItemAsync(USER_ID_KEY);\n}\n\nexport async function getStoredTokenAccount(): Promise<string | null> {\n return SecureStore.getItemAsync(TOKEN_ACCOUNT_KEY);\n}\n\nexport async function clearSession(): Promise<void> {\n await Promise.all([\n SecureStore.deleteItemAsync(ADDRESS_KEY),\n SecureStore.deleteItemAsync(USER_ID_KEY),\n SecureStore.deleteItemAsync(TOKEN_ACCOUNT_KEY),\n ]);\n}\n","/* Add-passkey-to-account transaction builder, lifted from\n `web/wallet-auth-manager/app/page.tsx` (`runValidateThen`,\n `handleSubmitAddPasskey`) so the wallet's `/embedded` post-connect\n step can reuse the exact same flow.\n\n Builds the on-chain transaction:\n VALIDATE(existingAuthority) + ADD_AUTHORITY(newPasskey) [+ REGISTER_CREDENTIAL]\n asks the caller's existing passkey to sign the challenge, then asks\n the caller's wallet signer to sign the assembled transaction, sends\n it, and returns the result. */\n\nimport {\n type Authority,\n buildAccountContext,\n concatenateInstructions,\n createValidateChallenge,\n createCredentialLookupSeed,\n deriveWalletAddress,\n encodeAddAuthorityInstruction,\n encodeRegisterCredentialInstruction,\n encodeValidateInstruction,\n parseWalletAuthorities,\n type ParsedAuthority,\n type WalletSigner,\n} from \"@thru/programs/passkey-manager\";\n\n/** Minimal shape required from a passkey signer. Both web's\n `signWithDiscoverablePasskey`/`signWithPasskey` and mobile's\n counterparts conform. */\nexport interface PasskeyChallengeSigner {\n signChallenge: (challenge: Uint8Array) => Promise<{\n signatureR: Uint8Array;\n signatureS: Uint8Array;\n authenticatorData: Uint8Array;\n clientDataJSON: Uint8Array;\n }>;\n}\n\n/** Minimal shape required from a Thru chain client. Loosely-typed\n because @thru/sdk's DTS emit is currently broken in this\n repo. The caller passes the real Thru and we narrow operationally. */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyThruClient = any;\n\nexport interface AddDeviceParams {\n /** Loosely-typed Thru chain client (`@thru/sdk/client`). */\n thru: AnyThruClient;\n /** Wallet (the on-chain WalletAccount) to attach the passkey to. */\n walletAddress: string;\n /** Index of the existing authority that approves this change. Must\n currently be a passkey authority. */\n authIdx: number;\n /** New passkey to attach. tag = 1 (passkey). */\n newAuthority: Authority;\n /** Optional credential-lookup registration so the new passkey is\n discoverable on subsequent sign-ins. */\n credentialId?: Uint8Array;\n walletName?: string;\n /** Existing-passkey challenge signer (web or mobile). */\n passkey: PasskeyChallengeSigner;\n /** Wallet transaction signer that returns base64(signed bytes). */\n walletSigner: WalletSigner;\n /** Passkey program address (base58). */\n programAddress: string;\n /** Sign-and-send executor (lifted from passkey-transaction.ts in the\n wallet-auth-manager - wallet apps own this because it depends on\n the `Thru` client's transaction builder). */\n executor: TxExecutor;\n /** Optional status callback so UIs can show progress. */\n onStatus?: (message: string) => void;\n}\n\nexport interface TxExecutorParams {\n thru: AnyThruClient;\n walletSigner: WalletSigner;\n instructionData: Uint8Array;\n readWriteAddresses: string[];\n readOnlyAddresses: string[];\n label: string;\n}\n\nexport interface TxExecutorResult {\n signature: string;\n /** Loosely-typed because @thru/sdk types aren't available. */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n execution: any;\n}\n\nexport type TxExecutor = (\n params: TxExecutorParams,\n) => Promise<TxExecutorResult>;\n\nexport interface AddDeviceResult extends TxExecutorResult {\n /** The new passkey's authority index after the transaction lands. */\n newAuthorityIdx: number;\n}\n\n/**\n * Run VALIDATE + ADD_AUTHORITY [+ REGISTER_CREDENTIAL] to attach a new\n * passkey to an on-chain WalletAccount.\n */\nexport async function addDeviceToAccount(\n params: AddDeviceParams,\n): Promise<AddDeviceResult> {\n const status = params.onStatus ?? (() => {});\n\n const walletAccount = await params.thru.accounts.get(params.walletAddress);\n const walletData: Uint8Array | undefined = walletAccount?.data?.data;\n if (!walletData) {\n throw new Error(\"Wallet account data missing\");\n }\n\n const parsed = parseWalletAuthorities(walletData);\n const authorizing: ParsedAuthority | undefined =\n parsed.authorities[params.authIdx];\n if (!authorizing) {\n throw new Error(\"Authorization index out of bounds\");\n }\n if (authorizing.kind !== \"passkey\") {\n throw new Error(\n \"addDeviceToAccount currently requires a passkey authority for VALIDATE\",\n );\n }\n\n /* The new authority will land at the next free slot. */\n const newAuthorityIdx = parsed.authorities.length;\n\n /* Build the instruction sequence after the VALIDATE. */\n const addAuthorityInstruction = encodeAddAuthorityInstruction({\n authority: params.newAuthority,\n });\n\n let trailingInstructionData = addAuthorityInstruction;\n let readWriteAccounts: Uint8Array[] = [];\n\n if (params.credentialId) {\n const lookupSeed = await createCredentialLookupSeed(params.credentialId);\n const lookupAddressBytes = await deriveWalletAddress(\n lookupSeed,\n params.programAddress,\n );\n\n status(\"Fetching state proof for credential lookup...\");\n const proofResult = await params.thru.proofs.generate({\n proofType: 1 /* StateProofType.CREATING */,\n address: lookupAddressBytes,\n });\n\n const ctx = buildAccountContext({\n walletAddress: params.walletAddress,\n readWriteAccounts: [lookupAddressBytes],\n readOnlyAccounts: [],\n });\n\n const registerCredentialInstruction = encodeRegisterCredentialInstruction({\n walletAccountIdx: ctx.walletAccountIdx,\n lookupAccountIdx: ctx.getAccountIndex(lookupAddressBytes),\n seed: lookupSeed,\n stateProof: proofResult.proof,\n });\n\n trailingInstructionData = concatenateInstructions([\n addAuthorityInstruction,\n registerCredentialInstruction,\n ]);\n readWriteAccounts = [lookupAddressBytes];\n }\n\n /* Build the VALIDATE challenge over (nonce, account_addresses,\n trailing_instruction_data) and ask the caller's passkey to sign. */\n const ctx = buildAccountContext({\n walletAddress: params.walletAddress,\n readWriteAccounts,\n readOnlyAccounts: [],\n });\n\n const challenge = await createValidateChallenge(\n parsed.nonce,\n ctx.accountAddresses,\n trailingInstructionData,\n );\n\n status(\"Waiting for passkey approval...\");\n const signature = await params.passkey.signChallenge(challenge);\n\n const validateInstruction = encodeValidateInstruction({\n walletAccountIdx: ctx.walletAccountIdx,\n authIdx: params.authIdx,\n signatureR: signature.signatureR,\n signatureS: signature.signatureS,\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n });\n\n const instructionData = concatenateInstructions([\n validateInstruction,\n trailingInstructionData,\n ]);\n\n status(\"Sending transaction...\");\n const result = await params.executor({\n thru: params.thru,\n walletSigner: params.walletSigner,\n instructionData,\n readWriteAddresses: ctx.readWriteAddresses,\n readOnlyAddresses: ctx.readOnlyAddresses,\n label: params.credentialId\n ? \"VALIDATE + ADD_AUTHORITY + REGISTER_CREDENTIAL\"\n : \"VALIDATE + ADD_AUTHORITY\",\n });\n\n return { ...result, newAuthorityIdx };\n}\n","import { bytesToHex } from '@thru/programs/passkey-manager';\nimport { create } from 'zustand';\nimport { classifyPasskeyError } from '../mobile/errors';\nimport {\n authenticateWithDiscoverablePasskey,\n registerPasskey,\n signWithPasskey,\n} from '../mobile/passkey';\nimport {\n clearPasskeyMetadata,\n clearSession,\n getStoredAddress,\n getStoredPasskeyMetadata,\n getStoredUserId,\n hasStoredPasskey,\n hasStoredWallet,\n storePasskeyMetadata,\n storeWalletInfo,\n touchPasskeyLastUsedAt,\n} from '../mobile/storage';\nimport type {\n PasskeyAuthApiResponse,\n PasskeyAuthBoundStore,\n PasskeyAuthConfig,\n PasskeyAuthStore,\n PasskeyUser,\n} from './types';\n\nconst storeCache = new Map<string, PasskeyAuthBoundStore<any>>();\n\nfunction createStoreKey(config: PasskeyAuthConfig): string {\n return [config.apiUrl, config.alias ?? '', config.rpId ?? '', config.rpName ?? ''].join('::');\n}\n\nfunction buildDisplayName(address: string): string {\n return `${address.slice(0, 8)}...${address.slice(-4)}`;\n}\n\nfunction toPasskeyUser<TExtra>(\n user: PasskeyAuthApiResponse<TExtra>['user']\n): PasskeyUser<TExtra> {\n return {\n id: user.id,\n displayName: buildDisplayName(user.publicKey),\n tokenAccountAddress: user.tokenAccountAddress ?? null,\n extras: user.extras,\n };\n}\n\nasync function readJson<T>(response: Response): Promise<T> {\n return (await response.json()) as T;\n}\n\nasync function postJson<T>(\n url: string,\n body: Record<string, unknown>\n): Promise<T> {\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n\n const data = await readJson<Record<string, unknown>>(response);\n if (!response.ok || data.success !== true) {\n throw new Error(\n typeof data.error === 'string' ? data.error : 'Request failed'\n );\n }\n\n return data as unknown as T;\n}\n\nasync function getCurrentUser<TExtra>(\n apiUrl: string,\n address: string\n): Promise<PasskeyAuthApiResponse<TExtra> | null> {\n const response = await fetch(`${apiUrl}/auth/me`, {\n headers: {\n 'Content-Type': 'application/json',\n 'x-wallet-address': address,\n },\n });\n\n if (response.status === 404) return null;\n\n const data = await readJson<Record<string, unknown>>(response);\n if (!response.ok || data.success !== true) {\n throw new Error(\n typeof data.error === 'string' ? data.error : 'Failed to fetch current user'\n );\n }\n\n return data as unknown as PasskeyAuthApiResponse<TExtra>;\n}\n\nexport function createPasskeyAuthStore<TExtra = Record<string, never>>(\n config: PasskeyAuthConfig\n): PasskeyAuthBoundStore<TExtra> {\n const resolvedAlias = config.alias ?? 'Thru Wallet';\n\n return create<PasskeyAuthStore<TExtra>>((set, get) => ({\n isAuthenticated: false,\n isLoading: false,\n isInitialized: false,\n hasExistingPasskey: false,\n needsNewPasskey: false,\n error: null,\n user: null,\n address: null,\n activeCredentialId: null,\n\n initialize: async () => {\n try {\n const hasPasskey = await hasStoredPasskey();\n\n if (hasPasskey) {\n const storedAddress = await getStoredAddress();\n if (storedAddress) {\n const user = await Promise.race([\n getCurrentUser<TExtra>(config.apiUrl, storedAddress),\n new Promise<null>((_, reject) =>\n setTimeout(() => reject(new Error('timeout')), 2000)\n ),\n ]).catch(() => undefined);\n\n if (user === null) {\n await clearSession();\n await clearPasskeyMetadata();\n set({ isInitialized: true, hasExistingPasskey: false });\n return;\n }\n } else {\n const metadata = await getStoredPasskeyMetadata();\n if (metadata && !metadata.publicKeyX && !metadata.publicKeyY) {\n await clearPasskeyMetadata();\n set({ isInitialized: true, hasExistingPasskey: false });\n return;\n }\n }\n }\n\n set({ isInitialized: true, hasExistingPasskey: hasPasskey });\n } catch (error) {\n console.error('Failed to initialize passkey auth:', error);\n set({ isInitialized: true, error: 'Failed to initialize wallet' });\n }\n },\n\n createWallet: async () => {\n set({ isLoading: true, error: null, needsNewPasskey: false });\n\n try {\n const tempId = `user-${Date.now()}`;\n const passkeyLabel = resolvedAlias.trim() || 'Thru Wallet';\n const { credentialId, publicKeyX, publicKeyY, rpId } =\n await registerPasskey(passkeyLabel, tempId, {\n rpId: config.rpId,\n rpName: config.rpName,\n });\n\n const now = new Date().toISOString();\n const pubkeyXHex = bytesToHex(publicKeyX);\n const pubkeyYHex = bytesToHex(publicKeyY);\n\n await storePasskeyMetadata({\n credentialId,\n publicKeyX: pubkeyXHex,\n publicKeyY: pubkeyYHex,\n rpId,\n label: passkeyLabel,\n createdAt: now,\n lastUsedAt: now,\n });\n\n const response = await postJson<PasskeyAuthApiResponse<TExtra>>(\n `${config.apiUrl}/auth/register-passkey-wallet`,\n {\n pubkeyX: pubkeyXHex,\n pubkeyY: pubkeyYHex,\n credentialId,\n }\n );\n\n const walletAddress = response.user.publicKey;\n await storeWalletInfo(\n walletAddress,\n response.user.id,\n response.user.tokenAccountAddress ?? undefined\n );\n\n set({\n isLoading: false,\n isAuthenticated: true,\n hasExistingPasskey: true,\n activeCredentialId: credentialId,\n address: walletAddress,\n user: toPasskeyUser(response.user),\n });\n\n return true;\n } catch (error) {\n if (classifyPasskeyError(error) === 'USER_CANCELLED') {\n set({ isLoading: false });\n return false;\n }\n\n console.error('Failed to create passkey wallet:', error);\n set({\n isLoading: false,\n error: error instanceof Error ? error.message : 'Failed to create wallet',\n });\n return false;\n }\n },\n\n unlockWithPasskey: async () => {\n set({ isLoading: true, error: null, needsNewPasskey: false });\n\n try {\n const metadata = await getStoredPasskeyMetadata();\n if (!metadata) throw new Error('No stored passkey found');\n\n await signWithPasskey(\n metadata.credentialId,\n crypto.getRandomValues(new Uint8Array(32)),\n metadata.rpId\n );\n await touchPasskeyLastUsedAt().catch((error) => {\n console.warn('Failed to update passkey last-used timestamp:', error);\n });\n\n const hasWallet = await hasStoredWallet();\n let walletAddress: string;\n let userId: string;\n let tokenAccountAddress: string | undefined;\n let response: PasskeyAuthApiResponse<TExtra> | null = null;\n\n if (hasWallet) {\n const storedAddress = await getStoredAddress();\n const storedUserId = await getStoredUserId();\n if (!storedAddress || !storedUserId) {\n throw new Error('Incomplete wallet data');\n }\n\n walletAddress = storedAddress;\n userId = storedUserId;\n\n const current = await getCurrentUser<TExtra>(config.apiUrl, walletAddress);\n if (current) {\n response = current;\n tokenAccountAddress = current.user.tokenAccountAddress ?? undefined;\n } else if (metadata.publicKeyX && metadata.publicKeyY) {\n response = await postJson<PasskeyAuthApiResponse<TExtra>>(\n `${config.apiUrl}/auth/register-passkey-wallet`,\n {\n pubkeyX: metadata.publicKeyX,\n pubkeyY: metadata.publicKeyY,\n credentialId: metadata.credentialId,\n }\n );\n walletAddress = response.user.publicKey;\n userId = response.user.id;\n tokenAccountAddress = response.user.tokenAccountAddress ?? undefined;\n await storeWalletInfo(walletAddress, userId, tokenAccountAddress);\n } else {\n await clearSession();\n await clearPasskeyMetadata();\n set({ isLoading: false, hasExistingPasskey: false, error: null });\n return false;\n }\n } else if (metadata.publicKeyX && metadata.publicKeyY) {\n response = await postJson<PasskeyAuthApiResponse<TExtra>>(\n `${config.apiUrl}/auth/register-passkey-wallet`,\n {\n pubkeyX: metadata.publicKeyX,\n pubkeyY: metadata.publicKeyY,\n credentialId: metadata.credentialId,\n }\n );\n walletAddress = response.user.publicKey;\n userId = response.user.id;\n tokenAccountAddress = response.user.tokenAccountAddress ?? undefined;\n await storeWalletInfo(walletAddress, userId, tokenAccountAddress);\n } else {\n const recovered = await postJson<PasskeyAuthApiResponse<TExtra>>(\n `${config.apiUrl}/auth/recover-passkey-wallet`,\n { credentialId: metadata.credentialId }\n ).catch(() => null);\n\n if (!recovered) {\n await clearSession();\n await clearPasskeyMetadata();\n set({ isLoading: false, hasExistingPasskey: false, error: null });\n return false;\n }\n\n response = recovered;\n walletAddress = recovered.user.publicKey;\n userId = recovered.user.id;\n tokenAccountAddress = recovered.user.tokenAccountAddress ?? undefined;\n await storeWalletInfo(walletAddress, userId, tokenAccountAddress);\n }\n\n set({\n isLoading: false,\n isAuthenticated: true,\n activeCredentialId: metadata.credentialId,\n address: walletAddress,\n user: response ? toPasskeyUser(response.user) : get().user,\n });\n\n return true;\n } catch (error) {\n console.error('Failed to unlock with passkey:', error);\n const kind = classifyPasskeyError(error);\n\n if (kind === 'USER_CANCELLED') {\n set({ isLoading: false });\n } else if (kind === 'NOT_FOUND') {\n await clearPasskeyMetadata();\n set({ isLoading: false, hasExistingPasskey: false, error: null });\n } else {\n set({\n isLoading: false,\n error: error instanceof Error ? error.message : 'Failed to unlock',\n });\n }\n\n return false;\n }\n },\n\n recoverWithDiscoverablePasskey: async () => {\n set({ isLoading: true, error: null, needsNewPasskey: false });\n\n try {\n const discovered = await authenticateWithDiscoverablePasskey({\n rpId: config.rpId,\n });\n\n if (!discovered) {\n set({ isLoading: false });\n return false;\n }\n\n const response = await postJson<PasskeyAuthApiResponse<TExtra>>(\n `${config.apiUrl}/auth/recover-passkey-wallet`,\n { credentialId: discovered.credentialId }\n ).catch(() => null);\n\n if (!response) {\n set({ isLoading: false, needsNewPasskey: true });\n return false;\n }\n\n const walletAddress = response.user.publicKey;\n const userId = response.user.id;\n const tokenAccountAddress = response.user.tokenAccountAddress ?? undefined;\n const now = new Date().toISOString();\n\n await storePasskeyMetadata({\n credentialId: discovered.credentialId,\n publicKeyX: '',\n publicKeyY: '',\n rpId: discovered.rpId,\n createdAt: now,\n lastUsedAt: now,\n });\n await storeWalletInfo(walletAddress, userId, tokenAccountAddress);\n\n set({\n isLoading: false,\n isAuthenticated: true,\n hasExistingPasskey: true,\n activeCredentialId: discovered.credentialId,\n address: walletAddress,\n user: toPasskeyUser(response.user),\n });\n\n return true;\n } catch (error) {\n console.error('Failed to recover with discoverable passkey:', error);\n set({\n isLoading: false,\n error:\n error instanceof Error ? error.message : 'Failed to recover wallet',\n });\n return false;\n }\n },\n\n logout: async () => {\n try {\n await clearSession();\n } catch (error) {\n console.error('Failed to clear passkey session:', error);\n }\n\n set({\n isAuthenticated: false,\n needsNewPasskey: false,\n user: null,\n address: null,\n activeCredentialId: null,\n });\n },\n\n clearError: () => set({ error: null }),\n dismissNewPasskey: () => set({ needsNewPasskey: false }),\n }));\n}\n\nexport function getPasskeyAuthStore<TExtra = Record<string, never>>(\n config: PasskeyAuthConfig\n): PasskeyAuthBoundStore<TExtra> {\n const key = createStoreKey(config);\n const cached = storeCache.get(key) as PasskeyAuthBoundStore<TExtra> | undefined;\n if (cached) return cached;\n\n const store = createPasskeyAuthStore<TExtra>(config);\n storeCache.set(key, store);\n return store;\n}\n\nexport function usePasskeyAuth<TExtra = Record<string, never>>(\n config: PasskeyAuthConfig\n): PasskeyAuthStore<TExtra> {\n return getPasskeyAuthStore<TExtra>(config)();\n}\n","const PASSKEY_ERRORS = {\n USER_CANCELLED: [\n 'error 1001',\n 'UserCancelled',\n 'Passkey authentication was cancelled',\n 'Passkey registration was cancelled',\n ],\n NOT_FOUND: [\n 'not found',\n 'No credentials available',\n 'no passkey',\n 'NoCredentials',\n ],\n} as const;\n\nexport type PasskeyErrorKind = keyof typeof PASSKEY_ERRORS;\n\nexport function classifyPasskeyError(error: unknown): PasskeyErrorKind | null {\n const message =\n error instanceof Error ? error.message : typeof error === 'string' ? error : null;\n\n if (!message) return null;\n\n for (const [kind, patterns] of Object.entries(PASSKEY_ERRORS)) {\n if (patterns.some((pattern) => message.includes(pattern))) {\n return kind as PasskeyErrorKind;\n }\n }\n\n return null;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,IAAAA,0BAA4D;;;ACA5D,mCAA2D;AAC3D,6BAMO;AAaP,SAAS,iBAAiB,QAA6D;AACrF,QAAM,MAAO,WAA2B,SAAS,OAAO,CAAC;AAEzD,SAAO;AAAA,IACL,MAAM,QAAQ,QAAQ,IAAI,6BAA6B;AAAA,IACvD,QAAQ,QAAQ,UAAU,IAAI,+BAA+B;AAAA,EAC/D;AACF;AAEA,eAAsB,gBACpB,OACA,QACA,QACoC;AACpC,QAAM,EAAE,MAAM,OAAO,IAAI,iBAAiB,MAAM;AAChD,QAAM,gBAAY,yCAAiB,OAAO,gBAAgB,IAAI,WAAW,EAAE,CAAC,CAAC;AAC7E,QAAM,gBAAY,yCAAiB,IAAI,YAAY,EAAE,OAAO,MAAM,CAAC;AAEnE,QAAM,SAAS,UAAM,6BAAAC,QAAc;AAAA,IACjC;AAAA,IACA,IAAI,EAAE,IAAI,MAAM,MAAM,OAAO;AAAA,IAC7B,MAAM,EAAE,IAAI,WAAW,MAAM,OAAO,aAAa,MAAM;AAAA,IACvD,kBAAkB,CAAC,EAAE,MAAM,cAAc,KAAK,GAAG,CAAC;AAAA,IAClD,wBAAwB;AAAA,MACtB,yBAAyB;AAAA,MACzB,kBAAkB;AAAA,MAClB,aAAa;AAAA,IACf;AAAA,IACA,aAAa;AAAA,IACb,SAAS;AAAA,EACX,CAAC;AAED,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,oCAAoC;AAAA,EACtD;AAEA,QAAM,eAAe,OAAO,SAAS,eAAe;AACpD,MAAI,CAAC,cAAc;AACjB,UAAM,IAAI,MAAM,iDAAiD;AAAA,EACnE;AAEA,QAAM,eAAW,yCAAiB,YAAY;AAC9C,QAAM,EAAE,GAAG,EAAE,IAAI,uBAAuB,QAAQ;AAEhD,SAAO;AAAA,IACL,cAAc,OAAO;AAAA,IACrB,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ;AAAA,EACF;AACF;AAEA,eAAsB,gBACpB,cACA,WACA,MAC+B;AAC/B,QAAM,eAAe,QAAQ,iBAAiB,EAAE;AAChD,QAAM,mBAAe,yCAAiB,SAAS;AAE/C,QAAM,SAAS,UAAM,6BAAAC,KAAW;AAAA,IAC9B,WAAW;AAAA,IACX,MAAM;AAAA,IACN,kBAAkB,CAAC,EAAE,MAAM,cAAc,IAAI,aAAa,CAAC;AAAA,IAC3D,kBAAkB;AAAA,IAClB,SAAS;AAAA,EACX,CAAC;AAED,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,sCAAsC;AAAA,EACxD;AAEA,QAAM,mBAAe,yCAAiB,OAAO,SAAS,SAAS;AAC/D,MAAI,EAAE,GAAG,EAAE,QAAI,0CAAkB,YAAY;AAC7C,UAAI,sCAAc,CAAC;AAEnB,SAAO;AAAA,IACL,WAAW,IAAI,WAAW,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,IACtC,uBAAmB,yCAAiB,OAAO,SAAS,iBAAiB;AAAA,IACrE,oBAAgB,yCAAiB,OAAO,SAAS,cAAc;AAAA,IAC/D,YAAY;AAAA,IACZ,YAAY;AAAA,EACd;AACF;AAEA,eAAsB,oCACpB,QAC2C;AAC3C,QAAM,EAAE,KAAK,IAAI,iBAAiB,MAAM;AAExC,MAAI;AACF,UAAM,gBAAY,yCAAiB,OAAO,gBAAgB,IAAI,WAAW,EAAE,CAAC,CAAC;AAC7E,UAAM,SAAS,UAAM,6BAAAA,KAAW;AAAA,MAC9B;AAAA,MACA;AAAA,MACA,kBAAkB;AAAA,MAClB,SAAS;AAAA,IACX,CAAC;AAED,WAAO,SAAS,EAAE,cAAc,OAAO,IAAI,KAAK,IAAI;AAAA,EACtD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,uBACd,UACkC;AAClC,MAAI,SAAS,WAAW,IAAI;AAC1B,WAAO;AAAA,MACL,GAAG,SAAS,MAAM,GAAG,EAAE;AAAA,MACvB,GAAG,SAAS,MAAM,IAAI,EAAE;AAAA,IAC1B;AAAA,EACF;AAEA,MAAI,SAAS,WAAW,MAAM,SAAS,CAAC,MAAM,GAAM;AAClD,WAAO;AAAA,MACL,GAAG,SAAS,MAAM,GAAG,EAAE;AAAA,MACvB,GAAG,SAAS,MAAM,IAAI,EAAE;AAAA,IAC1B;AAAA,EACF;AAEA,QAAM,aAAa,SAAS,SAAS;AACrC,MAAI,aAAa,KAAK,SAAS,UAAU,MAAM,GAAM;AACnD,WAAO;AAAA,MACL,GAAG,SAAS,MAAM,aAAa,GAAG,aAAa,EAAE;AAAA,MACjD,GAAG,SAAS,MAAM,aAAa,IAAI,aAAa,EAAE;AAAA,IACpD;AAAA,EACF;AAEA,QAAM,IAAI;AAAA,IACR,kCAAkC,SAAS,MAAM;AAAA,EACnD;AACF;;;ACzJA,kBAA6B;AAG7B,IAAM,oBAAoB;AAAA,EACxB,oBAAgC;AAClC;AAEA,IAAM,4BAA4B;AAClC,IAAM,2BAA2B;AACjC,IAAM,2BAA2B;AACjC,IAAM,oBAAoB;AAC1B,IAAM,oBAAoB;AAC1B,IAAM,yBAAyB;AAC/B,IAAM,2BAA2B;AAEjC,IAAM,cAAc;AACpB,IAAM,cAAc;AACpB,IAAM,oBAAoB;AAE1B,eAAsB,qBAAqB,UAA0C;AACnF,QAAM,QAAQ,IAAI;AAAA,IACJ,yBAAa,2BAA2B,SAAS,cAAc,iBAAiB;AAAA,IAChF,yBAAa,0BAA0B,SAAS,YAAY,iBAAiB;AAAA,IAC7E,yBAAa,0BAA0B,SAAS,YAAY,iBAAiB;AAAA,IAC7E,yBAAa,mBAAmB,SAAS,MAAM,iBAAiB;AAAA,IAChE,yBAAa,mBAAmB,SAAS,SAAS,IAAI,iBAAiB;AAAA,IACvE,yBAAa,wBAAwB,SAAS,WAAW,iBAAiB;AAAA,IAC1E,yBAAa,0BAA0B,SAAS,YAAY,iBAAiB;AAAA,EAC3F,CAAC;AACH;AAEA,eAAsB,2BAA4D;AAChF,QAAM,eAAe,MAAkB,yBAAa,yBAAyB;AAC7E,MAAI,CAAC,aAAc,QAAO;AAE1B,QAAM,CAAC,YAAY,YAAY,MAAM,OAAO,WAAW,UAAU,IAAI,MAAM,QAAQ,IAAI;AAAA,IACzE,yBAAa,wBAAwB;AAAA,IACrC,yBAAa,wBAAwB;AAAA,IACrC,yBAAa,iBAAiB;AAAA,IAC9B,yBAAa,iBAAiB;AAAA,IAC9B,yBAAa,sBAAsB;AAAA,IACnC,yBAAa,wBAAwB;AAAA,EACnD,CAAC;AAED,MAAI,CAAC,QAAQ,CAAC,UAAW,QAAO;AAEhC,SAAO;AAAA,IACL;AAAA,IACA,YAAY,cAAc;AAAA,IAC1B,YAAY,cAAc;AAAA,IAC1B;AAAA,IACA,OAAO,SAAS;AAAA,IAChB;AAAA,IACA,YAAY,cAAc;AAAA,EAC5B;AACF;AAEA,eAAsB,uBAAuB,cAAa,oBAAI,KAAK,GAAE,YAAY,GAAoB;AACnG,QAAkB,yBAAa,0BAA0B,YAAY,iBAAiB;AACtF,SAAO;AACT;AAEA,eAAsB,mBAAqC;AACzD,SAAQ,MAAkB,yBAAa,yBAAyB,MAAO;AACzE;AAEA,eAAsB,uBAAsC;AAC1D,QAAM,QAAQ,IAAI;AAAA,IACJ,4BAAgB,yBAAyB;AAAA,IACzC,4BAAgB,wBAAwB;AAAA,IACxC,4BAAgB,wBAAwB;AAAA,IACxC,4BAAgB,iBAAiB;AAAA,IACjC,4BAAgB,iBAAiB;AAAA,IACjC,4BAAgB,sBAAsB;AAAA,IACtC,4BAAgB,wBAAwB;AAAA,EACtD,CAAC;AACH;AAEA,eAAsB,gBACpB,SACA,QACA,qBACe;AACf,QAAM,QAAQ,IAAI;AAAA,IACJ,yBAAa,aAAa,SAAS,iBAAiB;AAAA,IACpD,yBAAa,aAAa,QAAQ,iBAAiB;AAAA,IAC/D,sBACgB,yBAAa,mBAAmB,qBAAqB,iBAAiB,IACtE,4BAAgB,iBAAiB;AAAA,EACnD,CAAC;AACH;AAEA,eAAsB,kBAAoC;AACxD,SAAQ,MAAkB,yBAAa,WAAW,MAAO;AAC3D;AAEA,eAAsB,mBAA2C;AAC/D,SAAmB,yBAAa,WAAW;AAC7C;AAEA,eAAsB,kBAA0C;AAC9D,SAAmB,yBAAa,WAAW;AAC7C;AAMA,eAAsB,eAA8B;AAClD,QAAM,QAAQ,IAAI;AAAA,IACJ,4BAAgB,WAAW;AAAA,IAC3B,4BAAgB,WAAW;AAAA,IAC3B,4BAAgB,iBAAiB;AAAA,EAC/C,CAAC;AACH;;;AF9GA,eAAe,SAAS,UAAsD;AAC5E,MAAI;AACF,WAAQ,MAAM,SAAS,KAAK;AAAA,EAC9B,QAAQ;AACN,UAAM,IAAI,MAAM,2BAA2B,SAAS,MAAM,GAAG;AAAA,EAC/D;AACF;AAEA,eAAsB,0BAGpB,MAMa;AACb,MAAI;AACJ,MAAI;AACF,mBAAe,MAAM,MAAM,KAAK,cAAc;AAAA,MAC5C,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU,KAAK,MAAM;AAAA,IAClC,CAAC;AAAA,EACH,QAAQ;AACN,UAAM,IAAI,MAAM,oCAAoC;AAAA,EACtD;AAEA,QAAM,gBAAgB,MAAM,SAAS,YAAY;AACjD,MAAI,CAAC,aAAa,MAAM,cAAc,YAAY,MAAM;AACtD,UAAM,IAAI;AAAA,MACR,OAAO,cAAc,UAAU,WAC3B,cAAc,QACd;AAAA,IACN;AAAA,EACF;AAEA,MAAI,OAAO,cAAc,cAAc,UAAU;AAC/C,UAAM,IAAI,MAAM,gDAAgD;AAAA,EAClE;AAEA,QAAM,qBAAiB,0CAAiB,cAAc,SAAS;AAC/D,QAAM,YAAY,MAAM;AAAA,IACtB,KAAK;AAAA,IACL;AAAA,IACA,KAAK;AAAA,EACP;AACA,QAAM,uBAAuB,EAAE,MAAM,CAAC,UAAU;AAC9C,YAAQ,KAAK,iDAAiD,KAAK;AAAA,EACrE,CAAC;AAED,QAAM,EAAE,SAAS,UAAU,OAAO,QAAQ,GAAG,gBAAgB,IAAI;AAEjE,MAAI;AACJ,MAAI;AACF,gBAAY,MAAM,MAAM,KAAK,WAAW;AAAA,MACtC,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU;AAAA,QACnB,GAAG,KAAK;AAAA,QACR,GAAG;AAAA,QACH,gBAAY,oCAAW,UAAU,UAAU;AAAA,QAC3C,gBAAY,oCAAW,UAAU,UAAU;AAAA,QAC3C,uBAAmB,uCAAc,UAAU,iBAAiB;AAAA,QAC5D,oBAAgB,uCAAc,UAAU,cAAc;AAAA,MACxD,CAAC;AAAA,IACH,CAAC;AAAA,EACH,QAAQ;AACN,UAAM,IAAI,MAAM,iCAAiC;AAAA,EACnD;AAEA,QAAM,aAAa,MAAM,SAAS,SAAS;AAC3C,MAAI,CAAC,UAAU,MAAM,WAAW,YAAY,MAAM;AAChD,UAAM,IAAI;AAAA,MACR,OAAO,WAAW,UAAU,WACxB,WAAW,QACX;AAAA,IACN;AAAA,EACF;AAEA,SAAO;AACT;;;AG3EA,IAAAC,0BAaO;AA6EP,eAAsB,mBACpB,QAC0B;AAC1B,QAAM,SAAS,OAAO,aAAa,MAAM;AAAA,EAAC;AAE1C,QAAM,gBAAgB,MAAM,OAAO,KAAK,SAAS,IAAI,OAAO,aAAa;AACzE,QAAM,aAAqC,eAAe,MAAM;AAChE,MAAI,CAAC,YAAY;AACf,UAAM,IAAI,MAAM,6BAA6B;AAAA,EAC/C;AAEA,QAAM,aAAS,gDAAuB,UAAU;AAChD,QAAM,cACJ,OAAO,YAAY,OAAO,OAAO;AACnC,MAAI,CAAC,aAAa;AAChB,UAAM,IAAI,MAAM,mCAAmC;AAAA,EACrD;AACA,MAAI,YAAY,SAAS,WAAW;AAClC,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAGA,QAAM,kBAAkB,OAAO,YAAY;AAG3C,QAAM,8BAA0B,uDAA8B;AAAA,IAC5D,WAAW,OAAO;AAAA,EACpB,CAAC;AAED,MAAI,0BAA0B;AAC9B,MAAI,oBAAkC,CAAC;AAEvC,MAAI,OAAO,cAAc;AACvB,UAAM,aAAa,UAAM,oDAA2B,OAAO,YAAY;AACvE,UAAM,qBAAqB,UAAM;AAAA,MAC/B;AAAA,MACA,OAAO;AAAA,IACT;AAEA,WAAO,+CAA+C;AACtD,UAAM,cAAc,MAAM,OAAO,KAAK,OAAO,SAAS;AAAA,MACpD,WAAW;AAAA,MACX,SAAS;AAAA,IACX,CAAC;AAED,UAAMC,WAAM,6CAAoB;AAAA,MAC9B,eAAe,OAAO;AAAA,MACtB,mBAAmB,CAAC,kBAAkB;AAAA,MACtC,kBAAkB,CAAC;AAAA,IACrB,CAAC;AAED,UAAM,oCAAgC,6DAAoC;AAAA,MACxE,kBAAkBA,KAAI;AAAA,MACtB,kBAAkBA,KAAI,gBAAgB,kBAAkB;AAAA,MACxD,MAAM;AAAA,MACN,YAAY,YAAY;AAAA,IAC1B,CAAC;AAED,kCAA0B,iDAAwB;AAAA,MAChD;AAAA,MACA;AAAA,IACF,CAAC;AACD,wBAAoB,CAAC,kBAAkB;AAAA,EACzC;AAIA,QAAM,UAAM,6CAAoB;AAAA,IAC9B,eAAe,OAAO;AAAA,IACtB;AAAA,IACA,kBAAkB,CAAC;AAAA,EACrB,CAAC;AAED,QAAM,YAAY,UAAM;AAAA,IACtB,OAAO;AAAA,IACP,IAAI;AAAA,IACJ;AAAA,EACF;AAEA,SAAO,iCAAiC;AACxC,QAAM,YAAY,MAAM,OAAO,QAAQ,cAAc,SAAS;AAE9D,QAAM,0BAAsB,mDAA0B;AAAA,IACpD,kBAAkB,IAAI;AAAA,IACtB,SAAS,OAAO;AAAA,IAChB,YAAY,UAAU;AAAA,IACtB,YAAY,UAAU;AAAA,IACtB,mBAAmB,UAAU;AAAA,IAC7B,gBAAgB,UAAU;AAAA,EAC5B,CAAC;AAED,QAAM,sBAAkB,iDAAwB;AAAA,IAC9C;AAAA,IACA;AAAA,EACF,CAAC;AAED,SAAO,wBAAwB;AAC/B,QAAM,SAAS,MAAM,OAAO,SAAS;AAAA,IACnC,MAAM,OAAO;AAAA,IACb,cAAc,OAAO;AAAA,IACrB;AAAA,IACA,oBAAoB,IAAI;AAAA,IACxB,mBAAmB,IAAI;AAAA,IACvB,OAAO,OAAO,eACV,mDACA;AAAA,EACN,CAAC;AAED,SAAO,EAAE,GAAG,QAAQ,gBAAgB;AACtC;;;ACpNA,IAAAC,0BAA2B;AAC3B,qBAAuB;;;ACDvB,IAAM,iBAAiB;AAAA,EACrB,gBAAgB;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,WAAW;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAIO,SAAS,qBAAqB,OAAyC;AAC5E,QAAM,UACJ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,UAAU,WAAW,QAAQ;AAE/E,MAAI,CAAC,QAAS,QAAO;AAErB,aAAW,CAAC,MAAM,QAAQ,KAAK,OAAO,QAAQ,cAAc,GAAG;AAC7D,QAAI,SAAS,KAAK,CAAC,YAAY,QAAQ,SAAS,OAAO,CAAC,GAAG;AACzD,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;;;ADFA,IAAM,aAAa,oBAAI,IAAwC;AAE/D,SAAS,eAAe,QAAmC;AACzD,SAAO,CAAC,OAAO,QAAQ,OAAO,SAAS,IAAI,OAAO,QAAQ,IAAI,OAAO,UAAU,EAAE,EAAE,KAAK,IAAI;AAC9F;AAEA,SAAS,iBAAiB,SAAyB;AACjD,SAAO,GAAG,QAAQ,MAAM,GAAG,CAAC,CAAC,MAAM,QAAQ,MAAM,EAAE,CAAC;AACtD;AAEA,SAAS,cACP,MACqB;AACrB,SAAO;AAAA,IACL,IAAI,KAAK;AAAA,IACT,aAAa,iBAAiB,KAAK,SAAS;AAAA,IAC5C,qBAAqB,KAAK,uBAAuB;AAAA,IACjD,QAAQ,KAAK;AAAA,EACf;AACF;AAEA,eAAeC,UAAY,UAAgC;AACzD,SAAQ,MAAM,SAAS,KAAK;AAC9B;AAEA,eAAe,SACb,KACA,MACY;AACZ,QAAM,WAAW,MAAM,MAAM,KAAK;AAAA,IAChC,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,IAC9C,MAAM,KAAK,UAAU,IAAI;AAAA,EAC3B,CAAC;AAED,QAAM,OAAO,MAAMA,UAAkC,QAAQ;AAC7D,MAAI,CAAC,SAAS,MAAM,KAAK,YAAY,MAAM;AACzC,UAAM,IAAI;AAAA,MACR,OAAO,KAAK,UAAU,WAAW,KAAK,QAAQ;AAAA,IAChD;AAAA,EACF;AAEA,SAAO;AACT;AAEA,eAAe,eACb,QACA,SACgD;AAChD,QAAM,WAAW,MAAM,MAAM,GAAG,MAAM,YAAY;AAAA,IAChD,SAAS;AAAA,MACP,gBAAgB;AAAA,MAChB,oBAAoB;AAAA,IACtB;AAAA,EACF,CAAC;AAED,MAAI,SAAS,WAAW,IAAK,QAAO;AAEpC,QAAM,OAAO,MAAMA,UAAkC,QAAQ;AAC7D,MAAI,CAAC,SAAS,MAAM,KAAK,YAAY,MAAM;AACzC,UAAM,IAAI;AAAA,MACR,OAAO,KAAK,UAAU,WAAW,KAAK,QAAQ;AAAA,IAChD;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,uBACd,QAC+B;AAC/B,QAAM,gBAAgB,OAAO,SAAS;AAEtC,aAAO,uBAAiC,CAAC,KAAK,SAAS;AAAA,IACrD,iBAAiB;AAAA,IACjB,WAAW;AAAA,IACX,eAAe;AAAA,IACf,oBAAoB;AAAA,IACpB,iBAAiB;AAAA,IACjB,OAAO;AAAA,IACP,MAAM;AAAA,IACN,SAAS;AAAA,IACT,oBAAoB;AAAA,IAEpB,YAAY,YAAY;AACtB,UAAI;AACF,cAAM,aAAa,MAAM,iBAAiB;AAE1C,YAAI,YAAY;AACd,gBAAM,gBAAgB,MAAM,iBAAiB;AAC7C,cAAI,eAAe;AACjB,kBAAM,OAAO,MAAM,QAAQ,KAAK;AAAA,cAC9B,eAAuB,OAAO,QAAQ,aAAa;AAAA,cACnD,IAAI;AAAA,gBAAc,CAAC,GAAG,WACpB,WAAW,MAAM,OAAO,IAAI,MAAM,SAAS,CAAC,GAAG,GAAI;AAAA,cACrD;AAAA,YACF,CAAC,EAAE,MAAM,MAAM,MAAS;AAExB,gBAAI,SAAS,MAAM;AACjB,oBAAM,aAAa;AACnB,oBAAM,qBAAqB;AAC3B,kBAAI,EAAE,eAAe,MAAM,oBAAoB,MAAM,CAAC;AACtD;AAAA,YACF;AAAA,UACF,OAAO;AACL,kBAAM,WAAW,MAAM,yBAAyB;AAChD,gBAAI,YAAY,CAAC,SAAS,cAAc,CAAC,SAAS,YAAY;AAC5D,oBAAM,qBAAqB;AAC3B,kBAAI,EAAE,eAAe,MAAM,oBAAoB,MAAM,CAAC;AACtD;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAEA,YAAI,EAAE,eAAe,MAAM,oBAAoB,WAAW,CAAC;AAAA,MAC7D,SAAS,OAAO;AACd,gBAAQ,MAAM,sCAAsC,KAAK;AACzD,YAAI,EAAE,eAAe,MAAM,OAAO,8BAA8B,CAAC;AAAA,MACnE;AAAA,IACF;AAAA,IAEA,cAAc,YAAY;AACxB,UAAI,EAAE,WAAW,MAAM,OAAO,MAAM,iBAAiB,MAAM,CAAC;AAE5D,UAAI;AACF,cAAM,SAAS,QAAQ,KAAK,IAAI,CAAC;AACjC,cAAM,eAAe,cAAc,KAAK,KAAK;AAC7C,cAAM,EAAE,cAAc,YAAY,YAAY,KAAK,IACjD,MAAM,gBAAgB,cAAc,QAAQ;AAAA,UAC1C,MAAM,OAAO;AAAA,UACb,QAAQ,OAAO;AAAA,QACjB,CAAC;AAEH,cAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AACnC,cAAM,iBAAa,oCAAW,UAAU;AACxC,cAAM,iBAAa,oCAAW,UAAU;AAExC,cAAM,qBAAqB;AAAA,UACzB;AAAA,UACA,YAAY;AAAA,UACZ,YAAY;AAAA,UACZ;AAAA,UACA,OAAO;AAAA,UACP,WAAW;AAAA,UACX,YAAY;AAAA,QACd,CAAC;AAED,cAAM,WAAW,MAAM;AAAA,UACrB,GAAG,OAAO,MAAM;AAAA,UAChB;AAAA,YACE,SAAS;AAAA,YACT,SAAS;AAAA,YACT;AAAA,UACF;AAAA,QACF;AAEA,cAAM,gBAAgB,SAAS,KAAK;AACpC,cAAM;AAAA,UACJ;AAAA,UACA,SAAS,KAAK;AAAA,UACd,SAAS,KAAK,uBAAuB;AAAA,QACvC;AAEA,YAAI;AAAA,UACF,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,oBAAoB;AAAA,UACpB,oBAAoB;AAAA,UACpB,SAAS;AAAA,UACT,MAAM,cAAc,SAAS,IAAI;AAAA,QACnC,CAAC;AAED,eAAO;AAAA,MACT,SAAS,OAAO;AACd,YAAI,qBAAqB,KAAK,MAAM,kBAAkB;AACpD,cAAI,EAAE,WAAW,MAAM,CAAC;AACxB,iBAAO;AAAA,QACT;AAEA,gBAAQ,MAAM,oCAAoC,KAAK;AACvD,YAAI;AAAA,UACF,WAAW;AAAA,UACX,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,QAClD,CAAC;AACD,eAAO;AAAA,MACT;AAAA,IACF;AAAA,IAEA,mBAAmB,YAAY;AAC7B,UAAI,EAAE,WAAW,MAAM,OAAO,MAAM,iBAAiB,MAAM,CAAC;AAE5D,UAAI;AACF,cAAM,WAAW,MAAM,yBAAyB;AAChD,YAAI,CAAC,SAAU,OAAM,IAAI,MAAM,yBAAyB;AAExD,cAAM;AAAA,UACJ,SAAS;AAAA,UACT,OAAO,gBAAgB,IAAI,WAAW,EAAE,CAAC;AAAA,UACzC,SAAS;AAAA,QACX;AACA,cAAM,uBAAuB,EAAE,MAAM,CAAC,UAAU;AAC9C,kBAAQ,KAAK,iDAAiD,KAAK;AAAA,QACrE,CAAC;AAED,cAAM,YAAY,MAAM,gBAAgB;AACxC,YAAI;AACJ,YAAI;AACJ,YAAI;AACJ,YAAI,WAAkD;AAEtD,YAAI,WAAW;AACb,gBAAM,gBAAgB,MAAM,iBAAiB;AAC7C,gBAAM,eAAe,MAAM,gBAAgB;AAC3C,cAAI,CAAC,iBAAiB,CAAC,cAAc;AACnC,kBAAM,IAAI,MAAM,wBAAwB;AAAA,UAC1C;AAEA,0BAAgB;AAChB,mBAAS;AAET,gBAAM,UAAU,MAAM,eAAuB,OAAO,QAAQ,aAAa;AACzE,cAAI,SAAS;AACX,uBAAW;AACX,kCAAsB,QAAQ,KAAK,uBAAuB;AAAA,UAC5D,WAAW,SAAS,cAAc,SAAS,YAAY;AACrD,uBAAW,MAAM;AAAA,cACf,GAAG,OAAO,MAAM;AAAA,cAChB;AAAA,gBACE,SAAS,SAAS;AAAA,gBAClB,SAAS,SAAS;AAAA,gBAClB,cAAc,SAAS;AAAA,cACzB;AAAA,YACF;AACA,4BAAgB,SAAS,KAAK;AAC9B,qBAAS,SAAS,KAAK;AACvB,kCAAsB,SAAS,KAAK,uBAAuB;AAC3D,kBAAM,gBAAgB,eAAe,QAAQ,mBAAmB;AAAA,UAClE,OAAO;AACL,kBAAM,aAAa;AACnB,kBAAM,qBAAqB;AAC3B,gBAAI,EAAE,WAAW,OAAO,oBAAoB,OAAO,OAAO,KAAK,CAAC;AAChE,mBAAO;AAAA,UACT;AAAA,QACF,WAAW,SAAS,cAAc,SAAS,YAAY;AACrD,qBAAW,MAAM;AAAA,YACf,GAAG,OAAO,MAAM;AAAA,YAChB;AAAA,cACE,SAAS,SAAS;AAAA,cAClB,SAAS,SAAS;AAAA,cAClB,cAAc,SAAS;AAAA,YACzB;AAAA,UACF;AACA,0BAAgB,SAAS,KAAK;AAC9B,mBAAS,SAAS,KAAK;AACvB,gCAAsB,SAAS,KAAK,uBAAuB;AAC3D,gBAAM,gBAAgB,eAAe,QAAQ,mBAAmB;AAAA,QAClE,OAAO;AACL,gBAAM,YAAY,MAAM;AAAA,YACtB,GAAG,OAAO,MAAM;AAAA,YAChB,EAAE,cAAc,SAAS,aAAa;AAAA,UACxC,EAAE,MAAM,MAAM,IAAI;AAElB,cAAI,CAAC,WAAW;AACd,kBAAM,aAAa;AACnB,kBAAM,qBAAqB;AAC3B,gBAAI,EAAE,WAAW,OAAO,oBAAoB,OAAO,OAAO,KAAK,CAAC;AAChE,mBAAO;AAAA,UACT;AAEA,qBAAW;AACX,0BAAgB,UAAU,KAAK;AAC/B,mBAAS,UAAU,KAAK;AACxB,gCAAsB,UAAU,KAAK,uBAAuB;AAC5D,gBAAM,gBAAgB,eAAe,QAAQ,mBAAmB;AAAA,QAClE;AAEA,YAAI;AAAA,UACF,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,oBAAoB,SAAS;AAAA,UAC7B,SAAS;AAAA,UACT,MAAM,WAAW,cAAc,SAAS,IAAI,IAAI,IAAI,EAAE;AAAA,QACxD,CAAC;AAED,eAAO;AAAA,MACT,SAAS,OAAO;AACd,gBAAQ,MAAM,kCAAkC,KAAK;AACrD,cAAM,OAAO,qBAAqB,KAAK;AAEvC,YAAI,SAAS,kBAAkB;AAC7B,cAAI,EAAE,WAAW,MAAM,CAAC;AAAA,QAC1B,WAAW,SAAS,aAAa;AAC/B,gBAAM,qBAAqB;AAC3B,cAAI,EAAE,WAAW,OAAO,oBAAoB,OAAO,OAAO,KAAK,CAAC;AAAA,QAClE,OAAO;AACL,cAAI;AAAA,YACF,WAAW;AAAA,YACX,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,UAClD,CAAC;AAAA,QACH;AAEA,eAAO;AAAA,MACT;AAAA,IACF;AAAA,IAEA,gCAAgC,YAAY;AAC1C,UAAI,EAAE,WAAW,MAAM,OAAO,MAAM,iBAAiB,MAAM,CAAC;AAE5D,UAAI;AACF,cAAM,aAAa,MAAM,oCAAoC;AAAA,UAC3D,MAAM,OAAO;AAAA,QACf,CAAC;AAED,YAAI,CAAC,YAAY;AACf,cAAI,EAAE,WAAW,MAAM,CAAC;AACxB,iBAAO;AAAA,QACT;AAEA,cAAM,WAAW,MAAM;AAAA,UACrB,GAAG,OAAO,MAAM;AAAA,UAChB,EAAE,cAAc,WAAW,aAAa;AAAA,QAC1C,EAAE,MAAM,MAAM,IAAI;AAElB,YAAI,CAAC,UAAU;AACb,cAAI,EAAE,WAAW,OAAO,iBAAiB,KAAK,CAAC;AAC/C,iBAAO;AAAA,QACT;AAEA,cAAM,gBAAgB,SAAS,KAAK;AACpC,cAAM,SAAS,SAAS,KAAK;AAC7B,cAAM,sBAAsB,SAAS,KAAK,uBAAuB;AACjE,cAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AAEnC,cAAM,qBAAqB;AAAA,UACzB,cAAc,WAAW;AAAA,UACzB,YAAY;AAAA,UACZ,YAAY;AAAA,UACZ,MAAM,WAAW;AAAA,UACjB,WAAW;AAAA,UACX,YAAY;AAAA,QACd,CAAC;AACD,cAAM,gBAAgB,eAAe,QAAQ,mBAAmB;AAEhE,YAAI;AAAA,UACF,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,oBAAoB;AAAA,UACpB,oBAAoB,WAAW;AAAA,UAC/B,SAAS;AAAA,UACT,MAAM,cAAc,SAAS,IAAI;AAAA,QACnC,CAAC;AAED,eAAO;AAAA,MACT,SAAS,OAAO;AACd,gBAAQ,MAAM,gDAAgD,KAAK;AACnE,YAAI;AAAA,UACF,WAAW;AAAA,UACX,OACE,iBAAiB,QAAQ,MAAM,UAAU;AAAA,QAC7C,CAAC;AACD,eAAO;AAAA,MACT;AAAA,IACF;AAAA,IAEA,QAAQ,YAAY;AAClB,UAAI;AACF,cAAM,aAAa;AAAA,MACrB,SAAS,OAAO;AACd,gBAAQ,MAAM,oCAAoC,KAAK;AAAA,MACzD;AAEA,UAAI;AAAA,QACF,iBAAiB;AAAA,QACjB,iBAAiB;AAAA,QACjB,MAAM;AAAA,QACN,SAAS;AAAA,QACT,oBAAoB;AAAA,MACtB,CAAC;AAAA,IACH;AAAA,IAEA,YAAY,MAAM,IAAI,EAAE,OAAO,KAAK,CAAC;AAAA,IACrC,mBAAmB,MAAM,IAAI,EAAE,iBAAiB,MAAM,CAAC;AAAA,EACzD,EAAE;AACJ;AAEO,SAAS,oBACd,QAC+B;AAC/B,QAAM,MAAM,eAAe,MAAM;AACjC,QAAM,SAAS,WAAW,IAAI,GAAG;AACjC,MAAI,OAAQ,QAAO;AAEnB,QAAM,QAAQ,uBAA+B,MAAM;AACnD,aAAW,IAAI,KAAK,KAAK;AACzB,SAAO;AACT;AAEO,SAAS,eACd,QAC0B;AAC1B,SAAO,oBAA4B,MAAM,EAAE;AAC7C;","names":["import_passkey_manager","passkeyCreate","passkeyGet","import_passkey_manager","ctx","import_passkey_manager","readJson"]}
1
+ {"version":3,"sources":["../src/auth/index.ts","../src/auth/execute-tx.ts","../src/mobile/passkey.ts","../src/mobile/storage.ts","../src/auth/add-device.ts","../src/auth/use-passkey-auth.ts","../src/mobile/errors.ts"],"sourcesContent":["export type {\n PasskeyApiUser,\n PasskeyAuthApiResponse,\n PasskeyUser,\n PasskeyAuthConfig,\n PasskeyAuthState,\n PasskeyAuthActions,\n PasskeyAuthStore,\n PasskeyAuthBoundStore,\n} from './types';\n\nexport { executePasskeyTransaction } from './execute-tx';\n\nexport { addDeviceToAccount } from './add-device';\nexport type {\n AddDeviceParams,\n AddDeviceResult,\n AnyThruClient,\n PasskeyChallengeSigner,\n TxExecutor,\n TxExecutorParams,\n TxExecutorResult,\n} from './add-device';\n\nexport {\n createPasskeyAuthStore,\n getPasskeyAuthStore,\n usePasskeyAuth,\n} from './use-passkey-auth';\n","import { base64UrlToBytes, bytesToBase64, bytesToHex } from '@thru/programs/passkey-manager';\nimport { signWithPasskey } from '../mobile/passkey';\nimport { touchPasskeyLastUsedAt } from '../mobile/storage';\n\nasync function readJson(response: Response): Promise<Record<string, unknown>> {\n try {\n return (await response.json()) as Record<string, unknown>;\n } catch {\n throw new Error(`Non-JSON response (HTTP ${response.status})`);\n }\n}\n\nexport async function executePasskeyTransaction<\n P extends Record<string, unknown>,\n R\n>(opts: {\n challengeUrl: string;\n submitUrl: string;\n params: P;\n credentialId: string;\n rpId: string;\n}): Promise<R> {\n let challengeRes: Response;\n try {\n challengeRes = await fetch(opts.challengeUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(opts.params),\n });\n } catch {\n throw new Error('Network request failed (challenge)');\n }\n\n const challengeData = await readJson(challengeRes);\n if (!challengeRes.ok || challengeData.success !== true) {\n throw new Error(\n typeof challengeData.error === 'string'\n ? challengeData.error\n : 'Failed to get challenge'\n );\n }\n\n if (typeof challengeData.challenge !== 'string') {\n throw new Error('Challenge response did not include a challenge');\n }\n\n const challengeBytes = base64UrlToBytes(challengeData.challenge);\n const signature = await signWithPasskey(\n opts.credentialId,\n challengeBytes,\n opts.rpId\n );\n await touchPasskeyLastUsedAt().catch((error) => {\n console.warn('Failed to update passkey last-used timestamp:', error);\n });\n\n const { success: _success, error: _error, ...challengeFields } = challengeData;\n\n let submitRes: Response;\n try {\n submitRes = await fetch(opts.submitUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n ...opts.params,\n ...challengeFields,\n signatureR: bytesToHex(signature.signatureR),\n signatureS: bytesToHex(signature.signatureS),\n authenticatorData: bytesToBase64(signature.authenticatorData),\n clientDataJSON: bytesToBase64(signature.clientDataJSON),\n }),\n });\n } catch {\n throw new Error('Network request failed (submit)');\n }\n\n const submitData = await readJson(submitRes);\n if (!submitRes.ok || submitData.success !== true) {\n throw new Error(\n typeof submitData.error === 'string'\n ? submitData.error\n : 'Failed to submit transaction'\n );\n }\n\n return submitData as R;\n}\n","import { create as passkeyCreate, get as passkeyGet } from 'react-native-passkeys';\nimport {\n bytesToBase64Url,\n base64UrlToBytes,\n normalizeLowS,\n parseDerSignature,\n type PasskeySigningResult,\n} from '@thru/programs/passkey-manager';\nimport type {\n DiscoverablePasskeyResult,\n PasskeyMobileConfig,\n PasskeyRegistrationResult,\n} from './types';\n\ntype ProcessLike = typeof globalThis & {\n process?: {\n env?: Record<string, string | undefined>;\n };\n};\n\nfunction getDefaultConfig(config?: PasskeyMobileConfig): Required<PasskeyMobileConfig> {\n const env = (globalThis as ProcessLike).process?.env ?? {};\n\n return {\n rpId: config?.rpId ?? env.EXPO_PUBLIC_PASSKEY_RP_ID ?? 'wallet.thru.org',\n rpName: config?.rpName ?? env.EXPO_PUBLIC_PASSKEY_RP_NAME ?? 'Thru Wallet',\n };\n}\n\nexport async function registerPasskey(\n alias: string,\n userId: string,\n config?: PasskeyMobileConfig\n): Promise<PasskeyRegistrationResult> {\n const { rpId, rpName } = getDefaultConfig(config);\n const challenge = bytesToBase64Url(crypto.getRandomValues(new Uint8Array(32)));\n const userIdB64 = bytesToBase64Url(new TextEncoder().encode(userId));\n\n const result = await passkeyCreate({\n challenge,\n rp: { id: rpId, name: rpName },\n user: { id: userIdB64, name: alias, displayName: alias },\n pubKeyCredParams: [{ type: 'public-key', alg: -7 }],\n authenticatorSelection: {\n authenticatorAttachment: 'platform',\n userVerification: 'required',\n residentKey: 'required',\n },\n attestation: 'none',\n timeout: 60000,\n });\n\n if (!result) {\n throw new Error('Passkey registration was cancelled');\n }\n\n const publicKeyB64 = result.response.getPublicKey?.();\n if (!publicKeyB64) {\n throw new Error('Failed to retrieve public key from registration');\n }\n\n const keyBytes = base64UrlToBytes(publicKeyB64);\n const { x, y } = extractP256Coordinates(keyBytes);\n\n return {\n credentialId: result.id,\n publicKeyX: x,\n publicKeyY: y,\n rpId,\n };\n}\n\nexport async function signWithPasskey(\n credentialId: string,\n challenge: Uint8Array,\n rpId?: string\n): Promise<PasskeySigningResult> {\n const resolvedRpId = rpId ?? getDefaultConfig().rpId;\n const challengeB64 = bytesToBase64Url(challenge);\n\n const result = await passkeyGet({\n challenge: challengeB64,\n rpId: resolvedRpId,\n allowCredentials: [{ type: 'public-key', id: credentialId }],\n userVerification: 'required',\n timeout: 60000,\n });\n\n if (!result) {\n throw new Error('Passkey authentication was cancelled');\n }\n\n const derSignature = base64UrlToBytes(result.response.signature);\n let { r, s } = parseDerSignature(derSignature);\n s = normalizeLowS(s);\n\n return {\n signature: new Uint8Array([...r, ...s]),\n authenticatorData: base64UrlToBytes(result.response.authenticatorData),\n clientDataJSON: base64UrlToBytes(result.response.clientDataJSON),\n signatureR: r,\n signatureS: s,\n };\n}\n\nexport async function authenticateWithDiscoverablePasskey(\n config?: Pick<PasskeyMobileConfig, 'rpId'>\n): Promise<DiscoverablePasskeyResult | null> {\n const { rpId } = getDefaultConfig(config);\n\n try {\n const challenge = bytesToBase64Url(crypto.getRandomValues(new Uint8Array(32)));\n const result = await passkeyGet({\n challenge,\n rpId,\n userVerification: 'required',\n timeout: 60000,\n });\n\n return result ? { credentialId: result.id, rpId } : null;\n } catch {\n return null;\n }\n}\n\nexport function extractP256Coordinates(\n keyBytes: Uint8Array\n): { x: Uint8Array; y: Uint8Array } {\n if (keyBytes.length === 64) {\n return {\n x: keyBytes.slice(0, 32),\n y: keyBytes.slice(32, 64),\n };\n }\n\n if (keyBytes.length === 65 && keyBytes[0] === 0x04) {\n return {\n x: keyBytes.slice(1, 33),\n y: keyBytes.slice(33, 65),\n };\n }\n\n const pointStart = keyBytes.length - 65;\n if (pointStart > 0 && keyBytes[pointStart] === 0x04) {\n return {\n x: keyBytes.slice(pointStart + 1, pointStart + 33),\n y: keyBytes.slice(pointStart + 33, pointStart + 65),\n };\n }\n\n throw new Error(\n `Unsupported public key format (${keyBytes.length} bytes). Expected raw X||Y (64), uncompressed point (65), or SPKI DER (91).`\n );\n}\n","import * as SecureStore from 'expo-secure-store';\nimport type { PasskeyMetadata } from '@thru/programs/passkey-manager';\n\nconst SECURE_STORE_OPTS = {\n keychainAccessible: SecureStore.WHEN_UNLOCKED_THIS_DEVICE_ONLY,\n} as const;\n\nconst PASSKEY_CREDENTIAL_ID_KEY = 'thru_passkey_credential_id';\nconst PASSKEY_PUBLIC_KEY_X_KEY = 'thru_passkey_pubkey_x';\nconst PASSKEY_PUBLIC_KEY_Y_KEY = 'thru_passkey_pubkey_y';\nconst PASSKEY_RP_ID_KEY = 'thru_passkey_rp_id';\nconst PASSKEY_LABEL_KEY = 'thru_passkey_label';\nconst PASSKEY_CREATED_AT_KEY = 'thru_passkey_created_at';\nconst PASSKEY_LAST_USED_AT_KEY = 'thru_passkey_last_used_at';\n\nconst ADDRESS_KEY = 'thru_address';\nconst USER_ID_KEY = 'thru_user_id';\nconst TOKEN_ACCOUNT_KEY = 'thru_token_account';\n\nexport async function storePasskeyMetadata(metadata: PasskeyMetadata): Promise<void> {\n await Promise.all([\n SecureStore.setItemAsync(PASSKEY_CREDENTIAL_ID_KEY, metadata.credentialId, SECURE_STORE_OPTS),\n SecureStore.setItemAsync(PASSKEY_PUBLIC_KEY_X_KEY, metadata.publicKeyX, SECURE_STORE_OPTS),\n SecureStore.setItemAsync(PASSKEY_PUBLIC_KEY_Y_KEY, metadata.publicKeyY, SECURE_STORE_OPTS),\n SecureStore.setItemAsync(PASSKEY_RP_ID_KEY, metadata.rpId, SECURE_STORE_OPTS),\n SecureStore.setItemAsync(PASSKEY_LABEL_KEY, metadata.label ?? '', SECURE_STORE_OPTS),\n SecureStore.setItemAsync(PASSKEY_CREATED_AT_KEY, metadata.createdAt, SECURE_STORE_OPTS),\n SecureStore.setItemAsync(PASSKEY_LAST_USED_AT_KEY, metadata.lastUsedAt, SECURE_STORE_OPTS),\n ]);\n}\n\nexport async function getStoredPasskeyMetadata(): Promise<PasskeyMetadata | null> {\n const credentialId = await SecureStore.getItemAsync(PASSKEY_CREDENTIAL_ID_KEY);\n if (!credentialId) return null;\n\n const [publicKeyX, publicKeyY, rpId, label, createdAt, lastUsedAt] = await Promise.all([\n SecureStore.getItemAsync(PASSKEY_PUBLIC_KEY_X_KEY),\n SecureStore.getItemAsync(PASSKEY_PUBLIC_KEY_Y_KEY),\n SecureStore.getItemAsync(PASSKEY_RP_ID_KEY),\n SecureStore.getItemAsync(PASSKEY_LABEL_KEY),\n SecureStore.getItemAsync(PASSKEY_CREATED_AT_KEY),\n SecureStore.getItemAsync(PASSKEY_LAST_USED_AT_KEY),\n ]);\n\n if (!rpId || !createdAt) return null;\n\n return {\n credentialId,\n publicKeyX: publicKeyX ?? '',\n publicKeyY: publicKeyY ?? '',\n rpId,\n label: label || undefined,\n createdAt,\n lastUsedAt: lastUsedAt ?? createdAt,\n };\n}\n\nexport async function touchPasskeyLastUsedAt(lastUsedAt = new Date().toISOString()): Promise<string> {\n await SecureStore.setItemAsync(PASSKEY_LAST_USED_AT_KEY, lastUsedAt, SECURE_STORE_OPTS);\n return lastUsedAt;\n}\n\nexport async function hasStoredPasskey(): Promise<boolean> {\n return (await SecureStore.getItemAsync(PASSKEY_CREDENTIAL_ID_KEY)) !== null;\n}\n\nexport async function clearPasskeyMetadata(): Promise<void> {\n await Promise.all([\n SecureStore.deleteItemAsync(PASSKEY_CREDENTIAL_ID_KEY),\n SecureStore.deleteItemAsync(PASSKEY_PUBLIC_KEY_X_KEY),\n SecureStore.deleteItemAsync(PASSKEY_PUBLIC_KEY_Y_KEY),\n SecureStore.deleteItemAsync(PASSKEY_RP_ID_KEY),\n SecureStore.deleteItemAsync(PASSKEY_LABEL_KEY),\n SecureStore.deleteItemAsync(PASSKEY_CREATED_AT_KEY),\n SecureStore.deleteItemAsync(PASSKEY_LAST_USED_AT_KEY),\n ]);\n}\n\nexport async function storeWalletInfo(\n address: string,\n userId: string,\n tokenAccountAddress?: string\n): Promise<void> {\n await Promise.all([\n SecureStore.setItemAsync(ADDRESS_KEY, address, SECURE_STORE_OPTS),\n SecureStore.setItemAsync(USER_ID_KEY, userId, SECURE_STORE_OPTS),\n tokenAccountAddress\n ? SecureStore.setItemAsync(TOKEN_ACCOUNT_KEY, tokenAccountAddress, SECURE_STORE_OPTS)\n : SecureStore.deleteItemAsync(TOKEN_ACCOUNT_KEY),\n ]);\n}\n\nexport async function hasStoredWallet(): Promise<boolean> {\n return (await SecureStore.getItemAsync(ADDRESS_KEY)) !== null;\n}\n\nexport async function getStoredAddress(): Promise<string | null> {\n return SecureStore.getItemAsync(ADDRESS_KEY);\n}\n\nexport async function getStoredUserId(): Promise<string | null> {\n return SecureStore.getItemAsync(USER_ID_KEY);\n}\n\nexport async function getStoredTokenAccount(): Promise<string | null> {\n return SecureStore.getItemAsync(TOKEN_ACCOUNT_KEY);\n}\n\nexport async function clearSession(): Promise<void> {\n await Promise.all([\n SecureStore.deleteItemAsync(ADDRESS_KEY),\n SecureStore.deleteItemAsync(USER_ID_KEY),\n SecureStore.deleteItemAsync(TOKEN_ACCOUNT_KEY),\n ]);\n}\n","/* Add-passkey-to-account transaction builder, lifted from\n `web/wallet-auth-manager/app/page.tsx` (`runValidateThen`,\n `handleSubmitAddPasskey`) so the wallet's `/embedded` post-connect\n step can reuse the exact same flow.\n\n Builds the on-chain transaction:\n VALIDATE(existingAuthority -> ADD_AUTHORITY(newPasskey))\n or VALIDATE(existingAuthority -> multicall[ADD_AUTHORITY, REGISTER_CREDENTIAL])\n asks the caller's existing passkey to sign the challenge, then asks\n the caller's wallet signer to sign the assembled transaction, sends\n it, and returns the result. */\n\nimport {\n type Authority,\n buildAccountContext,\n createValidateChallenge,\n createCredentialLookupSeed,\n decodeAddress,\n deriveWalletAddress,\n encodeAddAuthorityInstruction,\n encodeRegisterCredentialInstruction,\n encodeValidateInstruction,\n parseWalletAuthorities,\n type ParsedAuthority,\n type WalletSigner,\n} from \"@thru/programs/passkey-manager\";\nimport {\n MULTICALL_PROGRAM_PUBKEY,\n buildMulticallInstruction,\n} from \"@thru/programs/multicall\";\n\n/** Minimal shape required from a passkey signer. Both web's\n `signWithDiscoverablePasskey`/`signWithPasskey` and mobile's\n counterparts conform. */\nexport interface PasskeyChallengeSigner {\n signChallenge: (challenge: Uint8Array) => Promise<{\n signatureR: Uint8Array;\n signatureS: Uint8Array;\n authenticatorData: Uint8Array;\n clientDataJSON: Uint8Array;\n }>;\n}\n\n/** Minimal shape required from a Thru chain client. Loosely-typed\n because @thru/sdk's DTS emit is currently broken in this\n repo. The caller passes the real Thru and we narrow operationally. */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyThruClient = any;\n\nexport interface AddDeviceParams {\n /** Loosely-typed Thru chain client (`@thru/sdk/client`). */\n thru: AnyThruClient;\n /** Wallet (the on-chain WalletAccount) to attach the passkey to. */\n walletAddress: string;\n /** Index of the existing authority that approves this change. Must\n currently be a passkey authority. */\n authIdx: number;\n /** New passkey to attach. tag = 1 (passkey). */\n newAuthority: Authority;\n /** Optional credential-lookup registration so the new passkey is\n discoverable on subsequent sign-ins. */\n credentialId?: Uint8Array;\n walletName?: string;\n /** Existing-passkey challenge signer (web or mobile). */\n passkey: PasskeyChallengeSigner;\n /** Wallet transaction signer that returns base64(signed bytes). */\n walletSigner: WalletSigner;\n /** Passkey program address (base58). */\n programAddress: string;\n /** Sign-and-send executor (lifted from passkey-transaction.ts in the\n wallet-auth-manager - wallet apps own this because it depends on\n the `Thru` client's transaction builder). */\n executor: TxExecutor;\n /** Optional status callback so UIs can show progress. */\n onStatus?: (message: string) => void;\n}\n\nexport interface TxExecutorParams {\n thru: AnyThruClient;\n walletSigner: WalletSigner;\n instructionData: Uint8Array;\n readWriteAddresses: string[];\n readOnlyAddresses: string[];\n label: string;\n}\n\nexport interface TxExecutorResult {\n signature: string;\n /** Loosely-typed because @thru/sdk types aren't available. */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n execution: any;\n}\n\nexport type TxExecutor = (\n params: TxExecutorParams,\n) => Promise<TxExecutorResult>;\n\nexport interface AddDeviceResult extends TxExecutorResult {\n /** The new passkey's authority index after the transaction lands. */\n newAuthorityIdx: number;\n}\n\n/**\n * Run VALIDATE + ADD_AUTHORITY [+ REGISTER_CREDENTIAL] to attach a new\n * passkey to an on-chain WalletAccount.\n */\nexport async function addDeviceToAccount(\n params: AddDeviceParams,\n): Promise<AddDeviceResult> {\n const status = params.onStatus ?? (() => {});\n\n const walletAccount = await params.thru.accounts.get(params.walletAddress);\n const walletData: Uint8Array | undefined = walletAccount?.data?.data;\n if (!walletData) {\n throw new Error(\"Wallet account data missing\");\n }\n\n const parsed = parseWalletAuthorities(walletData);\n const authorizing: ParsedAuthority | undefined =\n parsed.authorities[params.authIdx];\n if (!authorizing) {\n throw new Error(\"Authorization index out of bounds\");\n }\n if (authorizing.kind !== \"passkey\") {\n throw new Error(\n \"addDeviceToAccount currently requires a passkey authority for VALIDATE\",\n );\n }\n\n /* The new authority will land at the next free slot. */\n const newAuthorityIdx = parsed.authorities.length;\n\n let readWriteAccounts: Uint8Array[] = [];\n let lookupSeed: Uint8Array | undefined;\n let lookupAddressBytes: Uint8Array | undefined;\n let lookupProof: Uint8Array | undefined;\n\n if (params.credentialId) {\n lookupSeed = await createCredentialLookupSeed(params.credentialId);\n lookupAddressBytes = await deriveWalletAddress(\n lookupSeed,\n params.programAddress,\n );\n\n status(\"Fetching state proof for credential lookup...\");\n const proofResult = await params.thru.proofs.generate({\n proofType: 1 /* StateProofType.CREATING */,\n address: lookupAddressBytes,\n });\n lookupProof = proofResult.proof;\n readWriteAccounts = [lookupAddressBytes];\n }\n\n const ctx = buildAccountContext({\n walletAddress: params.walletAddress,\n readWriteAccounts,\n readOnlyAccounts: params.credentialId ? [MULTICALL_PROGRAM_PUBKEY] : [],\n programAddress: params.programAddress,\n });\n\n const passkeyProgramPubkey = decodeAddress(params.programAddress);\n const addAuthorityInstruction = encodeAddAuthorityInstruction({\n walletAccountIdx: ctx.walletAccountIdx,\n authority: params.newAuthority,\n });\n\n let targetProgramIdx = ctx.getAccountIndex(passkeyProgramPubkey);\n let targetInstructionData = addAuthorityInstruction;\n\n if (params.credentialId) {\n if (!lookupSeed || !lookupAddressBytes || !lookupProof) {\n throw new Error(\"Credential lookup proof data missing\");\n }\n\n const registerCredentialInstruction = encodeRegisterCredentialInstruction({\n walletAccountIdx: ctx.walletAccountIdx,\n lookupAccountIdx: ctx.getAccountIndex(lookupAddressBytes),\n seed: lookupSeed,\n stateProof: lookupProof,\n });\n\n targetProgramIdx = ctx.getAccountIndex(MULTICALL_PROGRAM_PUBKEY);\n targetInstructionData = buildMulticallInstruction([\n {\n programIdx: ctx.getAccountIndex(passkeyProgramPubkey),\n instructionData: addAuthorityInstruction,\n },\n {\n programIdx: ctx.getAccountIndex(passkeyProgramPubkey),\n instructionData: registerCredentialInstruction,\n },\n ]);\n }\n\n /* Build the VALIDATE challenge over the target CPI and ask the caller's passkey to sign. */\n const challenge = await createValidateChallenge(\n parsed.nonce,\n ctx.accountAddresses,\n ctx.walletAccountIdx,\n params.authIdx,\n {\n programIdx: targetProgramIdx,\n instructionData: targetInstructionData,\n },\n );\n\n status(\"Waiting for passkey approval...\");\n const signature = await params.passkey.signChallenge(challenge);\n\n const validateInstruction = encodeValidateInstruction({\n walletAccountIdx: ctx.walletAccountIdx,\n authIdx: params.authIdx,\n targetInstruction: {\n programIdx: targetProgramIdx,\n instructionData: targetInstructionData,\n },\n signatureR: signature.signatureR,\n signatureS: signature.signatureS,\n authenticatorData: signature.authenticatorData,\n clientDataJSON: signature.clientDataJSON,\n });\n\n status(\"Sending transaction...\");\n const result = await params.executor({\n thru: params.thru,\n walletSigner: params.walletSigner,\n instructionData: validateInstruction,\n readWriteAddresses: ctx.readWriteAddresses,\n readOnlyAddresses: ctx.readOnlyAddresses,\n label: params.credentialId\n ? \"VALIDATE -> MULTICALL(ADD_AUTHORITY, REGISTER_CREDENTIAL)\"\n : \"VALIDATE -> ADD_AUTHORITY\",\n });\n\n return { ...result, newAuthorityIdx };\n}\n","import { bytesToHex } from '@thru/programs/passkey-manager';\nimport { create } from 'zustand';\nimport { classifyPasskeyError } from '../mobile/errors';\nimport {\n authenticateWithDiscoverablePasskey,\n registerPasskey,\n signWithPasskey,\n} from '../mobile/passkey';\nimport {\n clearPasskeyMetadata,\n clearSession,\n getStoredAddress,\n getStoredPasskeyMetadata,\n getStoredUserId,\n hasStoredPasskey,\n hasStoredWallet,\n storePasskeyMetadata,\n storeWalletInfo,\n touchPasskeyLastUsedAt,\n} from '../mobile/storage';\nimport type {\n PasskeyAuthApiResponse,\n PasskeyAuthBoundStore,\n PasskeyAuthConfig,\n PasskeyAuthStore,\n PasskeyUser,\n} from './types';\n\nconst storeCache = new Map<string, PasskeyAuthBoundStore<any>>();\n\nfunction createStoreKey(config: PasskeyAuthConfig): string {\n return [config.apiUrl, config.alias ?? '', config.rpId ?? '', config.rpName ?? ''].join('::');\n}\n\nfunction buildDisplayName(address: string): string {\n return `${address.slice(0, 8)}...${address.slice(-4)}`;\n}\n\nfunction toPasskeyUser<TExtra>(\n user: PasskeyAuthApiResponse<TExtra>['user']\n): PasskeyUser<TExtra> {\n return {\n id: user.id,\n displayName: buildDisplayName(user.publicKey),\n tokenAccountAddress: user.tokenAccountAddress ?? null,\n extras: user.extras,\n };\n}\n\nasync function readJson<T>(response: Response): Promise<T> {\n return (await response.json()) as T;\n}\n\nasync function postJson<T>(\n url: string,\n body: Record<string, unknown>\n): Promise<T> {\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n\n const data = await readJson<Record<string, unknown>>(response);\n if (!response.ok || data.success !== true) {\n throw new Error(\n typeof data.error === 'string' ? data.error : 'Request failed'\n );\n }\n\n return data as unknown as T;\n}\n\nasync function getCurrentUser<TExtra>(\n apiUrl: string,\n address: string\n): Promise<PasskeyAuthApiResponse<TExtra> | null> {\n const response = await fetch(`${apiUrl}/auth/me`, {\n headers: {\n 'Content-Type': 'application/json',\n 'x-wallet-address': address,\n },\n });\n\n if (response.status === 404) return null;\n\n const data = await readJson<Record<string, unknown>>(response);\n if (!response.ok || data.success !== true) {\n throw new Error(\n typeof data.error === 'string' ? data.error : 'Failed to fetch current user'\n );\n }\n\n return data as unknown as PasskeyAuthApiResponse<TExtra>;\n}\n\nexport function createPasskeyAuthStore<TExtra = Record<string, never>>(\n config: PasskeyAuthConfig\n): PasskeyAuthBoundStore<TExtra> {\n const resolvedAlias = config.alias ?? 'Thru Wallet';\n\n return create<PasskeyAuthStore<TExtra>>((set, get) => ({\n isAuthenticated: false,\n isLoading: false,\n isInitialized: false,\n hasExistingPasskey: false,\n needsNewPasskey: false,\n error: null,\n user: null,\n address: null,\n activeCredentialId: null,\n\n initialize: async () => {\n try {\n const hasPasskey = await hasStoredPasskey();\n\n if (hasPasskey) {\n const storedAddress = await getStoredAddress();\n if (storedAddress) {\n const user = await Promise.race([\n getCurrentUser<TExtra>(config.apiUrl, storedAddress),\n new Promise<null>((_, reject) =>\n setTimeout(() => reject(new Error('timeout')), 2000)\n ),\n ]).catch(() => undefined);\n\n if (user === null) {\n await clearSession();\n await clearPasskeyMetadata();\n set({ isInitialized: true, hasExistingPasskey: false });\n return;\n }\n } else {\n const metadata = await getStoredPasskeyMetadata();\n if (metadata && !metadata.publicKeyX && !metadata.publicKeyY) {\n await clearPasskeyMetadata();\n set({ isInitialized: true, hasExistingPasskey: false });\n return;\n }\n }\n }\n\n set({ isInitialized: true, hasExistingPasskey: hasPasskey });\n } catch (error) {\n console.error('Failed to initialize passkey auth:', error);\n set({ isInitialized: true, error: 'Failed to initialize wallet' });\n }\n },\n\n createWallet: async () => {\n set({ isLoading: true, error: null, needsNewPasskey: false });\n\n try {\n const tempId = `user-${Date.now()}`;\n const passkeyLabel = resolvedAlias.trim() || 'Thru Wallet';\n const { credentialId, publicKeyX, publicKeyY, rpId } =\n await registerPasskey(passkeyLabel, tempId, {\n rpId: config.rpId,\n rpName: config.rpName,\n });\n\n const now = new Date().toISOString();\n const pubkeyXHex = bytesToHex(publicKeyX);\n const pubkeyYHex = bytesToHex(publicKeyY);\n\n await storePasskeyMetadata({\n credentialId,\n publicKeyX: pubkeyXHex,\n publicKeyY: pubkeyYHex,\n rpId,\n label: passkeyLabel,\n createdAt: now,\n lastUsedAt: now,\n });\n\n const response = await postJson<PasskeyAuthApiResponse<TExtra>>(\n `${config.apiUrl}/auth/register-passkey-wallet`,\n {\n pubkeyX: pubkeyXHex,\n pubkeyY: pubkeyYHex,\n credentialId,\n }\n );\n\n const walletAddress = response.user.publicKey;\n await storeWalletInfo(\n walletAddress,\n response.user.id,\n response.user.tokenAccountAddress ?? undefined\n );\n\n set({\n isLoading: false,\n isAuthenticated: true,\n hasExistingPasskey: true,\n activeCredentialId: credentialId,\n address: walletAddress,\n user: toPasskeyUser(response.user),\n });\n\n return true;\n } catch (error) {\n if (classifyPasskeyError(error) === 'USER_CANCELLED') {\n set({ isLoading: false });\n return false;\n }\n\n console.error('Failed to create passkey wallet:', error);\n set({\n isLoading: false,\n error: error instanceof Error ? error.message : 'Failed to create wallet',\n });\n return false;\n }\n },\n\n unlockWithPasskey: async () => {\n set({ isLoading: true, error: null, needsNewPasskey: false });\n\n try {\n const metadata = await getStoredPasskeyMetadata();\n if (!metadata) throw new Error('No stored passkey found');\n\n await signWithPasskey(\n metadata.credentialId,\n crypto.getRandomValues(new Uint8Array(32)),\n metadata.rpId\n );\n await touchPasskeyLastUsedAt().catch((error) => {\n console.warn('Failed to update passkey last-used timestamp:', error);\n });\n\n const hasWallet = await hasStoredWallet();\n let walletAddress: string;\n let userId: string;\n let tokenAccountAddress: string | undefined;\n let response: PasskeyAuthApiResponse<TExtra> | null = null;\n\n if (hasWallet) {\n const storedAddress = await getStoredAddress();\n const storedUserId = await getStoredUserId();\n if (!storedAddress || !storedUserId) {\n throw new Error('Incomplete wallet data');\n }\n\n walletAddress = storedAddress;\n userId = storedUserId;\n\n const current = await getCurrentUser<TExtra>(config.apiUrl, walletAddress);\n if (current) {\n response = current;\n tokenAccountAddress = current.user.tokenAccountAddress ?? undefined;\n } else if (metadata.publicKeyX && metadata.publicKeyY) {\n response = await postJson<PasskeyAuthApiResponse<TExtra>>(\n `${config.apiUrl}/auth/register-passkey-wallet`,\n {\n pubkeyX: metadata.publicKeyX,\n pubkeyY: metadata.publicKeyY,\n credentialId: metadata.credentialId,\n }\n );\n walletAddress = response.user.publicKey;\n userId = response.user.id;\n tokenAccountAddress = response.user.tokenAccountAddress ?? undefined;\n await storeWalletInfo(walletAddress, userId, tokenAccountAddress);\n } else {\n await clearSession();\n await clearPasskeyMetadata();\n set({ isLoading: false, hasExistingPasskey: false, error: null });\n return false;\n }\n } else if (metadata.publicKeyX && metadata.publicKeyY) {\n response = await postJson<PasskeyAuthApiResponse<TExtra>>(\n `${config.apiUrl}/auth/register-passkey-wallet`,\n {\n pubkeyX: metadata.publicKeyX,\n pubkeyY: metadata.publicKeyY,\n credentialId: metadata.credentialId,\n }\n );\n walletAddress = response.user.publicKey;\n userId = response.user.id;\n tokenAccountAddress = response.user.tokenAccountAddress ?? undefined;\n await storeWalletInfo(walletAddress, userId, tokenAccountAddress);\n } else {\n const recovered = await postJson<PasskeyAuthApiResponse<TExtra>>(\n `${config.apiUrl}/auth/recover-passkey-wallet`,\n { credentialId: metadata.credentialId }\n ).catch(() => null);\n\n if (!recovered) {\n await clearSession();\n await clearPasskeyMetadata();\n set({ isLoading: false, hasExistingPasskey: false, error: null });\n return false;\n }\n\n response = recovered;\n walletAddress = recovered.user.publicKey;\n userId = recovered.user.id;\n tokenAccountAddress = recovered.user.tokenAccountAddress ?? undefined;\n await storeWalletInfo(walletAddress, userId, tokenAccountAddress);\n }\n\n set({\n isLoading: false,\n isAuthenticated: true,\n activeCredentialId: metadata.credentialId,\n address: walletAddress,\n user: response ? toPasskeyUser(response.user) : get().user,\n });\n\n return true;\n } catch (error) {\n console.error('Failed to unlock with passkey:', error);\n const kind = classifyPasskeyError(error);\n\n if (kind === 'USER_CANCELLED') {\n set({ isLoading: false });\n } else if (kind === 'NOT_FOUND') {\n await clearPasskeyMetadata();\n set({ isLoading: false, hasExistingPasskey: false, error: null });\n } else {\n set({\n isLoading: false,\n error: error instanceof Error ? error.message : 'Failed to unlock',\n });\n }\n\n return false;\n }\n },\n\n recoverWithDiscoverablePasskey: async () => {\n set({ isLoading: true, error: null, needsNewPasskey: false });\n\n try {\n const discovered = await authenticateWithDiscoverablePasskey({\n rpId: config.rpId,\n });\n\n if (!discovered) {\n set({ isLoading: false });\n return false;\n }\n\n const response = await postJson<PasskeyAuthApiResponse<TExtra>>(\n `${config.apiUrl}/auth/recover-passkey-wallet`,\n { credentialId: discovered.credentialId }\n ).catch(() => null);\n\n if (!response) {\n set({ isLoading: false, needsNewPasskey: true });\n return false;\n }\n\n const walletAddress = response.user.publicKey;\n const userId = response.user.id;\n const tokenAccountAddress = response.user.tokenAccountAddress ?? undefined;\n const now = new Date().toISOString();\n\n await storePasskeyMetadata({\n credentialId: discovered.credentialId,\n publicKeyX: '',\n publicKeyY: '',\n rpId: discovered.rpId,\n createdAt: now,\n lastUsedAt: now,\n });\n await storeWalletInfo(walletAddress, userId, tokenAccountAddress);\n\n set({\n isLoading: false,\n isAuthenticated: true,\n hasExistingPasskey: true,\n activeCredentialId: discovered.credentialId,\n address: walletAddress,\n user: toPasskeyUser(response.user),\n });\n\n return true;\n } catch (error) {\n console.error('Failed to recover with discoverable passkey:', error);\n set({\n isLoading: false,\n error:\n error instanceof Error ? error.message : 'Failed to recover wallet',\n });\n return false;\n }\n },\n\n logout: async () => {\n try {\n await clearSession();\n } catch (error) {\n console.error('Failed to clear passkey session:', error);\n }\n\n set({\n isAuthenticated: false,\n needsNewPasskey: false,\n user: null,\n address: null,\n activeCredentialId: null,\n });\n },\n\n clearError: () => set({ error: null }),\n dismissNewPasskey: () => set({ needsNewPasskey: false }),\n }));\n}\n\nexport function getPasskeyAuthStore<TExtra = Record<string, never>>(\n config: PasskeyAuthConfig\n): PasskeyAuthBoundStore<TExtra> {\n const key = createStoreKey(config);\n const cached = storeCache.get(key) as PasskeyAuthBoundStore<TExtra> | undefined;\n if (cached) return cached;\n\n const store = createPasskeyAuthStore<TExtra>(config);\n storeCache.set(key, store);\n return store;\n}\n\nexport function usePasskeyAuth<TExtra = Record<string, never>>(\n config: PasskeyAuthConfig\n): PasskeyAuthStore<TExtra> {\n return getPasskeyAuthStore<TExtra>(config)();\n}\n","const PASSKEY_ERRORS = {\n USER_CANCELLED: [\n 'error 1001',\n 'UserCancelled',\n 'Passkey authentication was cancelled',\n 'Passkey registration was cancelled',\n ],\n NOT_FOUND: [\n 'not found',\n 'No credentials available',\n 'no passkey',\n 'NoCredentials',\n ],\n} as const;\n\nexport type PasskeyErrorKind = keyof typeof PASSKEY_ERRORS;\n\nexport function classifyPasskeyError(error: unknown): PasskeyErrorKind | null {\n const message =\n error instanceof Error ? error.message : typeof error === 'string' ? error : null;\n\n if (!message) return null;\n\n for (const [kind, patterns] of Object.entries(PASSKEY_ERRORS)) {\n if (patterns.some((pattern) => message.includes(pattern))) {\n return kind as PasskeyErrorKind;\n }\n }\n\n return null;\n}\n"],"mappings":"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","names":["import_passkey_manager","passkeyCreate","passkeyGet","import_passkey_manager","import_passkey_manager","readJson"]}
package/dist/auth.js CHANGED
@@ -16,7 +16,7 @@ import {
16
16
  } from "./chunk-ZNBMADOM.js";
17
17
  import {
18
18
  addDeviceToAccount
19
- } from "./chunk-QAQNRQ7G.js";
19
+ } from "./chunk-KASTJBBY.js";
20
20
 
21
21
  // src/auth/execute-tx.ts
22
22
  import { base64UrlToBytes, bytesToBase64, bytesToHex } from "@thru/programs/passkey-manager";