@ledgerhq/device-signer-kit-solana 0.0.0-develop-20260811001235 → 0.0.0-develop-20260813001639

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.
@@ -1,2 +1,2 @@
1
- "use strict";var I=Object.defineProperty;var E=Object.getOwnPropertyDescriptor;var b=Object.getOwnPropertyNames;var _=Object.prototype.hasOwnProperty;var P=(a,e)=>{for(var n in e)I(a,n,{get:e[n],enumerable:!0})},q=(a,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of b(e))!_.call(a,t)&&t!==n&&I(a,t,{get:()=>e[t],enumerable:!(r=E(e,t))||r.enumerable});return a};var D=a=>q(I({},"__esModule",{value:!0}),a);var F={};P(F,{BuildGenericClearSignContextTask:()=>L,COMPUTE_BUDGET_PROGRAM_ID:()=>w,DEFAULT_NETWORK:()=>O});module.exports=D(F);var c=require("@ledgerhq/context-module"),x=require("@ledgerhq/device-management-kit"),M=require("../../app-binder/clear-sign/idl-type-pool"),N=require("../../app-binder/clear-sign/requirements"),T=require("../../app-binder/services/utils/TransactionParser");const w="ComputeBudget111111111111111111111111111111",O="solana-mainnet",v=new Map;class L{constructor(e){this.args=e;this.logger=e.loggerFactory("BuildGenericClearSignContextTask"),this.network=e.network??O}logger;network;async run(){const e={mode:"none",poolContexts:[],instructionInfoContexts:[],challengeBoundRequirements:{tokenAccountStates:[],altResolutions:[],trustedNames:[],tokenAmountAltRefs:[],mintAltRefs:[]}},n=await new T.TransactionParser(void 0,{preserveAltRefs:!0}).parse(this.args.transaction).run();if(n.isLeft())return this.logger.warn("[run] parse failed; falling back to legacy",{data:{error:n.extract()}}),e;const r=n.unsafeCoerce().message,t=r.compiledInstructions.map(o=>({ix:o,programId:this.programIdOf(r,o.programIdIndex)})).filter(({programId:o})=>o!==w);if(t.length===0)return e;const l=Array.from(new Set(t.map(o=>o.programId))),p=await this.args.contextModule.getContexts({deviceModelId:this.args.deviceModelId,instructions:l.map(o=>({programId:o})),network:this.network},[c.ClearSignContextType.SOLANA_INSTRUCTION_INFO]),u=new Map;for(const o of p){if(o.type!==c.ClearSignContextType.SOLANA_INSTRUCTION_INFO)continue;const i=u.get(o.payload.programId)??[];i.push({payload:o.payload,context:o}),u.set(o.payload.programId,i)}const f=[],A=new Map;let y=0;for(const{ix:o,programId:i}of t){const m=(u.get(i)??[]).find(({payload:B})=>this.discriminatorMatches(B.discriminator,o.data)),k=m?this.toInstructionDescriptor(m.payload):null;if(!m||!k){y+=1;continue}f.push({instruction:{programId:i,accounts:this.toRequirementAccounts(r,o.accountKeyIndexes),data:o.data},descriptor:k}),A.set(`${i}:${m.payload.discriminator}`,m.context)}if(f.length===0)return e;const h=Array.from(A.values());if(y>0)return this.logger.warn("[run] transaction has unrecognized instructions; falling back to legacy",{data:{unrecognized:y,recognized:f.length}}),e;const R="full",C=(0,N.buildRequirements)(f,{selectEnumVariants:this.args.selectEnumVariants});if(C.isLeft())return this.logger.warn("[run] requirement build failed; falling back",{data:{error:C.extract()}}),e;const s=C.unsafeCoerce(),g=[];s.tokenInfos.length>0&&g.push(...await this.getContextsByType({deviceModelId:this.args.deviceModelId,mints:s.tokenInfos,network:this.network},c.ClearSignContextType.SOLANA_TOKEN_INFO)),g.push(...this.selectedEnumVariants(s.enumVariants,h));const S=[];for(const o of s.tokenAmountRefs){const i=await this.getContextsByType({deviceModelId:this.args.deviceModelId,mints:[o],network:this.network},c.ClearSignContextType.SOLANA_TOKEN_INFO);i.length>0?g.push(...i):S.push(o)}const d={tokenAccountStates:[...s.tokenAccountStates,...S],altResolutions:s.altResolutions,trustedNames:s.trustedNames,tokenAmountAltRefs:s.tokenAmountAltRefs,mintAltRefs:s.mintAltRefs};return this.logger.debug("[run] built clear-sign context",{data:{mode:R,templates:h.length,pool:g.length,challengeBound:d.tokenAccountStates.length+d.altResolutions.length+d.trustedNames.length+d.tokenAmountAltRefs.length+d.mintAltRefs.length}}),{mode:R,poolContexts:g,instructionInfoContexts:h,challengeBoundRequirements:d}}async getContextsByType(e,n){const t=(await this.args.contextModule.getContexts(e,[n])).filter(l=>l.type===n);return t.length===0&&this.logger.warn("[run] satellite fetch yielded no descriptor (degraded)",{data:{type:n}}),t}selectedEnumVariants(e,n){const r=[];for(const t of e)for(const l of n){if(l.type!==c.ClearSignContextType.SOLANA_INSTRUCTION_INFO||l.payload.programId!==t.programId)continue;const p=l.payload.enumVariants.find(u=>u.enumId===t.enumId&&u.variantIndex===t.variantIndex);if(p){r.push({type:c.ClearSignContextType.SOLANA_ENUM_VARIANT,payload:{programId:t.programId,enumId:t.enumId,variantIndex:t.variantIndex,descriptor:p.descriptor},certificate:l.certificate});break}}return r}programIdOf(e,n){return e.allKeys[n]?.toBase58()??""}discriminatorMatches(e,n){const r=(0,x.hexaStringToBuffer)(e);if(!r||r.length===0||n.length<r.length)return!1;for(let t=0;t<r.length;t++)if(n[t]!==r[t])return!1;return!0}toInstructionDescriptor(e){return{discriminator:e.discriminator,idlDescriptor:{type_pool:e.idlDescriptor.typePool,root_type:e.idlDescriptor.rootType},mintAssociations:e.mintAssociations,valueFlowPorts:e.valueFlowPorts,accountResets:e.accountResets,displayFields:e.displayFields,enumCache:this.toEnumCache(e.enumVariants)}}toEnumCache(e){if(e.length===0)return v;const n=[];for(const r of e){const t=(0,x.hexaStringToBuffer)(r.descriptor.data);t&&n.push(t)}return(0,M.buildEnumCache)(n).caseOf({Left:()=>v,Right:r=>r})}toRequirementAccounts(e,n){return n.map(r=>{const t=e.addressLookupRefs?.[r];return t?{altRef:{altAddress:t.altAddress.toBase58(),entryIndex:t.entryIndex}}:{address:e.allKeys[r]?.toBase58()}})}}0&&(module.exports={BuildGenericClearSignContextTask,COMPUTE_BUDGET_PROGRAM_ID,DEFAULT_NETWORK});
1
+ "use strict";var x=Object.defineProperty;var b=Object.getOwnPropertyDescriptor;var _=Object.getOwnPropertyNames;var P=Object.prototype.hasOwnProperty;var q=(a,t)=>{for(var n in t)x(a,n,{get:t[n],enumerable:!0})},D=(a,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let e of _(t))!P.call(a,e)&&e!==n&&x(a,e,{get:()=>t[e],enumerable:!(r=b(t,e))||r.enumerable});return a};var L=a=>D(x({},"__esModule",{value:!0}),a);var V={};q(V,{BuildGenericClearSignContextTask:()=>F,COMPUTE_BUDGET_PROGRAM_ID:()=>O,DEFAULT_NETWORK:()=>B});module.exports=L(V);var c=require("@ledgerhq/context-module"),A=require("@ledgerhq/device-management-kit"),N=require("../../app-binder/clear-sign/idl-type-pool"),T=require("../../app-binder/clear-sign/requirements"),w=require("../../app-binder/services/utils/TransactionParser");const O="ComputeBudget111111111111111111111111111111",B="solana-mainnet",M=new Map;class F{constructor(t){this.args=t;this.logger=t.loggerFactory("BuildGenericClearSignContextTask"),this.network=t.network??B}logger;network;async run(){const t={mode:"none",poolContexts:[],instructionInfoContexts:[],challengeBoundRequirements:{tokenAccountStates:[],altResolutions:[],trustedNames:[],tokenAmountAltRefs:[],mintAltRefs:[]}},n=await new w.TransactionParser(void 0,{preserveAltRefs:!0}).parse(this.args.transaction).run();if(n.isLeft())return this.logger.warn("[run] parse failed; falling back to legacy",{data:{error:n.extract()}}),t;const r=n.unsafeCoerce().message,e=r.compiledInstructions.map(o=>({ix:o,programId:this.programIdOf(r,o.programIdIndex)})).filter(({programId:o})=>o!==O);if(e.length===0)return t;const l=Array.from(new Set(e.map(o=>o.programId))),p=await this.args.contextModule.getContexts({deviceModelId:this.args.deviceModelId,instructions:l.map(o=>({programId:o})),network:this.network},[c.ClearSignContextType.SOLANA_INSTRUCTION_INFO]),u=new Map;for(const o of p){if(o.type!==c.ClearSignContextType.SOLANA_INSTRUCTION_INFO)continue;const i=u.get(o.payload.programId)??[];i.push({payload:o.payload,context:o}),u.set(o.payload.programId,i)}const f=[],R=new Map;let y=0;for(const{ix:o,programId:i}of e){const m=(u.get(i)??[]).filter(({payload:I})=>this.discriminatorMatches(I.discriminator,o.data)).sort((I,E)=>E.payload.discriminator.length-I.payload.discriminator.length)[0],v=m?this.toInstructionDescriptor(m.payload):null;if(!m||!v){y+=1;continue}f.push({instruction:{programId:i,accounts:this.toRequirementAccounts(r,o.accountKeyIndexes),data:o.data},descriptor:v}),R.set(`${i}:${m.payload.discriminator}`,m.context)}if(f.length===0)return t;const h=Array.from(R.values());if(y>0)return this.logger.warn("[run] transaction has unrecognized instructions; falling back to legacy",{data:{unrecognized:y,recognized:f.length}}),t;const S="full",C=(0,T.buildRequirements)(f,{selectEnumVariants:this.args.selectEnumVariants});if(C.isLeft())return this.logger.warn("[run] requirement build failed; falling back",{data:{error:C.extract()}}),t;const s=C.unsafeCoerce(),g=[];s.tokenInfos.length>0&&g.push(...await this.getContextsByType({deviceModelId:this.args.deviceModelId,mints:s.tokenInfos,network:this.network},c.ClearSignContextType.SOLANA_TOKEN_INFO)),g.push(...this.selectedEnumVariants(s.enumVariants,h));const k=[];for(const o of s.tokenAmountRefs){const i=await this.getContextsByType({deviceModelId:this.args.deviceModelId,mints:[o],network:this.network},c.ClearSignContextType.SOLANA_TOKEN_INFO);i.length>0?g.push(...i):k.push(o)}const d={tokenAccountStates:[...s.tokenAccountStates,...k],altResolutions:s.altResolutions,trustedNames:s.trustedNames,tokenAmountAltRefs:s.tokenAmountAltRefs,mintAltRefs:s.mintAltRefs};return this.logger.debug("[run] built clear-sign context",{data:{mode:S,templates:h.length,pool:g.length,challengeBound:d.tokenAccountStates.length+d.altResolutions.length+d.trustedNames.length+d.tokenAmountAltRefs.length+d.mintAltRefs.length}}),{mode:S,poolContexts:g,instructionInfoContexts:h,challengeBoundRequirements:d}}async getContextsByType(t,n){const e=(await this.args.contextModule.getContexts(t,[n])).filter(l=>l.type===n);return e.length===0&&this.logger.warn("[run] satellite fetch yielded no descriptor (degraded)",{data:{type:n}}),e}selectedEnumVariants(t,n){const r=[];for(const e of t)for(const l of n){if(l.type!==c.ClearSignContextType.SOLANA_INSTRUCTION_INFO||l.payload.programId!==e.programId)continue;const p=l.payload.enumVariants.find(u=>u.enumId===e.enumId&&u.variantIndex===e.variantIndex);if(p){r.push({type:c.ClearSignContextType.SOLANA_ENUM_VARIANT,payload:{programId:e.programId,enumId:e.enumId,variantIndex:e.variantIndex,descriptor:p.descriptor},certificate:l.certificate});break}}return r}programIdOf(t,n){return t.allKeys[n]?.toBase58()??""}discriminatorMatches(t,n){if(t==="")return!0;const r=(0,A.hexaStringToBuffer)(t);if(!r||r.length===0||n.length<r.length)return!1;for(let e=0;e<r.length;e++)if(n[e]!==r[e])return!1;return!0}toInstructionDescriptor(t){return{discriminator:t.discriminator,idlDescriptor:{type_pool:t.idlDescriptor.typePool,root_type:t.idlDescriptor.rootType},mintAssociations:t.mintAssociations,valueFlowPorts:t.valueFlowPorts,accountResets:t.accountResets,displayFields:t.displayFields,enumCache:this.toEnumCache(t.enumVariants)}}toEnumCache(t){if(t.length===0)return M;const n=[];for(const r of t){const e=(0,A.hexaStringToBuffer)(r.descriptor.data);e&&n.push(e)}return(0,N.buildEnumCache)(n).caseOf({Left:()=>M,Right:r=>r})}toRequirementAccounts(t,n){return n.map(r=>{const e=t.addressLookupRefs?.[r];return e?{altRef:{altAddress:e.altAddress.toBase58(),entryIndex:e.entryIndex}}:{address:t.allKeys[r]?.toBase58()}})}}0&&(module.exports={BuildGenericClearSignContextTask,COMPUTE_BUDGET_PROGRAM_ID,DEFAULT_NETWORK});
2
2
  //# sourceMappingURL=BuildGenericClearSignContextTask.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/internal/app-binder/task/BuildGenericClearSignContextTask.ts"],
4
- "sourcesContent": ["import {\n type ClearSignContext,\n ClearSignContextType,\n type ContextModule,\n type SolanaInstructionInfoPayload,\n} from \"@ledgerhq/context-module\";\nimport {\n type DeviceModelId,\n hexaStringToBuffer,\n type LoggerPublisherService,\n} from \"@ledgerhq/device-management-kit\";\n\nimport { type ClearSignMode } from \"@api/app-binder/SignTransactionDeviceActionTypes\";\nimport {\n buildEnumCache,\n type VariantCache,\n} from \"@internal/app-binder/clear-sign/idl-type-pool\";\nimport {\n type AltEntryKey,\n buildRequirements,\n type BuildRequirementsOptions,\n type DescriptorRequirements,\n type InstructionDescriptor,\n type MatchedInstruction,\n type RequirementAccount,\n} from \"@internal/app-binder/clear-sign/requirements\";\nimport { type NormalizedMessage } from \"@internal/app-binder/services/TransactionInspector\";\nimport { TransactionParser } from \"@internal/app-binder/services/utils/TransactionParser\";\n\n/**\n * ComputeBudget program \u2014 a hardcoded allow-list skip. It has no CAL descriptor\n * and is understood natively by the device: never looked up, never counted,\n * never streamed. `setComputeUnitPrice` (priority fee) is a ComputeBudget\n * instruction so it is covered by the same skip.\n */\nexport const COMPUTE_BUDGET_PROGRAM_ID =\n \"ComputeBudget111111111111111111111111111111\";\n\nexport const DEFAULT_NETWORK = \"solana-mainnet\";\nconst EMPTY_ENUM_CACHE: VariantCache = new Map();\n\n/** Challenge-bound requirements, fetched one at a time in the provide phase. */\nexport type ChallengeBoundRequirements = Pick<\n DescriptorRequirements,\n \"tokenAccountStates\" | \"altResolutions\" | \"trustedNames\"\n> & {\n /** ALT-backed PARAM_TOKEN_AMOUNT.TOKEN refs needing TOKEN_INFO-first resolution. */\n tokenAmountAltRefs: AltEntryKey[];\n /** ALT-backed MINT entries from MINT_ASSOCIATIONS; require TOKEN_INFO via hold-and-conditionally-stream. */\n mintAltRefs: AltEntryKey[];\n};\n\n/**\n * Everything the device needs to clear-sign a transaction, gathered host-side.\n * The non-challenge-bound descriptors are pre-fetched here; the challenge-bound\n * ones are carried as requirements and fetched+streamed by the provide phase.\n */\nexport type GenericClearSignContext = {\n /** `full` (merge) / `srfc39-only` (partial) / `none` (legacy fallback). */\n readonly mode: ClearSignMode;\n /** Phase A pool descriptors that need no challenge (token-info, enum-variant). */\n readonly poolContexts: ClearSignContext[];\n /** Phase B templates: one SOLANA_INSTRUCTION_INFO per matched (programId, discriminator). */\n readonly instructionInfoContexts: ClearSignContext[];\n /** Challenge-bound Phase A requirements, fetched+streamed in the provide phase. */\n readonly challengeBoundRequirements: ChallengeBoundRequirements;\n};\n\nexport type BuildGenericClearSignContextTaskArgs = {\n readonly contextModule: ContextModule;\n readonly transaction: Uint8Array;\n readonly deviceModelId: DeviceModelId;\n readonly loggerFactory: (tag: string) => LoggerPublisherService;\n readonly network?: string;\n /** Enum-variant decoder override; defaults to the real type-pool decoder. */\n readonly selectEnumVariants?: BuildRequirementsOptions[\"selectEnumVariants\"];\n};\n\n/**\n * Groups the whole host-side preparation for generic clear-signing: parse the\n * TX (raw ALT refs preserved), skip ComputeBudget, look up CAL\n * `INSTRUCTION_INFO` per remaining program, match discriminators, build the\n * requirement set, and pre-fetch the non-challenge-bound satellite descriptors.\n * Challenge-bound descriptors are NOT fetched here \u2014 each needs a fresh\n * `GET CHALLENGE` issued immediately before it is streamed, so they are carried\n * forward as requirements and resolved by the provide task.\n */\nexport class BuildGenericClearSignContextTask {\n private readonly logger: LoggerPublisherService;\n private readonly network: string;\n\n constructor(private readonly args: BuildGenericClearSignContextTaskArgs) {\n this.logger = args.loggerFactory(\"BuildGenericClearSignContextTask\");\n this.network = args.network ?? DEFAULT_NETWORK;\n }\n\n async run(): Promise<GenericClearSignContext> {\n const none: GenericClearSignContext = {\n mode: \"none\",\n poolContexts: [],\n instructionInfoContexts: [],\n challengeBoundRequirements: {\n tokenAccountStates: [],\n altResolutions: [],\n trustedNames: [],\n tokenAmountAltRefs: [],\n mintAltRefs: [],\n },\n };\n\n // --- Parse + CAL lookup + match (Stage 1) ---\n const parsed = await new TransactionParser(undefined, {\n preserveAltRefs: true,\n })\n .parse(this.args.transaction)\n .run();\n if (parsed.isLeft()) {\n this.logger.warn(\"[run] parse failed; falling back to legacy\", {\n data: { error: parsed.extract() },\n });\n return none;\n }\n const message = parsed.unsafeCoerce().message;\n\n const remaining = message.compiledInstructions\n .map((ix) => ({\n ix,\n programId: this.programIdOf(message, ix.programIdIndex),\n }))\n .filter(({ programId }) => programId !== COMPUTE_BUDGET_PROGRAM_ID);\n if (remaining.length === 0) return none;\n\n const distinctProgramIds = Array.from(\n new Set(remaining.map((r) => r.programId)),\n );\n const infoContexts = await this.args.contextModule.getContexts(\n {\n deviceModelId: this.args.deviceModelId,\n instructions: distinctProgramIds.map((programId) => ({ programId })),\n network: this.network,\n },\n [ClearSignContextType.SOLANA_INSTRUCTION_INFO],\n );\n\n const byProgram = new Map<\n string,\n { payload: SolanaInstructionInfoPayload; context: ClearSignContext }[]\n >();\n for (const context of infoContexts) {\n if (context.type !== ClearSignContextType.SOLANA_INSTRUCTION_INFO)\n continue;\n const list = byProgram.get(context.payload.programId) ?? [];\n list.push({ payload: context.payload, context });\n byProgram.set(context.payload.programId, list);\n }\n\n const matched: MatchedInstruction[] = [];\n const templateByKey = new Map<string, ClearSignContext>();\n let unrecognized = 0;\n for (const { ix, programId } of remaining) {\n const candidate = (byProgram.get(programId) ?? []).find(({ payload }) =>\n this.discriminatorMatches(payload.discriminator, ix.data),\n );\n const descriptor = candidate\n ? this.toInstructionDescriptor(candidate.payload)\n : null;\n if (!candidate || !descriptor) {\n unrecognized += 1;\n continue;\n }\n matched.push({\n instruction: {\n programId,\n accounts: this.toRequirementAccounts(message, ix.accountKeyIndexes),\n data: ix.data,\n },\n descriptor,\n });\n templateByKey.set(\n `${programId}:${candidate.payload.discriminator}`,\n candidate.context,\n );\n }\n if (matched.length === 0) return none;\n\n const instructionInfoContexts = Array.from(templateByKey.values());\n\n // The device requires every non-ComputeBudget instruction to have a\n // template at FINALIZE (cs_transaction_finalize walks all instructions).\n // Any unrecognized instruction guarantees 6d20 so cs_transaction_reset() and\n // basic sign to 6808 (blind signing disabled). Bail out early so basic sign\n // starts from a clean device state.\n if (unrecognized > 0) {\n this.logger.warn(\n \"[run] transaction has unrecognized instructions; falling back to legacy\",\n { data: { unrecognized, recognized: matched.length } },\n );\n return none;\n }\n const mode: ClearSignMode = \"full\";\n\n // --- Requirements (Stage 2) ---\n const requirementsResult = buildRequirements(matched, {\n selectEnumVariants: this.args.selectEnumVariants,\n });\n if (requirementsResult.isLeft()) {\n this.logger.warn(\"[run] requirement build failed; falling back\", {\n data: { error: requirementsResult.extract() },\n });\n return none;\n }\n const requirements = requirementsResult.unsafeCoerce();\n\n // --- Fetch non-challenge-bound satellites (Stage 3) ---\n const poolContexts: ClearSignContext[] = [];\n if (requirements.tokenInfos.length > 0) {\n poolContexts.push(\n ...(await this.getContextsByType(\n {\n deviceModelId: this.args.deviceModelId,\n mints: requirements.tokenInfos,\n network: this.network,\n },\n ClearSignContextType.SOLANA_TOKEN_INFO,\n )),\n );\n }\n poolContexts.push(\n ...this.selectedEnumVariants(\n requirements.enumVariants,\n instructionInfoContexts,\n ),\n );\n\n // PARAM_TOKEN_AMOUNT.TOKEN refs: try TOKEN_INFO first (optimistic mint).\n // If that fails, fall back to TOKEN_ACCOUNT_STATE (it's an ATA).\n const tokenAmountFallbackAccounts: string[] = [];\n for (const ref of requirements.tokenAmountRefs) {\n const tokenInfoContexts = await this.getContextsByType(\n {\n deviceModelId: this.args.deviceModelId,\n mints: [ref],\n network: this.network,\n },\n ClearSignContextType.SOLANA_TOKEN_INFO,\n );\n if (tokenInfoContexts.length > 0) {\n poolContexts.push(...tokenInfoContexts);\n } else {\n tokenAmountFallbackAccounts.push(ref);\n }\n }\n\n // RequirementAccumulator.build() already strips tokenAmountAltRefs and\n // mintAltRefs entries from altResolutions (cross-bucket priority dedup),\n // so requirements.altResolutions is safe to use directly here.\n const challengeBoundRequirements: ChallengeBoundRequirements = {\n tokenAccountStates: [\n ...requirements.tokenAccountStates,\n ...tokenAmountFallbackAccounts,\n ],\n altResolutions: requirements.altResolutions,\n trustedNames: requirements.trustedNames,\n tokenAmountAltRefs: requirements.tokenAmountAltRefs,\n mintAltRefs: requirements.mintAltRefs,\n };\n\n this.logger.debug(\"[run] built clear-sign context\", {\n data: {\n mode,\n templates: instructionInfoContexts.length,\n pool: poolContexts.length,\n challengeBound:\n challengeBoundRequirements.tokenAccountStates.length +\n challengeBoundRequirements.altResolutions.length +\n challengeBoundRequirements.trustedNames.length +\n challengeBoundRequirements.tokenAmountAltRefs.length +\n challengeBoundRequirements.mintAltRefs.length,\n },\n });\n\n return {\n mode,\n poolContexts,\n instructionInfoContexts,\n challengeBoundRequirements,\n };\n }\n\n /** Fetch contexts of `type`; ERROR / wrong-type contexts are dropped (satellites degrade). */\n private async getContextsByType<TInput>(\n input: TInput,\n type: ClearSignContextType,\n ): Promise<ClearSignContext[]> {\n const contexts = await this.args.contextModule.getContexts(input, [type]);\n const usable = contexts.filter((c) => c.type === type);\n if (usable.length === 0) {\n this.logger.warn(\n \"[run] satellite fetch yielded no descriptor (degraded)\",\n {\n data: { type },\n },\n );\n }\n return usable;\n }\n\n /** Build SOLANA_ENUM_VARIANT contexts for the selected variants from the bundled payloads. */\n private selectedEnumVariants(\n keys: readonly {\n programId: string;\n enumId: string;\n variantIndex: number;\n }[],\n instructionInfoContexts: ClearSignContext[],\n ): ClearSignContext[] {\n const out: ClearSignContext[] = [];\n for (const key of keys) {\n for (const context of instructionInfoContexts) {\n if (context.type !== ClearSignContextType.SOLANA_INSTRUCTION_INFO)\n continue;\n if (context.payload.programId !== key.programId) continue;\n const variant = context.payload.enumVariants.find(\n (v) => v.enumId === key.enumId && v.variantIndex === key.variantIndex,\n );\n if (variant) {\n out.push({\n type: ClearSignContextType.SOLANA_ENUM_VARIANT,\n payload: {\n programId: key.programId,\n enumId: key.enumId,\n variantIndex: key.variantIndex,\n descriptor: variant.descriptor,\n },\n certificate: context.certificate,\n });\n break;\n }\n }\n }\n return out;\n }\n\n private programIdOf(message: NormalizedMessage, index: number): string {\n return message.allKeys[index]?.toBase58() ?? \"\";\n }\n\n private discriminatorMatches(\n discriminatorHex: string,\n data: Uint8Array,\n ): boolean {\n const disc = hexaStringToBuffer(discriminatorHex);\n if (!disc || disc.length === 0 || data.length < disc.length) return false;\n for (let i = 0; i < disc.length; i++) {\n if (data[i] !== disc[i]) return false;\n }\n return true;\n }\n\n private toInstructionDescriptor(\n payload: SolanaInstructionInfoPayload,\n ): InstructionDescriptor {\n return {\n discriminator: payload.discriminator,\n idlDescriptor: {\n type_pool: payload.idlDescriptor.typePool,\n root_type: payload.idlDescriptor.rootType,\n },\n mintAssociations: payload.mintAssociations,\n valueFlowPorts: payload.valueFlowPorts,\n accountResets: payload.accountResets,\n displayFields: payload.displayFields,\n enumCache: this.toEnumCache(payload.enumVariants),\n };\n }\n\n private toEnumCache(\n enumVariants: SolanaInstructionInfoPayload[\"enumVariants\"],\n ): VariantCache {\n if (enumVariants.length === 0) return EMPTY_ENUM_CACHE;\n const tlvs: Uint8Array[] = [];\n for (const variant of enumVariants) {\n const bytes = hexaStringToBuffer(variant.descriptor.data);\n if (bytes) tlvs.push(bytes);\n }\n return buildEnumCache(tlvs).caseOf({\n Left: () => EMPTY_ENUM_CACHE,\n Right: (cache) => cache,\n });\n }\n\n private toRequirementAccounts(\n message: NormalizedMessage,\n accountKeyIndexes: number[],\n ): RequirementAccount[] {\n return accountKeyIndexes.map((keyIdx) => {\n const altRef = message.addressLookupRefs?.[keyIdx];\n if (altRef) {\n return {\n altRef: {\n altAddress: altRef.altAddress.toBase58(),\n entryIndex: altRef.entryIndex,\n },\n };\n }\n return { address: message.allKeys[keyIdx]?.toBase58() };\n });\n }\n}\n"],
5
- "mappings": "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",
6
- "names": ["BuildGenericClearSignContextTask_exports", "__export", "BuildGenericClearSignContextTask", "COMPUTE_BUDGET_PROGRAM_ID", "DEFAULT_NETWORK", "__toCommonJS", "import_context_module", "import_device_management_kit", "import_idl_type_pool", "import_requirements", "import_TransactionParser", "EMPTY_ENUM_CACHE", "args", "none", "parsed", "message", "remaining", "ix", "programId", "distinctProgramIds", "r", "infoContexts", "byProgram", "context", "list", "matched", "templateByKey", "unrecognized", "candidate", "payload", "descriptor", "instructionInfoContexts", "mode", "requirementsResult", "requirements", "poolContexts", "tokenAmountFallbackAccounts", "ref", "tokenInfoContexts", "challengeBoundRequirements", "input", "type", "usable", "c", "keys", "out", "key", "variant", "v", "index", "discriminatorHex", "data", "disc", "i", "enumVariants", "tlvs", "bytes", "cache", "accountKeyIndexes", "keyIdx", "altRef"]
4
+ "sourcesContent": ["import {\n type ClearSignContext,\n ClearSignContextType,\n type ContextModule,\n type SolanaInstructionInfoPayload,\n} from \"@ledgerhq/context-module\";\nimport {\n type DeviceModelId,\n hexaStringToBuffer,\n type LoggerPublisherService,\n} from \"@ledgerhq/device-management-kit\";\n\nimport { type ClearSignMode } from \"@api/app-binder/SignTransactionDeviceActionTypes\";\nimport {\n buildEnumCache,\n type VariantCache,\n} from \"@internal/app-binder/clear-sign/idl-type-pool\";\nimport {\n type AltEntryKey,\n buildRequirements,\n type BuildRequirementsOptions,\n type DescriptorRequirements,\n type InstructionDescriptor,\n type MatchedInstruction,\n type RequirementAccount,\n} from \"@internal/app-binder/clear-sign/requirements\";\nimport { type NormalizedMessage } from \"@internal/app-binder/services/TransactionInspector\";\nimport { TransactionParser } from \"@internal/app-binder/services/utils/TransactionParser\";\n\n/**\n * ComputeBudget program \u2014 a hardcoded allow-list skip. It has no CAL descriptor\n * and is understood natively by the device: never looked up, never counted,\n * never streamed. `setComputeUnitPrice` (priority fee) is a ComputeBudget\n * instruction so it is covered by the same skip.\n */\nexport const COMPUTE_BUDGET_PROGRAM_ID =\n \"ComputeBudget111111111111111111111111111111\";\n\nexport const DEFAULT_NETWORK = \"solana-mainnet\";\nconst EMPTY_ENUM_CACHE: VariantCache = new Map();\n\n/** Challenge-bound requirements, fetched one at a time in the provide phase. */\nexport type ChallengeBoundRequirements = Pick<\n DescriptorRequirements,\n \"tokenAccountStates\" | \"altResolutions\" | \"trustedNames\"\n> & {\n /** ALT-backed PARAM_TOKEN_AMOUNT.TOKEN refs needing TOKEN_INFO-first resolution. */\n tokenAmountAltRefs: AltEntryKey[];\n /** ALT-backed MINT entries from MINT_ASSOCIATIONS; require TOKEN_INFO via hold-and-conditionally-stream. */\n mintAltRefs: AltEntryKey[];\n};\n\n/**\n * Everything the device needs to clear-sign a transaction, gathered host-side.\n * The non-challenge-bound descriptors are pre-fetched here; the challenge-bound\n * ones are carried as requirements and fetched+streamed by the provide phase.\n */\nexport type GenericClearSignContext = {\n /** `full` (merge) / `srfc39-only` (partial) / `none` (legacy fallback). */\n readonly mode: ClearSignMode;\n /** Phase A pool descriptors that need no challenge (token-info, enum-variant). */\n readonly poolContexts: ClearSignContext[];\n /** Phase B templates: one SOLANA_INSTRUCTION_INFO per matched (programId, discriminator). */\n readonly instructionInfoContexts: ClearSignContext[];\n /** Challenge-bound Phase A requirements, fetched+streamed in the provide phase. */\n readonly challengeBoundRequirements: ChallengeBoundRequirements;\n};\n\nexport type BuildGenericClearSignContextTaskArgs = {\n readonly contextModule: ContextModule;\n readonly transaction: Uint8Array;\n readonly deviceModelId: DeviceModelId;\n readonly loggerFactory: (tag: string) => LoggerPublisherService;\n readonly network?: string;\n /** Enum-variant decoder override; defaults to the real type-pool decoder. */\n readonly selectEnumVariants?: BuildRequirementsOptions[\"selectEnumVariants\"];\n};\n\n/**\n * Groups the whole host-side preparation for generic clear-signing: parse the\n * TX (raw ALT refs preserved), skip ComputeBudget, look up CAL\n * `INSTRUCTION_INFO` per remaining program, match discriminators, build the\n * requirement set, and pre-fetch the non-challenge-bound satellite descriptors.\n * Challenge-bound descriptors are NOT fetched here \u2014 each needs a fresh\n * `GET CHALLENGE` issued immediately before it is streamed, so they are carried\n * forward as requirements and resolved by the provide task.\n */\nexport class BuildGenericClearSignContextTask {\n private readonly logger: LoggerPublisherService;\n private readonly network: string;\n\n constructor(private readonly args: BuildGenericClearSignContextTaskArgs) {\n this.logger = args.loggerFactory(\"BuildGenericClearSignContextTask\");\n this.network = args.network ?? DEFAULT_NETWORK;\n }\n\n async run(): Promise<GenericClearSignContext> {\n const none: GenericClearSignContext = {\n mode: \"none\",\n poolContexts: [],\n instructionInfoContexts: [],\n challengeBoundRequirements: {\n tokenAccountStates: [],\n altResolutions: [],\n trustedNames: [],\n tokenAmountAltRefs: [],\n mintAltRefs: [],\n },\n };\n\n // --- Parse + CAL lookup + match (Stage 1) ---\n const parsed = await new TransactionParser(undefined, {\n preserveAltRefs: true,\n })\n .parse(this.args.transaction)\n .run();\n if (parsed.isLeft()) {\n this.logger.warn(\"[run] parse failed; falling back to legacy\", {\n data: { error: parsed.extract() },\n });\n return none;\n }\n const message = parsed.unsafeCoerce().message;\n\n const remaining = message.compiledInstructions\n .map((ix) => ({\n ix,\n programId: this.programIdOf(message, ix.programIdIndex),\n }))\n .filter(({ programId }) => programId !== COMPUTE_BUDGET_PROGRAM_ID);\n if (remaining.length === 0) return none;\n\n const distinctProgramIds = Array.from(\n new Set(remaining.map((r) => r.programId)),\n );\n const infoContexts = await this.args.contextModule.getContexts(\n {\n deviceModelId: this.args.deviceModelId,\n instructions: distinctProgramIds.map((programId) => ({ programId })),\n network: this.network,\n },\n [ClearSignContextType.SOLANA_INSTRUCTION_INFO],\n );\n\n const byProgram = new Map<\n string,\n { payload: SolanaInstructionInfoPayload; context: ClearSignContext }[]\n >();\n for (const context of infoContexts) {\n if (context.type !== ClearSignContextType.SOLANA_INSTRUCTION_INFO)\n continue;\n const list = byProgram.get(context.payload.programId) ?? [];\n list.push({ payload: context.payload, context });\n byProgram.set(context.payload.programId, list);\n }\n\n const matched: MatchedInstruction[] = [];\n const templateByKey = new Map<string, ClearSignContext>();\n let unrecognized = 0;\n for (const { ix, programId } of remaining) {\n // Prefer the most specific match: a discriminator-less descriptor\n // matches any data of its program, so it must not shadow a descriptor\n // that pins actual leading bytes.\n const candidate = (byProgram.get(programId) ?? [])\n .filter(({ payload }) =>\n this.discriminatorMatches(payload.discriminator, ix.data),\n )\n .sort(\n (a, b) =>\n b.payload.discriminator.length - a.payload.discriminator.length,\n )[0];\n const descriptor = candidate\n ? this.toInstructionDescriptor(candidate.payload)\n : null;\n if (!candidate || !descriptor) {\n unrecognized += 1;\n continue;\n }\n matched.push({\n instruction: {\n programId,\n accounts: this.toRequirementAccounts(message, ix.accountKeyIndexes),\n data: ix.data,\n },\n descriptor,\n });\n templateByKey.set(\n `${programId}:${candidate.payload.discriminator}`,\n candidate.context,\n );\n }\n if (matched.length === 0) return none;\n\n const instructionInfoContexts = Array.from(templateByKey.values());\n\n // The device requires every non-ComputeBudget instruction to have a\n // template at FINALIZE (cs_transaction_finalize walks all instructions).\n // Any unrecognized instruction guarantees 6d20 so cs_transaction_reset() and\n // basic sign to 6808 (blind signing disabled). Bail out early so basic sign\n // starts from a clean device state.\n if (unrecognized > 0) {\n this.logger.warn(\n \"[run] transaction has unrecognized instructions; falling back to legacy\",\n { data: { unrecognized, recognized: matched.length } },\n );\n return none;\n }\n const mode: ClearSignMode = \"full\";\n\n // --- Requirements (Stage 2) ---\n const requirementsResult = buildRequirements(matched, {\n selectEnumVariants: this.args.selectEnumVariants,\n });\n if (requirementsResult.isLeft()) {\n this.logger.warn(\"[run] requirement build failed; falling back\", {\n data: { error: requirementsResult.extract() },\n });\n return none;\n }\n const requirements = requirementsResult.unsafeCoerce();\n\n // --- Fetch non-challenge-bound satellites (Stage 3) ---\n const poolContexts: ClearSignContext[] = [];\n if (requirements.tokenInfos.length > 0) {\n poolContexts.push(\n ...(await this.getContextsByType(\n {\n deviceModelId: this.args.deviceModelId,\n mints: requirements.tokenInfos,\n network: this.network,\n },\n ClearSignContextType.SOLANA_TOKEN_INFO,\n )),\n );\n }\n poolContexts.push(\n ...this.selectedEnumVariants(\n requirements.enumVariants,\n instructionInfoContexts,\n ),\n );\n\n // PARAM_TOKEN_AMOUNT.TOKEN refs: try TOKEN_INFO first (optimistic mint).\n // If that fails, fall back to TOKEN_ACCOUNT_STATE (it's an ATA).\n const tokenAmountFallbackAccounts: string[] = [];\n for (const ref of requirements.tokenAmountRefs) {\n const tokenInfoContexts = await this.getContextsByType(\n {\n deviceModelId: this.args.deviceModelId,\n mints: [ref],\n network: this.network,\n },\n ClearSignContextType.SOLANA_TOKEN_INFO,\n );\n if (tokenInfoContexts.length > 0) {\n poolContexts.push(...tokenInfoContexts);\n } else {\n tokenAmountFallbackAccounts.push(ref);\n }\n }\n\n // RequirementAccumulator.build() already strips tokenAmountAltRefs and\n // mintAltRefs entries from altResolutions (cross-bucket priority dedup),\n // so requirements.altResolutions is safe to use directly here.\n const challengeBoundRequirements: ChallengeBoundRequirements = {\n tokenAccountStates: [\n ...requirements.tokenAccountStates,\n ...tokenAmountFallbackAccounts,\n ],\n altResolutions: requirements.altResolutions,\n trustedNames: requirements.trustedNames,\n tokenAmountAltRefs: requirements.tokenAmountAltRefs,\n mintAltRefs: requirements.mintAltRefs,\n };\n\n this.logger.debug(\"[run] built clear-sign context\", {\n data: {\n mode,\n templates: instructionInfoContexts.length,\n pool: poolContexts.length,\n challengeBound:\n challengeBoundRequirements.tokenAccountStates.length +\n challengeBoundRequirements.altResolutions.length +\n challengeBoundRequirements.trustedNames.length +\n challengeBoundRequirements.tokenAmountAltRefs.length +\n challengeBoundRequirements.mintAltRefs.length,\n },\n });\n\n return {\n mode,\n poolContexts,\n instructionInfoContexts,\n challengeBoundRequirements,\n };\n }\n\n /** Fetch contexts of `type`; ERROR / wrong-type contexts are dropped (satellites degrade). */\n private async getContextsByType<TInput>(\n input: TInput,\n type: ClearSignContextType,\n ): Promise<ClearSignContext[]> {\n const contexts = await this.args.contextModule.getContexts(input, [type]);\n const usable = contexts.filter((c) => c.type === type);\n if (usable.length === 0) {\n this.logger.warn(\n \"[run] satellite fetch yielded no descriptor (degraded)\",\n {\n data: { type },\n },\n );\n }\n return usable;\n }\n\n /** Build SOLANA_ENUM_VARIANT contexts for the selected variants from the bundled payloads. */\n private selectedEnumVariants(\n keys: readonly {\n programId: string;\n enumId: string;\n variantIndex: number;\n }[],\n instructionInfoContexts: ClearSignContext[],\n ): ClearSignContext[] {\n const out: ClearSignContext[] = [];\n for (const key of keys) {\n for (const context of instructionInfoContexts) {\n if (context.type !== ClearSignContextType.SOLANA_INSTRUCTION_INFO)\n continue;\n if (context.payload.programId !== key.programId) continue;\n const variant = context.payload.enumVariants.find(\n (v) => v.enumId === key.enumId && v.variantIndex === key.variantIndex,\n );\n if (variant) {\n out.push({\n type: ClearSignContextType.SOLANA_ENUM_VARIANT,\n payload: {\n programId: key.programId,\n enumId: key.enumId,\n variantIndex: key.variantIndex,\n descriptor: variant.descriptor,\n },\n certificate: context.certificate,\n });\n break;\n }\n }\n }\n return out;\n }\n\n private programIdOf(message: NormalizedMessage, index: number): string {\n return message.allKeys[index]?.toBase58() ?? \"\";\n }\n\n private discriminatorMatches(\n discriminatorHex: string,\n data: Uint8Array,\n ): boolean {\n // Single-instruction programs (e.g. SPL Memo) carry no discriminator: the\n // instruction data is all arguments, so the descriptor matches any data.\n if (discriminatorHex === \"\") return true;\n const disc = hexaStringToBuffer(discriminatorHex);\n if (!disc || disc.length === 0 || data.length < disc.length) return false;\n for (let i = 0; i < disc.length; i++) {\n if (data[i] !== disc[i]) return false;\n }\n return true;\n }\n\n private toInstructionDescriptor(\n payload: SolanaInstructionInfoPayload,\n ): InstructionDescriptor {\n return {\n discriminator: payload.discriminator,\n idlDescriptor: {\n type_pool: payload.idlDescriptor.typePool,\n root_type: payload.idlDescriptor.rootType,\n },\n mintAssociations: payload.mintAssociations,\n valueFlowPorts: payload.valueFlowPorts,\n accountResets: payload.accountResets,\n displayFields: payload.displayFields,\n enumCache: this.toEnumCache(payload.enumVariants),\n };\n }\n\n private toEnumCache(\n enumVariants: SolanaInstructionInfoPayload[\"enumVariants\"],\n ): VariantCache {\n if (enumVariants.length === 0) return EMPTY_ENUM_CACHE;\n const tlvs: Uint8Array[] = [];\n for (const variant of enumVariants) {\n const bytes = hexaStringToBuffer(variant.descriptor.data);\n if (bytes) tlvs.push(bytes);\n }\n return buildEnumCache(tlvs).caseOf({\n Left: () => EMPTY_ENUM_CACHE,\n Right: (cache) => cache,\n });\n }\n\n private toRequirementAccounts(\n message: NormalizedMessage,\n accountKeyIndexes: number[],\n ): RequirementAccount[] {\n return accountKeyIndexes.map((keyIdx) => {\n const altRef = message.addressLookupRefs?.[keyIdx];\n if (altRef) {\n return {\n altRef: {\n altAddress: altRef.altAddress.toBase58(),\n entryIndex: altRef.entryIndex,\n },\n };\n }\n return { address: message.allKeys[keyIdx]?.toBase58() };\n });\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["BuildGenericClearSignContextTask_exports", "__export", "BuildGenericClearSignContextTask", "COMPUTE_BUDGET_PROGRAM_ID", "DEFAULT_NETWORK", "__toCommonJS", "import_context_module", "import_device_management_kit", "import_idl_type_pool", "import_requirements", "import_TransactionParser", "EMPTY_ENUM_CACHE", "args", "none", "parsed", "message", "remaining", "ix", "programId", "distinctProgramIds", "r", "infoContexts", "byProgram", "context", "list", "matched", "templateByKey", "unrecognized", "candidate", "payload", "a", "b", "descriptor", "instructionInfoContexts", "mode", "requirementsResult", "requirements", "poolContexts", "tokenAmountFallbackAccounts", "ref", "tokenInfoContexts", "challengeBoundRequirements", "input", "type", "usable", "c", "keys", "out", "key", "variant", "v", "index", "discriminatorHex", "data", "disc", "i", "enumVariants", "tlvs", "bytes", "cache", "accountKeyIndexes", "keyIdx", "altRef"]
7
7
  }
@@ -1,2 +1,2 @@
1
- "use strict";var x=require("@ledgerhq/context-module"),C=require("@ledgerhq/device-management-kit"),r=require("@solana/web3.js"),f=require("buffer"),g=require("purify-ts"),n=require("vitest"),y=require("../../app-binder/services/bs58Encoder"),i=require("./BuildGenericClearSignContextTask");const I=y.DefaultBs58Encoder.encode(new Uint8Array(32).fill(170)),a=new r.PublicKey("9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin"),d=new r.PublicKey("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr"),T="0001",w={typePool:[{index:0,kind:"STRUCT",refs:[]}],rootType:0};function s(e,t){return new r.TransactionInstruction({keys:[{pubkey:r.Keypair.generate().publicKey,isSigner:!1,isWritable:!0}],programId:e,data:f.Buffer.from(t)})}function u(e){const t=r.Keypair.generate(),o=new r.Transaction;return o.recentBlockhash=I,o.feePayer=t.publicKey,o.add(...e),o.sign(t),o.serialize()}function m(e,t){return{type:x.ClearSignContextType.SOLANA_INSTRUCTION_INFO,payload:{programId:e,discriminator:t,instructionInfo:{data:T,signature:"00"},substructures:[],enumVariants:[],idlDescriptor:w,mintAssociations:[],valueFlowPorts:[],accountResets:[],displayFields:[]}}}function l(e,t){const o=n.vi.fn(async(k,p)=>p.includes(x.ClearSignContextType.SOLANA_INSTRUCTION_INFO)?t:[]),c={getContexts:o};return{task:new i.BuildGenericClearSignContextTask({contextModule:c,transaction:e,deviceModelId:C.DeviceModelId.STAX,loggerFactory:()=>({debug:n.vi.fn(),info:n.vi.fn(),warn:n.vi.fn(),error:n.vi.fn()}),selectEnumVariants:()=>(0,g.Right)([])}),getContexts:o}}(0,n.describe)("BuildGenericClearSignContextTask",()=>{(0,n.it)("returns mode `full` and a template when every non-ComputeBudget instruction is recognized",async()=>{const e=u([s(new r.PublicKey(i.COMPUTE_BUDGET_PROGRAM_ID),[2,64,66]),s(a,[1,2,170])]),{task:t,getContexts:o}=l(e,[m(a.toBase58(),"0102")]),c=await t.run();(0,n.expect)(c.mode).toBe("full"),(0,n.expect)(c.instructionInfoContexts).toHaveLength(1),(0,n.expect)(o).toHaveBeenCalledWith(n.expect.objectContaining({instructions:[{programId:a.toBase58()}]}),[x.ClearSignContextType.SOLANA_INSTRUCTION_INFO])}),(0,n.it)("returns mode `none` when some instructions are unrecognized",async()=>{const e=u([s(a,[1,2]),s(d,[9])]),{task:t}=l(e,[m(a.toBase58(),"0102")]),o=await t.run();(0,n.expect)(o.mode).toBe("none"),(0,n.expect)(o.instructionInfoContexts).toHaveLength(0)}),(0,n.it)("returns mode `none` when nothing is recognized",async()=>{const e=u([s(d,[9])]),{task:t}=l(e,[]);(0,n.expect)((await t.run()).mode).toBe("none")}),(0,n.it)("returns mode `none` for a ComputeBudget-only tx without calling CAL",async()=>{const e=u([s(new r.PublicKey(i.COMPUTE_BUDGET_PROGRAM_ID),[2,64,66])]),{task:t,getContexts:o}=l(e,[]);(0,n.expect)((await t.run()).mode).toBe("none"),(0,n.expect)(o).not.toHaveBeenCalled()})});
1
+ "use strict";var d=require("@ledgerhq/context-module"),f=require("@ledgerhq/device-management-kit"),s=require("@solana/web3.js"),C=require("buffer"),g=require("purify-ts"),t=require("vitest"),y=require("../../app-binder/services/bs58Encoder"),l=require("./BuildGenericClearSignContextTask");const I=y.DefaultBs58Encoder.encode(new Uint8Array(32).fill(170)),a=new s.PublicKey("9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin"),m=new s.PublicKey("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr"),w="0001",B={typePool:[{index:0,kind:"STRUCT",refs:[]}],rootType:0};function r(o,e){return new s.TransactionInstruction({keys:[{pubkey:s.Keypair.generate().publicKey,isSigner:!1,isWritable:!0}],programId:o,data:C.Buffer.from(e)})}function i(o){const e=s.Keypair.generate(),n=new s.Transaction;return n.recentBlockhash=I,n.feePayer=e.publicKey,n.add(...o),n.sign(e),n.serialize()}function c(o,e,n=w){return{type:d.ClearSignContextType.SOLANA_INSTRUCTION_INFO,payload:{programId:o,discriminator:e,instructionInfo:{data:n,signature:"00"},substructures:[],enumVariants:[],idlDescriptor:B,mintAssociations:[],valueFlowPorts:[],accountResets:[],displayFields:[]}}}function u(o,e){const n=t.vi.fn(async(b,p)=>p.includes(d.ClearSignContextType.SOLANA_INSTRUCTION_INFO)?e:[]),x={getContexts:n};return{task:new l.BuildGenericClearSignContextTask({contextModule:x,transaction:o,deviceModelId:f.DeviceModelId.STAX,loggerFactory:()=>({debug:t.vi.fn(),info:t.vi.fn(),warn:t.vi.fn(),error:t.vi.fn()}),selectEnumVariants:()=>(0,g.Right)([])}),getContexts:n}}(0,t.describe)("BuildGenericClearSignContextTask",()=>{(0,t.it)("returns mode `full` and a template when every non-ComputeBudget instruction is recognized",async()=>{const o=i([r(new s.PublicKey(l.COMPUTE_BUDGET_PROGRAM_ID),[2,64,66]),r(a,[1,2,170])]),{task:e,getContexts:n}=u(o,[c(a.toBase58(),"0102")]),x=await e.run();(0,t.expect)(x.mode).toBe("full"),(0,t.expect)(x.instructionInfoContexts).toHaveLength(1),(0,t.expect)(n).toHaveBeenCalledWith(t.expect.objectContaining({instructions:[{programId:a.toBase58()}]}),[d.ClearSignContextType.SOLANA_INSTRUCTION_INFO])}),(0,t.it)("matches a descriptor without a discriminator against any instruction data",async()=>{const o=i([r(a,[104,105])]),{task:e}=u(o,[c(a.toBase58(),"")]),n=await e.run();(0,t.expect)(n.mode).toBe("full"),(0,t.expect)(n.instructionInfoContexts).toHaveLength(1)}),(0,t.it)("prefers the most specific descriptor over a discriminator-less one",async()=>{const o=i([r(a,[1,2,170])]),{task:e}=u(o,[c(a.toBase58(),"","aaaa"),c(a.toBase58(),"0102","bbbb")]),n=await e.run();(0,t.expect)(n.mode).toBe("full"),(0,t.expect)(n.instructionInfoContexts).toEqual([c(a.toBase58(),"0102","bbbb")])}),(0,t.it)("returns mode `none` when some instructions are unrecognized",async()=>{const o=i([r(a,[1,2]),r(m,[9])]),{task:e}=u(o,[c(a.toBase58(),"0102")]),n=await e.run();(0,t.expect)(n.mode).toBe("none"),(0,t.expect)(n.instructionInfoContexts).toHaveLength(0)}),(0,t.it)("returns mode `none` when nothing is recognized",async()=>{const o=i([r(m,[9])]),{task:e}=u(o,[]);(0,t.expect)((await e.run()).mode).toBe("none")}),(0,t.it)("returns mode `none` for a ComputeBudget-only tx without calling CAL",async()=>{const o=i([r(new s.PublicKey(l.COMPUTE_BUDGET_PROGRAM_ID),[2,64,66])]),{task:e,getContexts:n}=u(o,[]);(0,t.expect)((await e.run()).mode).toBe("none"),(0,t.expect)(n).not.toHaveBeenCalled()})});
2
2
  //# sourceMappingURL=BuildGenericClearSignContextTask.test.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/internal/app-binder/task/BuildGenericClearSignContextTask.test.ts"],
4
- "sourcesContent": ["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {\n type ClearSignContext,\n ClearSignContextType,\n type ContextModule,\n} from \"@ledgerhq/context-module\";\nimport { DeviceModelId } from \"@ledgerhq/device-management-kit\";\nimport {\n Keypair,\n PublicKey,\n Transaction,\n TransactionInstruction,\n} from \"@solana/web3.js\";\nimport { Buffer } from \"buffer\";\nimport { Right } from \"purify-ts\";\nimport { describe, expect, it, vi } from \"vitest\";\n\nimport { DefaultBs58Encoder } from \"@internal/app-binder/services/bs58Encoder\";\n\nimport {\n BuildGenericClearSignContextTask,\n COMPUTE_BUDGET_PROGRAM_ID,\n} from \"./BuildGenericClearSignContextTask\";\n\nconst DUMMY_BLOCKHASH = DefaultBs58Encoder.encode(\n new Uint8Array(32).fill(0xaa),\n);\nconst KNOWN_PROGRAM = new PublicKey(\n \"9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin\",\n);\nconst UNKNOWN_PROGRAM = new PublicKey(\n \"MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr\",\n);\n\n// Dummy signed TLV hex (streamed to the device; not parsed host-side).\nconst INFO_HEX = \"0001\";\n\n// Minimal-but-valid decoded type pool so buildRequirements returns Right.\nconst MIN_IDL_DESCRIPTOR = {\n typePool: [{ index: 0, kind: \"STRUCT\", refs: [] }],\n rootType: 0,\n};\n\nfunction makeIx(programId: PublicKey, data: number[]): TransactionInstruction {\n return new TransactionInstruction({\n keys: [\n {\n pubkey: Keypair.generate().publicKey,\n isSigner: false,\n isWritable: true,\n },\n ],\n programId,\n data: Buffer.from(data),\n });\n}\n\nfunction makeRawTx(ixs: TransactionInstruction[]): Uint8Array {\n const payer = Keypair.generate();\n const tx = new Transaction();\n tx.recentBlockhash = DUMMY_BLOCKHASH;\n tx.feePayer = payer.publicKey;\n tx.add(...ixs);\n tx.sign(payer);\n return tx.serialize();\n}\n\nfunction instructionInfoContext(\n programId: string,\n discriminator: string,\n): ClearSignContext {\n return {\n type: ClearSignContextType.SOLANA_INSTRUCTION_INFO,\n payload: {\n programId,\n discriminator,\n instructionInfo: { data: INFO_HEX, signature: \"00\" },\n substructures: [],\n enumVariants: [],\n idlDescriptor: MIN_IDL_DESCRIPTOR,\n mintAssociations: [],\n valueFlowPorts: [],\n accountResets: [],\n displayFields: [],\n },\n } as any;\n}\n\nfunction makeTask(transaction: Uint8Array, infoContexts: ClearSignContext[]) {\n const getContexts = vi.fn(async (_input: unknown, types: unknown) =>\n (types as ClearSignContextType[]).includes(\n ClearSignContextType.SOLANA_INSTRUCTION_INFO,\n )\n ? infoContexts\n : [],\n );\n const contextModule = { getContexts } as unknown as ContextModule;\n const task = new BuildGenericClearSignContextTask({\n contextModule,\n transaction,\n deviceModelId: DeviceModelId.STAX,\n loggerFactory: () =>\n ({\n debug: vi.fn(),\n info: vi.fn(),\n warn: vi.fn(),\n error: vi.fn(),\n }) as any,\n // Stub the enum decoder (the minimal fixture pool isn't real-decodable).\n selectEnumVariants: () => Right([]),\n });\n return { task, getContexts };\n}\n\ndescribe(\"BuildGenericClearSignContextTask\", () => {\n it(\"returns mode `full` and a template when every non-ComputeBudget instruction is recognized\", async () => {\n const tx = makeRawTx([\n makeIx(new PublicKey(COMPUTE_BUDGET_PROGRAM_ID), [0x02, 0x40, 0x42]),\n makeIx(KNOWN_PROGRAM, [0x01, 0x02, 0xaa]),\n ]);\n const { task, getContexts } = makeTask(tx, [\n instructionInfoContext(KNOWN_PROGRAM.toBase58(), \"0102\"),\n ]);\n\n const result = await task.run();\n\n expect(result.mode).toBe(\"full\");\n expect(result.instructionInfoContexts).toHaveLength(1);\n // ComputeBudget is never looked up in CAL.\n expect(getContexts).toHaveBeenCalledWith(\n expect.objectContaining({\n instructions: [{ programId: KNOWN_PROGRAM.toBase58() }],\n }),\n [ClearSignContextType.SOLANA_INSTRUCTION_INFO],\n );\n });\n\n it(\"returns mode `none` when some instructions are unrecognized\", async () => {\n // Any unrecognized instruction causes FINALIZE to fail on the device\n // (cs_transaction_finalize walks all instructions), so we bail to legacy\n // basic sign from a clean state rather than attempting generic clear-signing.\n const tx = makeRawTx([\n makeIx(KNOWN_PROGRAM, [0x01, 0x02]),\n makeIx(UNKNOWN_PROGRAM, [0x09]),\n ]);\n const { task } = makeTask(tx, [\n instructionInfoContext(KNOWN_PROGRAM.toBase58(), \"0102\"),\n ]);\n\n const result = await task.run();\n\n expect(result.mode).toBe(\"none\");\n expect(result.instructionInfoContexts).toHaveLength(0);\n });\n\n it(\"returns mode `none` when nothing is recognized\", async () => {\n const tx = makeRawTx([makeIx(UNKNOWN_PROGRAM, [0x09])]);\n const { task } = makeTask(tx, []);\n\n expect((await task.run()).mode).toBe(\"none\");\n });\n\n it(\"returns mode `none` for a ComputeBudget-only tx without calling CAL\", async () => {\n const tx = makeRawTx([\n makeIx(new PublicKey(COMPUTE_BUDGET_PROGRAM_ID), [0x02, 0x40, 0x42]),\n ]);\n const { task, getContexts } = makeTask(tx, []);\n\n expect((await task.run()).mode).toBe(\"none\");\n expect(getContexts).not.toHaveBeenCalled();\n });\n});\n"],
5
- "mappings": "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",
6
- "names": ["import_context_module", "import_device_management_kit", "import_web3", "import_buffer", "import_purify_ts", "import_vitest", "import_bs58Encoder", "import_BuildGenericClearSignContextTask", "DUMMY_BLOCKHASH", "KNOWN_PROGRAM", "UNKNOWN_PROGRAM", "INFO_HEX", "MIN_IDL_DESCRIPTOR", "makeIx", "programId", "data", "makeRawTx", "ixs", "payer", "tx", "instructionInfoContext", "discriminator", "makeTask", "transaction", "infoContexts", "getContexts", "_input", "types", "contextModule", "task", "result"]
4
+ "sourcesContent": ["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {\n type ClearSignContext,\n ClearSignContextType,\n type ContextModule,\n} from \"@ledgerhq/context-module\";\nimport { DeviceModelId } from \"@ledgerhq/device-management-kit\";\nimport {\n Keypair,\n PublicKey,\n Transaction,\n TransactionInstruction,\n} from \"@solana/web3.js\";\nimport { Buffer } from \"buffer\";\nimport { Right } from \"purify-ts\";\nimport { describe, expect, it, vi } from \"vitest\";\n\nimport { DefaultBs58Encoder } from \"@internal/app-binder/services/bs58Encoder\";\n\nimport {\n BuildGenericClearSignContextTask,\n COMPUTE_BUDGET_PROGRAM_ID,\n} from \"./BuildGenericClearSignContextTask\";\n\nconst DUMMY_BLOCKHASH = DefaultBs58Encoder.encode(\n new Uint8Array(32).fill(0xaa),\n);\nconst KNOWN_PROGRAM = new PublicKey(\n \"9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin\",\n);\nconst UNKNOWN_PROGRAM = new PublicKey(\n \"MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr\",\n);\n\n// Dummy signed TLV hex (streamed to the device; not parsed host-side).\nconst INFO_HEX = \"0001\";\n\n// Minimal-but-valid decoded type pool so buildRequirements returns Right.\nconst MIN_IDL_DESCRIPTOR = {\n typePool: [{ index: 0, kind: \"STRUCT\", refs: [] }],\n rootType: 0,\n};\n\nfunction makeIx(programId: PublicKey, data: number[]): TransactionInstruction {\n return new TransactionInstruction({\n keys: [\n {\n pubkey: Keypair.generate().publicKey,\n isSigner: false,\n isWritable: true,\n },\n ],\n programId,\n data: Buffer.from(data),\n });\n}\n\nfunction makeRawTx(ixs: TransactionInstruction[]): Uint8Array {\n const payer = Keypair.generate();\n const tx = new Transaction();\n tx.recentBlockhash = DUMMY_BLOCKHASH;\n tx.feePayer = payer.publicKey;\n tx.add(...ixs);\n tx.sign(payer);\n return tx.serialize();\n}\n\nfunction instructionInfoContext(\n programId: string,\n discriminator: string,\n infoHex: string = INFO_HEX,\n): ClearSignContext {\n return {\n type: ClearSignContextType.SOLANA_INSTRUCTION_INFO,\n payload: {\n programId,\n discriminator,\n instructionInfo: { data: infoHex, signature: \"00\" },\n substructures: [],\n enumVariants: [],\n idlDescriptor: MIN_IDL_DESCRIPTOR,\n mintAssociations: [],\n valueFlowPorts: [],\n accountResets: [],\n displayFields: [],\n },\n } as any;\n}\n\nfunction makeTask(transaction: Uint8Array, infoContexts: ClearSignContext[]) {\n const getContexts = vi.fn(async (_input: unknown, types: unknown) =>\n (types as ClearSignContextType[]).includes(\n ClearSignContextType.SOLANA_INSTRUCTION_INFO,\n )\n ? infoContexts\n : [],\n );\n const contextModule = { getContexts } as unknown as ContextModule;\n const task = new BuildGenericClearSignContextTask({\n contextModule,\n transaction,\n deviceModelId: DeviceModelId.STAX,\n loggerFactory: () =>\n ({\n debug: vi.fn(),\n info: vi.fn(),\n warn: vi.fn(),\n error: vi.fn(),\n }) as any,\n // Stub the enum decoder (the minimal fixture pool isn't real-decodable).\n selectEnumVariants: () => Right([]),\n });\n return { task, getContexts };\n}\n\ndescribe(\"BuildGenericClearSignContextTask\", () => {\n it(\"returns mode `full` and a template when every non-ComputeBudget instruction is recognized\", async () => {\n const tx = makeRawTx([\n makeIx(new PublicKey(COMPUTE_BUDGET_PROGRAM_ID), [0x02, 0x40, 0x42]),\n makeIx(KNOWN_PROGRAM, [0x01, 0x02, 0xaa]),\n ]);\n const { task, getContexts } = makeTask(tx, [\n instructionInfoContext(KNOWN_PROGRAM.toBase58(), \"0102\"),\n ]);\n\n const result = await task.run();\n\n expect(result.mode).toBe(\"full\");\n expect(result.instructionInfoContexts).toHaveLength(1);\n // ComputeBudget is never looked up in CAL.\n expect(getContexts).toHaveBeenCalledWith(\n expect.objectContaining({\n instructions: [{ programId: KNOWN_PROGRAM.toBase58() }],\n }),\n [ClearSignContextType.SOLANA_INSTRUCTION_INFO],\n );\n });\n\n it(\"matches a descriptor without a discriminator against any instruction data\", async () => {\n // Single-instruction programs (e.g. SPL Memo `addMemo`) have no\n // discriminator: CAL omits `discriminator_hex` and the whole instruction\n // data is arguments.\n const tx = makeRawTx([makeIx(KNOWN_PROGRAM, [0x68, 0x69])]);\n const { task } = makeTask(tx, [\n instructionInfoContext(KNOWN_PROGRAM.toBase58(), \"\"),\n ]);\n\n const result = await task.run();\n\n expect(result.mode).toBe(\"full\");\n expect(result.instructionInfoContexts).toHaveLength(1);\n });\n\n it(\"prefers the most specific descriptor over a discriminator-less one\", async () => {\n const tx = makeRawTx([makeIx(KNOWN_PROGRAM, [0x01, 0x02, 0xaa])]);\n const { task } = makeTask(tx, [\n instructionInfoContext(KNOWN_PROGRAM.toBase58(), \"\", \"aaaa\"),\n instructionInfoContext(KNOWN_PROGRAM.toBase58(), \"0102\", \"bbbb\"),\n ]);\n\n const result = await task.run();\n\n expect(result.mode).toBe(\"full\");\n expect(result.instructionInfoContexts).toEqual([\n instructionInfoContext(KNOWN_PROGRAM.toBase58(), \"0102\", \"bbbb\"),\n ]);\n });\n\n it(\"returns mode `none` when some instructions are unrecognized\", async () => {\n // Any unrecognized instruction causes FINALIZE to fail on the device\n // (cs_transaction_finalize walks all instructions), so we bail to legacy\n // basic sign from a clean state rather than attempting generic clear-signing.\n const tx = makeRawTx([\n makeIx(KNOWN_PROGRAM, [0x01, 0x02]),\n makeIx(UNKNOWN_PROGRAM, [0x09]),\n ]);\n const { task } = makeTask(tx, [\n instructionInfoContext(KNOWN_PROGRAM.toBase58(), \"0102\"),\n ]);\n\n const result = await task.run();\n\n expect(result.mode).toBe(\"none\");\n expect(result.instructionInfoContexts).toHaveLength(0);\n });\n\n it(\"returns mode `none` when nothing is recognized\", async () => {\n const tx = makeRawTx([makeIx(UNKNOWN_PROGRAM, [0x09])]);\n const { task } = makeTask(tx, []);\n\n expect((await task.run()).mode).toBe(\"none\");\n });\n\n it(\"returns mode `none` for a ComputeBudget-only tx without calling CAL\", async () => {\n const tx = makeRawTx([\n makeIx(new PublicKey(COMPUTE_BUDGET_PROGRAM_ID), [0x02, 0x40, 0x42]),\n ]);\n const { task, getContexts } = makeTask(tx, []);\n\n expect((await task.run()).mode).toBe(\"none\");\n expect(getContexts).not.toHaveBeenCalled();\n });\n});\n"],
5
+ "mappings": "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",
6
+ "names": ["import_context_module", "import_device_management_kit", "import_web3", "import_buffer", "import_purify_ts", "import_vitest", "import_bs58Encoder", "import_BuildGenericClearSignContextTask", "DUMMY_BLOCKHASH", "KNOWN_PROGRAM", "UNKNOWN_PROGRAM", "INFO_HEX", "MIN_IDL_DESCRIPTOR", "makeIx", "programId", "data", "makeRawTx", "ixs", "payer", "tx", "instructionInfoContext", "discriminator", "infoHex", "makeTask", "transaction", "infoContexts", "getContexts", "_input", "types", "contextModule", "task", "result"]
7
7
  }
@@ -63,5 +63,5 @@
63
63
  "watch:builds": "pnpm ldmk-tool watch --entryPoints src/index.ts,src/**/*.ts --tsconfig tsconfig.prod.json",
64
64
  "watch:types": "concurrently \"tsc --watch -p tsconfig.prod.json\" \"tsc-alias --watch -p tsconfig.prod.json\""
65
65
  },
66
- "version": "0.0.0-develop-20260811001235"
66
+ "version": "0.0.0-develop-20260813001639"
67
67
  }
@@ -1,2 +1,2 @@
1
- import{ClearSignContextType as u}from"@ledgerhq/context-module";import{hexaStringToBuffer as R}from"@ledgerhq/device-management-kit";import{buildEnumCache as v}from"../../app-binder/clear-sign/idl-type-pool";import{buildRequirements as M}from"../../app-binder/clear-sign/requirements";import{TransactionParser as N}from"../../app-binder/services/utils/TransactionParser";const T="ComputeBudget111111111111111111111111111111",w="solana-mainnet",S=new Map;class q{constructor(e){this.args=e;this.logger=e.loggerFactory("BuildGenericClearSignContextTask"),this.network=e.network??w}logger;network;async run(){const e={mode:"none",poolContexts:[],instructionInfoContexts:[],challengeBoundRequirements:{tokenAccountStates:[],altResolutions:[],trustedNames:[],tokenAmountAltRefs:[],mintAltRefs:[]}},o=await new N(void 0,{preserveAltRefs:!0}).parse(this.args.transaction).run();if(o.isLeft())return this.logger.warn("[run] parse failed; falling back to legacy",{data:{error:o.extract()}}),e;const r=o.unsafeCoerce().message,t=r.compiledInstructions.map(n=>({ix:n,programId:this.programIdOf(r,n.programIdIndex)})).filter(({programId:n})=>n!==T);if(t.length===0)return e;const a=Array.from(new Set(t.map(n=>n.programId))),m=await this.args.contextModule.getContexts({deviceModelId:this.args.deviceModelId,instructions:a.map(n=>({programId:n})),network:this.network},[u.SOLANA_INSTRUCTION_INFO]),l=new Map;for(const n of m){if(n.type!==u.SOLANA_INSTRUCTION_INFO)continue;const i=l.get(n.payload.programId)??[];i.push({payload:n.payload,context:n}),l.set(n.payload.programId,i)}const p=[],C=new Map;let f=0;for(const{ix:n,programId:i}of t){const g=(l.get(i)??[]).find(({payload:k})=>this.discriminatorMatches(k.discriminator,n.data)),A=g?this.toInstructionDescriptor(g.payload):null;if(!g||!A){f+=1;continue}p.push({instruction:{programId:i,accounts:this.toRequirementAccounts(r,n.accountKeyIndexes),data:n.data},descriptor:A}),C.set(`${i}:${g.payload.discriminator}`,g.context)}if(p.length===0)return e;const y=Array.from(C.values());if(f>0)return this.logger.warn("[run] transaction has unrecognized instructions; falling back to legacy",{data:{unrecognized:f,recognized:p.length}}),e;const I="full",h=M(p,{selectEnumVariants:this.args.selectEnumVariants});if(h.isLeft())return this.logger.warn("[run] requirement build failed; falling back",{data:{error:h.extract()}}),e;const s=h.unsafeCoerce(),d=[];s.tokenInfos.length>0&&d.push(...await this.getContextsByType({deviceModelId:this.args.deviceModelId,mints:s.tokenInfos,network:this.network},u.SOLANA_TOKEN_INFO)),d.push(...this.selectedEnumVariants(s.enumVariants,y));const x=[];for(const n of s.tokenAmountRefs){const i=await this.getContextsByType({deviceModelId:this.args.deviceModelId,mints:[n],network:this.network},u.SOLANA_TOKEN_INFO);i.length>0?d.push(...i):x.push(n)}const c={tokenAccountStates:[...s.tokenAccountStates,...x],altResolutions:s.altResolutions,trustedNames:s.trustedNames,tokenAmountAltRefs:s.tokenAmountAltRefs,mintAltRefs:s.mintAltRefs};return this.logger.debug("[run] built clear-sign context",{data:{mode:I,templates:y.length,pool:d.length,challengeBound:c.tokenAccountStates.length+c.altResolutions.length+c.trustedNames.length+c.tokenAmountAltRefs.length+c.mintAltRefs.length}}),{mode:I,poolContexts:d,instructionInfoContexts:y,challengeBoundRequirements:c}}async getContextsByType(e,o){const t=(await this.args.contextModule.getContexts(e,[o])).filter(a=>a.type===o);return t.length===0&&this.logger.warn("[run] satellite fetch yielded no descriptor (degraded)",{data:{type:o}}),t}selectedEnumVariants(e,o){const r=[];for(const t of e)for(const a of o){if(a.type!==u.SOLANA_INSTRUCTION_INFO||a.payload.programId!==t.programId)continue;const m=a.payload.enumVariants.find(l=>l.enumId===t.enumId&&l.variantIndex===t.variantIndex);if(m){r.push({type:u.SOLANA_ENUM_VARIANT,payload:{programId:t.programId,enumId:t.enumId,variantIndex:t.variantIndex,descriptor:m.descriptor},certificate:a.certificate});break}}return r}programIdOf(e,o){return e.allKeys[o]?.toBase58()??""}discriminatorMatches(e,o){const r=R(e);if(!r||r.length===0||o.length<r.length)return!1;for(let t=0;t<r.length;t++)if(o[t]!==r[t])return!1;return!0}toInstructionDescriptor(e){return{discriminator:e.discriminator,idlDescriptor:{type_pool:e.idlDescriptor.typePool,root_type:e.idlDescriptor.rootType},mintAssociations:e.mintAssociations,valueFlowPorts:e.valueFlowPorts,accountResets:e.accountResets,displayFields:e.displayFields,enumCache:this.toEnumCache(e.enumVariants)}}toEnumCache(e){if(e.length===0)return S;const o=[];for(const r of e){const t=R(r.descriptor.data);t&&o.push(t)}return v(o).caseOf({Left:()=>S,Right:r=>r})}toRequirementAccounts(e,o){return o.map(r=>{const t=e.addressLookupRefs?.[r];return t?{altRef:{altAddress:t.altAddress.toBase58(),entryIndex:t.entryIndex}}:{address:e.allKeys[r]?.toBase58()}})}}export{q as BuildGenericClearSignContextTask,T as COMPUTE_BUDGET_PROGRAM_ID,w as DEFAULT_NETWORK};
1
+ import{ClearSignContextType as u}from"@ledgerhq/context-module";import{hexaStringToBuffer as S}from"@ledgerhq/device-management-kit";import{buildEnumCache as M}from"../../app-binder/clear-sign/idl-type-pool";import{buildRequirements as N}from"../../app-binder/clear-sign/requirements";import{TransactionParser as T}from"../../app-binder/services/utils/TransactionParser";const w="ComputeBudget111111111111111111111111111111",O="solana-mainnet",k=new Map;class D{constructor(t){this.args=t;this.logger=t.loggerFactory("BuildGenericClearSignContextTask"),this.network=t.network??O}logger;network;async run(){const t={mode:"none",poolContexts:[],instructionInfoContexts:[],challengeBoundRequirements:{tokenAccountStates:[],altResolutions:[],trustedNames:[],tokenAmountAltRefs:[],mintAltRefs:[]}},o=await new T(void 0,{preserveAltRefs:!0}).parse(this.args.transaction).run();if(o.isLeft())return this.logger.warn("[run] parse failed; falling back to legacy",{data:{error:o.extract()}}),t;const r=o.unsafeCoerce().message,e=r.compiledInstructions.map(n=>({ix:n,programId:this.programIdOf(r,n.programIdIndex)})).filter(({programId:n})=>n!==w);if(e.length===0)return t;const a=Array.from(new Set(e.map(n=>n.programId))),m=await this.args.contextModule.getContexts({deviceModelId:this.args.deviceModelId,instructions:a.map(n=>({programId:n})),network:this.network},[u.SOLANA_INSTRUCTION_INFO]),l=new Map;for(const n of m){if(n.type!==u.SOLANA_INSTRUCTION_INFO)continue;const i=l.get(n.payload.programId)??[];i.push({payload:n.payload,context:n}),l.set(n.payload.programId,i)}const p=[],I=new Map;let f=0;for(const{ix:n,programId:i}of e){const g=(l.get(i)??[]).filter(({payload:C})=>this.discriminatorMatches(C.discriminator,n.data)).sort((C,v)=>v.payload.discriminator.length-C.payload.discriminator.length)[0],R=g?this.toInstructionDescriptor(g.payload):null;if(!g||!R){f+=1;continue}p.push({instruction:{programId:i,accounts:this.toRequirementAccounts(r,n.accountKeyIndexes),data:n.data},descriptor:R}),I.set(`${i}:${g.payload.discriminator}`,g.context)}if(p.length===0)return t;const y=Array.from(I.values());if(f>0)return this.logger.warn("[run] transaction has unrecognized instructions; falling back to legacy",{data:{unrecognized:f,recognized:p.length}}),t;const x="full",h=N(p,{selectEnumVariants:this.args.selectEnumVariants});if(h.isLeft())return this.logger.warn("[run] requirement build failed; falling back",{data:{error:h.extract()}}),t;const s=h.unsafeCoerce(),d=[];s.tokenInfos.length>0&&d.push(...await this.getContextsByType({deviceModelId:this.args.deviceModelId,mints:s.tokenInfos,network:this.network},u.SOLANA_TOKEN_INFO)),d.push(...this.selectedEnumVariants(s.enumVariants,y));const A=[];for(const n of s.tokenAmountRefs){const i=await this.getContextsByType({deviceModelId:this.args.deviceModelId,mints:[n],network:this.network},u.SOLANA_TOKEN_INFO);i.length>0?d.push(...i):A.push(n)}const c={tokenAccountStates:[...s.tokenAccountStates,...A],altResolutions:s.altResolutions,trustedNames:s.trustedNames,tokenAmountAltRefs:s.tokenAmountAltRefs,mintAltRefs:s.mintAltRefs};return this.logger.debug("[run] built clear-sign context",{data:{mode:x,templates:y.length,pool:d.length,challengeBound:c.tokenAccountStates.length+c.altResolutions.length+c.trustedNames.length+c.tokenAmountAltRefs.length+c.mintAltRefs.length}}),{mode:x,poolContexts:d,instructionInfoContexts:y,challengeBoundRequirements:c}}async getContextsByType(t,o){const e=(await this.args.contextModule.getContexts(t,[o])).filter(a=>a.type===o);return e.length===0&&this.logger.warn("[run] satellite fetch yielded no descriptor (degraded)",{data:{type:o}}),e}selectedEnumVariants(t,o){const r=[];for(const e of t)for(const a of o){if(a.type!==u.SOLANA_INSTRUCTION_INFO||a.payload.programId!==e.programId)continue;const m=a.payload.enumVariants.find(l=>l.enumId===e.enumId&&l.variantIndex===e.variantIndex);if(m){r.push({type:u.SOLANA_ENUM_VARIANT,payload:{programId:e.programId,enumId:e.enumId,variantIndex:e.variantIndex,descriptor:m.descriptor},certificate:a.certificate});break}}return r}programIdOf(t,o){return t.allKeys[o]?.toBase58()??""}discriminatorMatches(t,o){if(t==="")return!0;const r=S(t);if(!r||r.length===0||o.length<r.length)return!1;for(let e=0;e<r.length;e++)if(o[e]!==r[e])return!1;return!0}toInstructionDescriptor(t){return{discriminator:t.discriminator,idlDescriptor:{type_pool:t.idlDescriptor.typePool,root_type:t.idlDescriptor.rootType},mintAssociations:t.mintAssociations,valueFlowPorts:t.valueFlowPorts,accountResets:t.accountResets,displayFields:t.displayFields,enumCache:this.toEnumCache(t.enumVariants)}}toEnumCache(t){if(t.length===0)return k;const o=[];for(const r of t){const e=S(r.descriptor.data);e&&o.push(e)}return M(o).caseOf({Left:()=>k,Right:r=>r})}toRequirementAccounts(t,o){return o.map(r=>{const e=t.addressLookupRefs?.[r];return e?{altRef:{altAddress:e.altAddress.toBase58(),entryIndex:e.entryIndex}}:{address:t.allKeys[r]?.toBase58()}})}}export{D as BuildGenericClearSignContextTask,w as COMPUTE_BUDGET_PROGRAM_ID,O as DEFAULT_NETWORK};
2
2
  //# sourceMappingURL=BuildGenericClearSignContextTask.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/internal/app-binder/task/BuildGenericClearSignContextTask.ts"],
4
- "sourcesContent": ["import {\n type ClearSignContext,\n ClearSignContextType,\n type ContextModule,\n type SolanaInstructionInfoPayload,\n} from \"@ledgerhq/context-module\";\nimport {\n type DeviceModelId,\n hexaStringToBuffer,\n type LoggerPublisherService,\n} from \"@ledgerhq/device-management-kit\";\n\nimport { type ClearSignMode } from \"@api/app-binder/SignTransactionDeviceActionTypes\";\nimport {\n buildEnumCache,\n type VariantCache,\n} from \"@internal/app-binder/clear-sign/idl-type-pool\";\nimport {\n type AltEntryKey,\n buildRequirements,\n type BuildRequirementsOptions,\n type DescriptorRequirements,\n type InstructionDescriptor,\n type MatchedInstruction,\n type RequirementAccount,\n} from \"@internal/app-binder/clear-sign/requirements\";\nimport { type NormalizedMessage } from \"@internal/app-binder/services/TransactionInspector\";\nimport { TransactionParser } from \"@internal/app-binder/services/utils/TransactionParser\";\n\n/**\n * ComputeBudget program \u2014 a hardcoded allow-list skip. It has no CAL descriptor\n * and is understood natively by the device: never looked up, never counted,\n * never streamed. `setComputeUnitPrice` (priority fee) is a ComputeBudget\n * instruction so it is covered by the same skip.\n */\nexport const COMPUTE_BUDGET_PROGRAM_ID =\n \"ComputeBudget111111111111111111111111111111\";\n\nexport const DEFAULT_NETWORK = \"solana-mainnet\";\nconst EMPTY_ENUM_CACHE: VariantCache = new Map();\n\n/** Challenge-bound requirements, fetched one at a time in the provide phase. */\nexport type ChallengeBoundRequirements = Pick<\n DescriptorRequirements,\n \"tokenAccountStates\" | \"altResolutions\" | \"trustedNames\"\n> & {\n /** ALT-backed PARAM_TOKEN_AMOUNT.TOKEN refs needing TOKEN_INFO-first resolution. */\n tokenAmountAltRefs: AltEntryKey[];\n /** ALT-backed MINT entries from MINT_ASSOCIATIONS; require TOKEN_INFO via hold-and-conditionally-stream. */\n mintAltRefs: AltEntryKey[];\n};\n\n/**\n * Everything the device needs to clear-sign a transaction, gathered host-side.\n * The non-challenge-bound descriptors are pre-fetched here; the challenge-bound\n * ones are carried as requirements and fetched+streamed by the provide phase.\n */\nexport type GenericClearSignContext = {\n /** `full` (merge) / `srfc39-only` (partial) / `none` (legacy fallback). */\n readonly mode: ClearSignMode;\n /** Phase A pool descriptors that need no challenge (token-info, enum-variant). */\n readonly poolContexts: ClearSignContext[];\n /** Phase B templates: one SOLANA_INSTRUCTION_INFO per matched (programId, discriminator). */\n readonly instructionInfoContexts: ClearSignContext[];\n /** Challenge-bound Phase A requirements, fetched+streamed in the provide phase. */\n readonly challengeBoundRequirements: ChallengeBoundRequirements;\n};\n\nexport type BuildGenericClearSignContextTaskArgs = {\n readonly contextModule: ContextModule;\n readonly transaction: Uint8Array;\n readonly deviceModelId: DeviceModelId;\n readonly loggerFactory: (tag: string) => LoggerPublisherService;\n readonly network?: string;\n /** Enum-variant decoder override; defaults to the real type-pool decoder. */\n readonly selectEnumVariants?: BuildRequirementsOptions[\"selectEnumVariants\"];\n};\n\n/**\n * Groups the whole host-side preparation for generic clear-signing: parse the\n * TX (raw ALT refs preserved), skip ComputeBudget, look up CAL\n * `INSTRUCTION_INFO` per remaining program, match discriminators, build the\n * requirement set, and pre-fetch the non-challenge-bound satellite descriptors.\n * Challenge-bound descriptors are NOT fetched here \u2014 each needs a fresh\n * `GET CHALLENGE` issued immediately before it is streamed, so they are carried\n * forward as requirements and resolved by the provide task.\n */\nexport class BuildGenericClearSignContextTask {\n private readonly logger: LoggerPublisherService;\n private readonly network: string;\n\n constructor(private readonly args: BuildGenericClearSignContextTaskArgs) {\n this.logger = args.loggerFactory(\"BuildGenericClearSignContextTask\");\n this.network = args.network ?? DEFAULT_NETWORK;\n }\n\n async run(): Promise<GenericClearSignContext> {\n const none: GenericClearSignContext = {\n mode: \"none\",\n poolContexts: [],\n instructionInfoContexts: [],\n challengeBoundRequirements: {\n tokenAccountStates: [],\n altResolutions: [],\n trustedNames: [],\n tokenAmountAltRefs: [],\n mintAltRefs: [],\n },\n };\n\n // --- Parse + CAL lookup + match (Stage 1) ---\n const parsed = await new TransactionParser(undefined, {\n preserveAltRefs: true,\n })\n .parse(this.args.transaction)\n .run();\n if (parsed.isLeft()) {\n this.logger.warn(\"[run] parse failed; falling back to legacy\", {\n data: { error: parsed.extract() },\n });\n return none;\n }\n const message = parsed.unsafeCoerce().message;\n\n const remaining = message.compiledInstructions\n .map((ix) => ({\n ix,\n programId: this.programIdOf(message, ix.programIdIndex),\n }))\n .filter(({ programId }) => programId !== COMPUTE_BUDGET_PROGRAM_ID);\n if (remaining.length === 0) return none;\n\n const distinctProgramIds = Array.from(\n new Set(remaining.map((r) => r.programId)),\n );\n const infoContexts = await this.args.contextModule.getContexts(\n {\n deviceModelId: this.args.deviceModelId,\n instructions: distinctProgramIds.map((programId) => ({ programId })),\n network: this.network,\n },\n [ClearSignContextType.SOLANA_INSTRUCTION_INFO],\n );\n\n const byProgram = new Map<\n string,\n { payload: SolanaInstructionInfoPayload; context: ClearSignContext }[]\n >();\n for (const context of infoContexts) {\n if (context.type !== ClearSignContextType.SOLANA_INSTRUCTION_INFO)\n continue;\n const list = byProgram.get(context.payload.programId) ?? [];\n list.push({ payload: context.payload, context });\n byProgram.set(context.payload.programId, list);\n }\n\n const matched: MatchedInstruction[] = [];\n const templateByKey = new Map<string, ClearSignContext>();\n let unrecognized = 0;\n for (const { ix, programId } of remaining) {\n const candidate = (byProgram.get(programId) ?? []).find(({ payload }) =>\n this.discriminatorMatches(payload.discriminator, ix.data),\n );\n const descriptor = candidate\n ? this.toInstructionDescriptor(candidate.payload)\n : null;\n if (!candidate || !descriptor) {\n unrecognized += 1;\n continue;\n }\n matched.push({\n instruction: {\n programId,\n accounts: this.toRequirementAccounts(message, ix.accountKeyIndexes),\n data: ix.data,\n },\n descriptor,\n });\n templateByKey.set(\n `${programId}:${candidate.payload.discriminator}`,\n candidate.context,\n );\n }\n if (matched.length === 0) return none;\n\n const instructionInfoContexts = Array.from(templateByKey.values());\n\n // The device requires every non-ComputeBudget instruction to have a\n // template at FINALIZE (cs_transaction_finalize walks all instructions).\n // Any unrecognized instruction guarantees 6d20 so cs_transaction_reset() and\n // basic sign to 6808 (blind signing disabled). Bail out early so basic sign\n // starts from a clean device state.\n if (unrecognized > 0) {\n this.logger.warn(\n \"[run] transaction has unrecognized instructions; falling back to legacy\",\n { data: { unrecognized, recognized: matched.length } },\n );\n return none;\n }\n const mode: ClearSignMode = \"full\";\n\n // --- Requirements (Stage 2) ---\n const requirementsResult = buildRequirements(matched, {\n selectEnumVariants: this.args.selectEnumVariants,\n });\n if (requirementsResult.isLeft()) {\n this.logger.warn(\"[run] requirement build failed; falling back\", {\n data: { error: requirementsResult.extract() },\n });\n return none;\n }\n const requirements = requirementsResult.unsafeCoerce();\n\n // --- Fetch non-challenge-bound satellites (Stage 3) ---\n const poolContexts: ClearSignContext[] = [];\n if (requirements.tokenInfos.length > 0) {\n poolContexts.push(\n ...(await this.getContextsByType(\n {\n deviceModelId: this.args.deviceModelId,\n mints: requirements.tokenInfos,\n network: this.network,\n },\n ClearSignContextType.SOLANA_TOKEN_INFO,\n )),\n );\n }\n poolContexts.push(\n ...this.selectedEnumVariants(\n requirements.enumVariants,\n instructionInfoContexts,\n ),\n );\n\n // PARAM_TOKEN_AMOUNT.TOKEN refs: try TOKEN_INFO first (optimistic mint).\n // If that fails, fall back to TOKEN_ACCOUNT_STATE (it's an ATA).\n const tokenAmountFallbackAccounts: string[] = [];\n for (const ref of requirements.tokenAmountRefs) {\n const tokenInfoContexts = await this.getContextsByType(\n {\n deviceModelId: this.args.deviceModelId,\n mints: [ref],\n network: this.network,\n },\n ClearSignContextType.SOLANA_TOKEN_INFO,\n );\n if (tokenInfoContexts.length > 0) {\n poolContexts.push(...tokenInfoContexts);\n } else {\n tokenAmountFallbackAccounts.push(ref);\n }\n }\n\n // RequirementAccumulator.build() already strips tokenAmountAltRefs and\n // mintAltRefs entries from altResolutions (cross-bucket priority dedup),\n // so requirements.altResolutions is safe to use directly here.\n const challengeBoundRequirements: ChallengeBoundRequirements = {\n tokenAccountStates: [\n ...requirements.tokenAccountStates,\n ...tokenAmountFallbackAccounts,\n ],\n altResolutions: requirements.altResolutions,\n trustedNames: requirements.trustedNames,\n tokenAmountAltRefs: requirements.tokenAmountAltRefs,\n mintAltRefs: requirements.mintAltRefs,\n };\n\n this.logger.debug(\"[run] built clear-sign context\", {\n data: {\n mode,\n templates: instructionInfoContexts.length,\n pool: poolContexts.length,\n challengeBound:\n challengeBoundRequirements.tokenAccountStates.length +\n challengeBoundRequirements.altResolutions.length +\n challengeBoundRequirements.trustedNames.length +\n challengeBoundRequirements.tokenAmountAltRefs.length +\n challengeBoundRequirements.mintAltRefs.length,\n },\n });\n\n return {\n mode,\n poolContexts,\n instructionInfoContexts,\n challengeBoundRequirements,\n };\n }\n\n /** Fetch contexts of `type`; ERROR / wrong-type contexts are dropped (satellites degrade). */\n private async getContextsByType<TInput>(\n input: TInput,\n type: ClearSignContextType,\n ): Promise<ClearSignContext[]> {\n const contexts = await this.args.contextModule.getContexts(input, [type]);\n const usable = contexts.filter((c) => c.type === type);\n if (usable.length === 0) {\n this.logger.warn(\n \"[run] satellite fetch yielded no descriptor (degraded)\",\n {\n data: { type },\n },\n );\n }\n return usable;\n }\n\n /** Build SOLANA_ENUM_VARIANT contexts for the selected variants from the bundled payloads. */\n private selectedEnumVariants(\n keys: readonly {\n programId: string;\n enumId: string;\n variantIndex: number;\n }[],\n instructionInfoContexts: ClearSignContext[],\n ): ClearSignContext[] {\n const out: ClearSignContext[] = [];\n for (const key of keys) {\n for (const context of instructionInfoContexts) {\n if (context.type !== ClearSignContextType.SOLANA_INSTRUCTION_INFO)\n continue;\n if (context.payload.programId !== key.programId) continue;\n const variant = context.payload.enumVariants.find(\n (v) => v.enumId === key.enumId && v.variantIndex === key.variantIndex,\n );\n if (variant) {\n out.push({\n type: ClearSignContextType.SOLANA_ENUM_VARIANT,\n payload: {\n programId: key.programId,\n enumId: key.enumId,\n variantIndex: key.variantIndex,\n descriptor: variant.descriptor,\n },\n certificate: context.certificate,\n });\n break;\n }\n }\n }\n return out;\n }\n\n private programIdOf(message: NormalizedMessage, index: number): string {\n return message.allKeys[index]?.toBase58() ?? \"\";\n }\n\n private discriminatorMatches(\n discriminatorHex: string,\n data: Uint8Array,\n ): boolean {\n const disc = hexaStringToBuffer(discriminatorHex);\n if (!disc || disc.length === 0 || data.length < disc.length) return false;\n for (let i = 0; i < disc.length; i++) {\n if (data[i] !== disc[i]) return false;\n }\n return true;\n }\n\n private toInstructionDescriptor(\n payload: SolanaInstructionInfoPayload,\n ): InstructionDescriptor {\n return {\n discriminator: payload.discriminator,\n idlDescriptor: {\n type_pool: payload.idlDescriptor.typePool,\n root_type: payload.idlDescriptor.rootType,\n },\n mintAssociations: payload.mintAssociations,\n valueFlowPorts: payload.valueFlowPorts,\n accountResets: payload.accountResets,\n displayFields: payload.displayFields,\n enumCache: this.toEnumCache(payload.enumVariants),\n };\n }\n\n private toEnumCache(\n enumVariants: SolanaInstructionInfoPayload[\"enumVariants\"],\n ): VariantCache {\n if (enumVariants.length === 0) return EMPTY_ENUM_CACHE;\n const tlvs: Uint8Array[] = [];\n for (const variant of enumVariants) {\n const bytes = hexaStringToBuffer(variant.descriptor.data);\n if (bytes) tlvs.push(bytes);\n }\n return buildEnumCache(tlvs).caseOf({\n Left: () => EMPTY_ENUM_CACHE,\n Right: (cache) => cache,\n });\n }\n\n private toRequirementAccounts(\n message: NormalizedMessage,\n accountKeyIndexes: number[],\n ): RequirementAccount[] {\n return accountKeyIndexes.map((keyIdx) => {\n const altRef = message.addressLookupRefs?.[keyIdx];\n if (altRef) {\n return {\n altRef: {\n altAddress: altRef.altAddress.toBase58(),\n entryIndex: altRef.entryIndex,\n },\n };\n }\n return { address: message.allKeys[keyIdx]?.toBase58() };\n });\n }\n}\n"],
5
- "mappings": "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",
6
- "names": ["ClearSignContextType", "hexaStringToBuffer", "buildEnumCache", "buildRequirements", "TransactionParser", "COMPUTE_BUDGET_PROGRAM_ID", "DEFAULT_NETWORK", "EMPTY_ENUM_CACHE", "BuildGenericClearSignContextTask", "args", "none", "parsed", "message", "remaining", "ix", "programId", "distinctProgramIds", "r", "infoContexts", "byProgram", "context", "list", "matched", "templateByKey", "unrecognized", "candidate", "payload", "descriptor", "instructionInfoContexts", "mode", "requirementsResult", "requirements", "poolContexts", "tokenAmountFallbackAccounts", "ref", "tokenInfoContexts", "challengeBoundRequirements", "input", "type", "usable", "c", "keys", "out", "key", "variant", "v", "index", "discriminatorHex", "data", "disc", "i", "enumVariants", "tlvs", "bytes", "cache", "accountKeyIndexes", "keyIdx", "altRef"]
4
+ "sourcesContent": ["import {\n type ClearSignContext,\n ClearSignContextType,\n type ContextModule,\n type SolanaInstructionInfoPayload,\n} from \"@ledgerhq/context-module\";\nimport {\n type DeviceModelId,\n hexaStringToBuffer,\n type LoggerPublisherService,\n} from \"@ledgerhq/device-management-kit\";\n\nimport { type ClearSignMode } from \"@api/app-binder/SignTransactionDeviceActionTypes\";\nimport {\n buildEnumCache,\n type VariantCache,\n} from \"@internal/app-binder/clear-sign/idl-type-pool\";\nimport {\n type AltEntryKey,\n buildRequirements,\n type BuildRequirementsOptions,\n type DescriptorRequirements,\n type InstructionDescriptor,\n type MatchedInstruction,\n type RequirementAccount,\n} from \"@internal/app-binder/clear-sign/requirements\";\nimport { type NormalizedMessage } from \"@internal/app-binder/services/TransactionInspector\";\nimport { TransactionParser } from \"@internal/app-binder/services/utils/TransactionParser\";\n\n/**\n * ComputeBudget program \u2014 a hardcoded allow-list skip. It has no CAL descriptor\n * and is understood natively by the device: never looked up, never counted,\n * never streamed. `setComputeUnitPrice` (priority fee) is a ComputeBudget\n * instruction so it is covered by the same skip.\n */\nexport const COMPUTE_BUDGET_PROGRAM_ID =\n \"ComputeBudget111111111111111111111111111111\";\n\nexport const DEFAULT_NETWORK = \"solana-mainnet\";\nconst EMPTY_ENUM_CACHE: VariantCache = new Map();\n\n/** Challenge-bound requirements, fetched one at a time in the provide phase. */\nexport type ChallengeBoundRequirements = Pick<\n DescriptorRequirements,\n \"tokenAccountStates\" | \"altResolutions\" | \"trustedNames\"\n> & {\n /** ALT-backed PARAM_TOKEN_AMOUNT.TOKEN refs needing TOKEN_INFO-first resolution. */\n tokenAmountAltRefs: AltEntryKey[];\n /** ALT-backed MINT entries from MINT_ASSOCIATIONS; require TOKEN_INFO via hold-and-conditionally-stream. */\n mintAltRefs: AltEntryKey[];\n};\n\n/**\n * Everything the device needs to clear-sign a transaction, gathered host-side.\n * The non-challenge-bound descriptors are pre-fetched here; the challenge-bound\n * ones are carried as requirements and fetched+streamed by the provide phase.\n */\nexport type GenericClearSignContext = {\n /** `full` (merge) / `srfc39-only` (partial) / `none` (legacy fallback). */\n readonly mode: ClearSignMode;\n /** Phase A pool descriptors that need no challenge (token-info, enum-variant). */\n readonly poolContexts: ClearSignContext[];\n /** Phase B templates: one SOLANA_INSTRUCTION_INFO per matched (programId, discriminator). */\n readonly instructionInfoContexts: ClearSignContext[];\n /** Challenge-bound Phase A requirements, fetched+streamed in the provide phase. */\n readonly challengeBoundRequirements: ChallengeBoundRequirements;\n};\n\nexport type BuildGenericClearSignContextTaskArgs = {\n readonly contextModule: ContextModule;\n readonly transaction: Uint8Array;\n readonly deviceModelId: DeviceModelId;\n readonly loggerFactory: (tag: string) => LoggerPublisherService;\n readonly network?: string;\n /** Enum-variant decoder override; defaults to the real type-pool decoder. */\n readonly selectEnumVariants?: BuildRequirementsOptions[\"selectEnumVariants\"];\n};\n\n/**\n * Groups the whole host-side preparation for generic clear-signing: parse the\n * TX (raw ALT refs preserved), skip ComputeBudget, look up CAL\n * `INSTRUCTION_INFO` per remaining program, match discriminators, build the\n * requirement set, and pre-fetch the non-challenge-bound satellite descriptors.\n * Challenge-bound descriptors are NOT fetched here \u2014 each needs a fresh\n * `GET CHALLENGE` issued immediately before it is streamed, so they are carried\n * forward as requirements and resolved by the provide task.\n */\nexport class BuildGenericClearSignContextTask {\n private readonly logger: LoggerPublisherService;\n private readonly network: string;\n\n constructor(private readonly args: BuildGenericClearSignContextTaskArgs) {\n this.logger = args.loggerFactory(\"BuildGenericClearSignContextTask\");\n this.network = args.network ?? DEFAULT_NETWORK;\n }\n\n async run(): Promise<GenericClearSignContext> {\n const none: GenericClearSignContext = {\n mode: \"none\",\n poolContexts: [],\n instructionInfoContexts: [],\n challengeBoundRequirements: {\n tokenAccountStates: [],\n altResolutions: [],\n trustedNames: [],\n tokenAmountAltRefs: [],\n mintAltRefs: [],\n },\n };\n\n // --- Parse + CAL lookup + match (Stage 1) ---\n const parsed = await new TransactionParser(undefined, {\n preserveAltRefs: true,\n })\n .parse(this.args.transaction)\n .run();\n if (parsed.isLeft()) {\n this.logger.warn(\"[run] parse failed; falling back to legacy\", {\n data: { error: parsed.extract() },\n });\n return none;\n }\n const message = parsed.unsafeCoerce().message;\n\n const remaining = message.compiledInstructions\n .map((ix) => ({\n ix,\n programId: this.programIdOf(message, ix.programIdIndex),\n }))\n .filter(({ programId }) => programId !== COMPUTE_BUDGET_PROGRAM_ID);\n if (remaining.length === 0) return none;\n\n const distinctProgramIds = Array.from(\n new Set(remaining.map((r) => r.programId)),\n );\n const infoContexts = await this.args.contextModule.getContexts(\n {\n deviceModelId: this.args.deviceModelId,\n instructions: distinctProgramIds.map((programId) => ({ programId })),\n network: this.network,\n },\n [ClearSignContextType.SOLANA_INSTRUCTION_INFO],\n );\n\n const byProgram = new Map<\n string,\n { payload: SolanaInstructionInfoPayload; context: ClearSignContext }[]\n >();\n for (const context of infoContexts) {\n if (context.type !== ClearSignContextType.SOLANA_INSTRUCTION_INFO)\n continue;\n const list = byProgram.get(context.payload.programId) ?? [];\n list.push({ payload: context.payload, context });\n byProgram.set(context.payload.programId, list);\n }\n\n const matched: MatchedInstruction[] = [];\n const templateByKey = new Map<string, ClearSignContext>();\n let unrecognized = 0;\n for (const { ix, programId } of remaining) {\n // Prefer the most specific match: a discriminator-less descriptor\n // matches any data of its program, so it must not shadow a descriptor\n // that pins actual leading bytes.\n const candidate = (byProgram.get(programId) ?? [])\n .filter(({ payload }) =>\n this.discriminatorMatches(payload.discriminator, ix.data),\n )\n .sort(\n (a, b) =>\n b.payload.discriminator.length - a.payload.discriminator.length,\n )[0];\n const descriptor = candidate\n ? this.toInstructionDescriptor(candidate.payload)\n : null;\n if (!candidate || !descriptor) {\n unrecognized += 1;\n continue;\n }\n matched.push({\n instruction: {\n programId,\n accounts: this.toRequirementAccounts(message, ix.accountKeyIndexes),\n data: ix.data,\n },\n descriptor,\n });\n templateByKey.set(\n `${programId}:${candidate.payload.discriminator}`,\n candidate.context,\n );\n }\n if (matched.length === 0) return none;\n\n const instructionInfoContexts = Array.from(templateByKey.values());\n\n // The device requires every non-ComputeBudget instruction to have a\n // template at FINALIZE (cs_transaction_finalize walks all instructions).\n // Any unrecognized instruction guarantees 6d20 so cs_transaction_reset() and\n // basic sign to 6808 (blind signing disabled). Bail out early so basic sign\n // starts from a clean device state.\n if (unrecognized > 0) {\n this.logger.warn(\n \"[run] transaction has unrecognized instructions; falling back to legacy\",\n { data: { unrecognized, recognized: matched.length } },\n );\n return none;\n }\n const mode: ClearSignMode = \"full\";\n\n // --- Requirements (Stage 2) ---\n const requirementsResult = buildRequirements(matched, {\n selectEnumVariants: this.args.selectEnumVariants,\n });\n if (requirementsResult.isLeft()) {\n this.logger.warn(\"[run] requirement build failed; falling back\", {\n data: { error: requirementsResult.extract() },\n });\n return none;\n }\n const requirements = requirementsResult.unsafeCoerce();\n\n // --- Fetch non-challenge-bound satellites (Stage 3) ---\n const poolContexts: ClearSignContext[] = [];\n if (requirements.tokenInfos.length > 0) {\n poolContexts.push(\n ...(await this.getContextsByType(\n {\n deviceModelId: this.args.deviceModelId,\n mints: requirements.tokenInfos,\n network: this.network,\n },\n ClearSignContextType.SOLANA_TOKEN_INFO,\n )),\n );\n }\n poolContexts.push(\n ...this.selectedEnumVariants(\n requirements.enumVariants,\n instructionInfoContexts,\n ),\n );\n\n // PARAM_TOKEN_AMOUNT.TOKEN refs: try TOKEN_INFO first (optimistic mint).\n // If that fails, fall back to TOKEN_ACCOUNT_STATE (it's an ATA).\n const tokenAmountFallbackAccounts: string[] = [];\n for (const ref of requirements.tokenAmountRefs) {\n const tokenInfoContexts = await this.getContextsByType(\n {\n deviceModelId: this.args.deviceModelId,\n mints: [ref],\n network: this.network,\n },\n ClearSignContextType.SOLANA_TOKEN_INFO,\n );\n if (tokenInfoContexts.length > 0) {\n poolContexts.push(...tokenInfoContexts);\n } else {\n tokenAmountFallbackAccounts.push(ref);\n }\n }\n\n // RequirementAccumulator.build() already strips tokenAmountAltRefs and\n // mintAltRefs entries from altResolutions (cross-bucket priority dedup),\n // so requirements.altResolutions is safe to use directly here.\n const challengeBoundRequirements: ChallengeBoundRequirements = {\n tokenAccountStates: [\n ...requirements.tokenAccountStates,\n ...tokenAmountFallbackAccounts,\n ],\n altResolutions: requirements.altResolutions,\n trustedNames: requirements.trustedNames,\n tokenAmountAltRefs: requirements.tokenAmountAltRefs,\n mintAltRefs: requirements.mintAltRefs,\n };\n\n this.logger.debug(\"[run] built clear-sign context\", {\n data: {\n mode,\n templates: instructionInfoContexts.length,\n pool: poolContexts.length,\n challengeBound:\n challengeBoundRequirements.tokenAccountStates.length +\n challengeBoundRequirements.altResolutions.length +\n challengeBoundRequirements.trustedNames.length +\n challengeBoundRequirements.tokenAmountAltRefs.length +\n challengeBoundRequirements.mintAltRefs.length,\n },\n });\n\n return {\n mode,\n poolContexts,\n instructionInfoContexts,\n challengeBoundRequirements,\n };\n }\n\n /** Fetch contexts of `type`; ERROR / wrong-type contexts are dropped (satellites degrade). */\n private async getContextsByType<TInput>(\n input: TInput,\n type: ClearSignContextType,\n ): Promise<ClearSignContext[]> {\n const contexts = await this.args.contextModule.getContexts(input, [type]);\n const usable = contexts.filter((c) => c.type === type);\n if (usable.length === 0) {\n this.logger.warn(\n \"[run] satellite fetch yielded no descriptor (degraded)\",\n {\n data: { type },\n },\n );\n }\n return usable;\n }\n\n /** Build SOLANA_ENUM_VARIANT contexts for the selected variants from the bundled payloads. */\n private selectedEnumVariants(\n keys: readonly {\n programId: string;\n enumId: string;\n variantIndex: number;\n }[],\n instructionInfoContexts: ClearSignContext[],\n ): ClearSignContext[] {\n const out: ClearSignContext[] = [];\n for (const key of keys) {\n for (const context of instructionInfoContexts) {\n if (context.type !== ClearSignContextType.SOLANA_INSTRUCTION_INFO)\n continue;\n if (context.payload.programId !== key.programId) continue;\n const variant = context.payload.enumVariants.find(\n (v) => v.enumId === key.enumId && v.variantIndex === key.variantIndex,\n );\n if (variant) {\n out.push({\n type: ClearSignContextType.SOLANA_ENUM_VARIANT,\n payload: {\n programId: key.programId,\n enumId: key.enumId,\n variantIndex: key.variantIndex,\n descriptor: variant.descriptor,\n },\n certificate: context.certificate,\n });\n break;\n }\n }\n }\n return out;\n }\n\n private programIdOf(message: NormalizedMessage, index: number): string {\n return message.allKeys[index]?.toBase58() ?? \"\";\n }\n\n private discriminatorMatches(\n discriminatorHex: string,\n data: Uint8Array,\n ): boolean {\n // Single-instruction programs (e.g. SPL Memo) carry no discriminator: the\n // instruction data is all arguments, so the descriptor matches any data.\n if (discriminatorHex === \"\") return true;\n const disc = hexaStringToBuffer(discriminatorHex);\n if (!disc || disc.length === 0 || data.length < disc.length) return false;\n for (let i = 0; i < disc.length; i++) {\n if (data[i] !== disc[i]) return false;\n }\n return true;\n }\n\n private toInstructionDescriptor(\n payload: SolanaInstructionInfoPayload,\n ): InstructionDescriptor {\n return {\n discriminator: payload.discriminator,\n idlDescriptor: {\n type_pool: payload.idlDescriptor.typePool,\n root_type: payload.idlDescriptor.rootType,\n },\n mintAssociations: payload.mintAssociations,\n valueFlowPorts: payload.valueFlowPorts,\n accountResets: payload.accountResets,\n displayFields: payload.displayFields,\n enumCache: this.toEnumCache(payload.enumVariants),\n };\n }\n\n private toEnumCache(\n enumVariants: SolanaInstructionInfoPayload[\"enumVariants\"],\n ): VariantCache {\n if (enumVariants.length === 0) return EMPTY_ENUM_CACHE;\n const tlvs: Uint8Array[] = [];\n for (const variant of enumVariants) {\n const bytes = hexaStringToBuffer(variant.descriptor.data);\n if (bytes) tlvs.push(bytes);\n }\n return buildEnumCache(tlvs).caseOf({\n Left: () => EMPTY_ENUM_CACHE,\n Right: (cache) => cache,\n });\n }\n\n private toRequirementAccounts(\n message: NormalizedMessage,\n accountKeyIndexes: number[],\n ): RequirementAccount[] {\n return accountKeyIndexes.map((keyIdx) => {\n const altRef = message.addressLookupRefs?.[keyIdx];\n if (altRef) {\n return {\n altRef: {\n altAddress: altRef.altAddress.toBase58(),\n entryIndex: altRef.entryIndex,\n },\n };\n }\n return { address: message.allKeys[keyIdx]?.toBase58() };\n });\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["ClearSignContextType", "hexaStringToBuffer", "buildEnumCache", "buildRequirements", "TransactionParser", "COMPUTE_BUDGET_PROGRAM_ID", "DEFAULT_NETWORK", "EMPTY_ENUM_CACHE", "BuildGenericClearSignContextTask", "args", "none", "parsed", "message", "remaining", "ix", "programId", "distinctProgramIds", "r", "infoContexts", "byProgram", "context", "list", "matched", "templateByKey", "unrecognized", "candidate", "payload", "a", "b", "descriptor", "instructionInfoContexts", "mode", "requirementsResult", "requirements", "poolContexts", "tokenAmountFallbackAccounts", "ref", "tokenInfoContexts", "challengeBoundRequirements", "input", "type", "usable", "c", "keys", "out", "key", "variant", "v", "index", "discriminatorHex", "data", "disc", "i", "enumVariants", "tlvs", "bytes", "cache", "accountKeyIndexes", "keyIdx", "altRef"]
7
7
  }
@@ -1,2 +1,2 @@
1
- import{ClearSignContextType as d}from"@ledgerhq/context-module";import{DeviceModelId as p}from"@ledgerhq/device-management-kit";import{Keypair as g,PublicKey as x,Transaction as I,TransactionInstruction as T}from"@solana/web3.js";import{Buffer as w}from"buffer";import{Right as N}from"purify-ts";import{describe as k,expect as o,it as c,vi as s}from"vitest";import{DefaultBs58Encoder as B}from"../../app-binder/services/bs58Encoder";import{BuildGenericClearSignContextTask as S,COMPUTE_BUDGET_PROGRAM_ID as m}from"./BuildGenericClearSignContextTask";const A=B.encode(new Uint8Array(32).fill(170)),a=new x("9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin"),C=new x("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr"),O="0001",_={typePool:[{index:0,kind:"STRUCT",refs:[]}],rootType:0};function r(t,n){return new T({keys:[{pubkey:g.generate().publicKey,isSigner:!1,isWritable:!0}],programId:t,data:w.from(n)})}function u(t){const n=g.generate(),e=new I;return e.recentBlockhash=A,e.feePayer=n.publicKey,e.add(...t),e.sign(n),e.serialize()}function f(t,n){return{type:d.SOLANA_INSTRUCTION_INFO,payload:{programId:t,discriminator:n,instructionInfo:{data:O,signature:"00"},substructures:[],enumVariants:[],idlDescriptor:_,mintAssociations:[],valueFlowPorts:[],accountResets:[],displayFields:[]}}}function l(t,n){const e=s.fn(async(M,y)=>y.includes(d.SOLANA_INSTRUCTION_INFO)?n:[]),i={getContexts:e};return{task:new S({contextModule:i,transaction:t,deviceModelId:p.STAX,loggerFactory:()=>({debug:s.fn(),info:s.fn(),warn:s.fn(),error:s.fn()}),selectEnumVariants:()=>N([])}),getContexts:e}}k("BuildGenericClearSignContextTask",()=>{c("returns mode `full` and a template when every non-ComputeBudget instruction is recognized",async()=>{const t=u([r(new x(m),[2,64,66]),r(a,[1,2,170])]),{task:n,getContexts:e}=l(t,[f(a.toBase58(),"0102")]),i=await n.run();o(i.mode).toBe("full"),o(i.instructionInfoContexts).toHaveLength(1),o(e).toHaveBeenCalledWith(o.objectContaining({instructions:[{programId:a.toBase58()}]}),[d.SOLANA_INSTRUCTION_INFO])}),c("returns mode `none` when some instructions are unrecognized",async()=>{const t=u([r(a,[1,2]),r(C,[9])]),{task:n}=l(t,[f(a.toBase58(),"0102")]),e=await n.run();o(e.mode).toBe("none"),o(e.instructionInfoContexts).toHaveLength(0)}),c("returns mode `none` when nothing is recognized",async()=>{const t=u([r(C,[9])]),{task:n}=l(t,[]);o((await n.run()).mode).toBe("none")}),c("returns mode `none` for a ComputeBudget-only tx without calling CAL",async()=>{const t=u([r(new x(m),[2,64,66])]),{task:n,getContexts:e}=l(t,[]);o((await n.run()).mode).toBe("none"),o(e).not.toHaveBeenCalled()})});
1
+ import{ClearSignContextType as m}from"@ledgerhq/context-module";import{DeviceModelId as p}from"@ledgerhq/device-management-kit";import{Keypair as g,PublicKey as d,Transaction as I,TransactionInstruction as w}from"@solana/web3.js";import{Buffer as B}from"buffer";import{Right as T}from"purify-ts";import{describe as b,expect as o,it as r,vi as l}from"vitest";import{DefaultBs58Encoder as k}from"../../app-binder/services/bs58Encoder";import{BuildGenericClearSignContextTask as N,COMPUTE_BUDGET_PROGRAM_ID as f}from"./BuildGenericClearSignContextTask";const S=k.encode(new Uint8Array(32).fill(170)),s=new d("9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin"),C=new d("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr"),A="0001",O={typePool:[{index:0,kind:"STRUCT",refs:[]}],rootType:0};function a(e,n){return new w({keys:[{pubkey:g.generate().publicKey,isSigner:!1,isWritable:!0}],programId:e,data:B.from(n)})}function i(e){const n=g.generate(),t=new I;return t.recentBlockhash=S,t.feePayer=n.publicKey,t.add(...e),t.sign(n),t.serialize()}function c(e,n,t=A){return{type:m.SOLANA_INSTRUCTION_INFO,payload:{programId:e,discriminator:n,instructionInfo:{data:t,signature:"00"},substructures:[],enumVariants:[],idlDescriptor:O,mintAssociations:[],valueFlowPorts:[],accountResets:[],displayFields:[]}}}function u(e,n){const t=l.fn(async(h,y)=>y.includes(m.SOLANA_INSTRUCTION_INFO)?n:[]),x={getContexts:t};return{task:new N({contextModule:x,transaction:e,deviceModelId:p.STAX,loggerFactory:()=>({debug:l.fn(),info:l.fn(),warn:l.fn(),error:l.fn()}),selectEnumVariants:()=>T([])}),getContexts:t}}b("BuildGenericClearSignContextTask",()=>{r("returns mode `full` and a template when every non-ComputeBudget instruction is recognized",async()=>{const e=i([a(new d(f),[2,64,66]),a(s,[1,2,170])]),{task:n,getContexts:t}=u(e,[c(s.toBase58(),"0102")]),x=await n.run();o(x.mode).toBe("full"),o(x.instructionInfoContexts).toHaveLength(1),o(t).toHaveBeenCalledWith(o.objectContaining({instructions:[{programId:s.toBase58()}]}),[m.SOLANA_INSTRUCTION_INFO])}),r("matches a descriptor without a discriminator against any instruction data",async()=>{const e=i([a(s,[104,105])]),{task:n}=u(e,[c(s.toBase58(),"")]),t=await n.run();o(t.mode).toBe("full"),o(t.instructionInfoContexts).toHaveLength(1)}),r("prefers the most specific descriptor over a discriminator-less one",async()=>{const e=i([a(s,[1,2,170])]),{task:n}=u(e,[c(s.toBase58(),"","aaaa"),c(s.toBase58(),"0102","bbbb")]),t=await n.run();o(t.mode).toBe("full"),o(t.instructionInfoContexts).toEqual([c(s.toBase58(),"0102","bbbb")])}),r("returns mode `none` when some instructions are unrecognized",async()=>{const e=i([a(s,[1,2]),a(C,[9])]),{task:n}=u(e,[c(s.toBase58(),"0102")]),t=await n.run();o(t.mode).toBe("none"),o(t.instructionInfoContexts).toHaveLength(0)}),r("returns mode `none` when nothing is recognized",async()=>{const e=i([a(C,[9])]),{task:n}=u(e,[]);o((await n.run()).mode).toBe("none")}),r("returns mode `none` for a ComputeBudget-only tx without calling CAL",async()=>{const e=i([a(new d(f),[2,64,66])]),{task:n,getContexts:t}=u(e,[]);o((await n.run()).mode).toBe("none"),o(t).not.toHaveBeenCalled()})});
2
2
  //# sourceMappingURL=BuildGenericClearSignContextTask.test.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/internal/app-binder/task/BuildGenericClearSignContextTask.test.ts"],
4
- "sourcesContent": ["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {\n type ClearSignContext,\n ClearSignContextType,\n type ContextModule,\n} from \"@ledgerhq/context-module\";\nimport { DeviceModelId } from \"@ledgerhq/device-management-kit\";\nimport {\n Keypair,\n PublicKey,\n Transaction,\n TransactionInstruction,\n} from \"@solana/web3.js\";\nimport { Buffer } from \"buffer\";\nimport { Right } from \"purify-ts\";\nimport { describe, expect, it, vi } from \"vitest\";\n\nimport { DefaultBs58Encoder } from \"@internal/app-binder/services/bs58Encoder\";\n\nimport {\n BuildGenericClearSignContextTask,\n COMPUTE_BUDGET_PROGRAM_ID,\n} from \"./BuildGenericClearSignContextTask\";\n\nconst DUMMY_BLOCKHASH = DefaultBs58Encoder.encode(\n new Uint8Array(32).fill(0xaa),\n);\nconst KNOWN_PROGRAM = new PublicKey(\n \"9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin\",\n);\nconst UNKNOWN_PROGRAM = new PublicKey(\n \"MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr\",\n);\n\n// Dummy signed TLV hex (streamed to the device; not parsed host-side).\nconst INFO_HEX = \"0001\";\n\n// Minimal-but-valid decoded type pool so buildRequirements returns Right.\nconst MIN_IDL_DESCRIPTOR = {\n typePool: [{ index: 0, kind: \"STRUCT\", refs: [] }],\n rootType: 0,\n};\n\nfunction makeIx(programId: PublicKey, data: number[]): TransactionInstruction {\n return new TransactionInstruction({\n keys: [\n {\n pubkey: Keypair.generate().publicKey,\n isSigner: false,\n isWritable: true,\n },\n ],\n programId,\n data: Buffer.from(data),\n });\n}\n\nfunction makeRawTx(ixs: TransactionInstruction[]): Uint8Array {\n const payer = Keypair.generate();\n const tx = new Transaction();\n tx.recentBlockhash = DUMMY_BLOCKHASH;\n tx.feePayer = payer.publicKey;\n tx.add(...ixs);\n tx.sign(payer);\n return tx.serialize();\n}\n\nfunction instructionInfoContext(\n programId: string,\n discriminator: string,\n): ClearSignContext {\n return {\n type: ClearSignContextType.SOLANA_INSTRUCTION_INFO,\n payload: {\n programId,\n discriminator,\n instructionInfo: { data: INFO_HEX, signature: \"00\" },\n substructures: [],\n enumVariants: [],\n idlDescriptor: MIN_IDL_DESCRIPTOR,\n mintAssociations: [],\n valueFlowPorts: [],\n accountResets: [],\n displayFields: [],\n },\n } as any;\n}\n\nfunction makeTask(transaction: Uint8Array, infoContexts: ClearSignContext[]) {\n const getContexts = vi.fn(async (_input: unknown, types: unknown) =>\n (types as ClearSignContextType[]).includes(\n ClearSignContextType.SOLANA_INSTRUCTION_INFO,\n )\n ? infoContexts\n : [],\n );\n const contextModule = { getContexts } as unknown as ContextModule;\n const task = new BuildGenericClearSignContextTask({\n contextModule,\n transaction,\n deviceModelId: DeviceModelId.STAX,\n loggerFactory: () =>\n ({\n debug: vi.fn(),\n info: vi.fn(),\n warn: vi.fn(),\n error: vi.fn(),\n }) as any,\n // Stub the enum decoder (the minimal fixture pool isn't real-decodable).\n selectEnumVariants: () => Right([]),\n });\n return { task, getContexts };\n}\n\ndescribe(\"BuildGenericClearSignContextTask\", () => {\n it(\"returns mode `full` and a template when every non-ComputeBudget instruction is recognized\", async () => {\n const tx = makeRawTx([\n makeIx(new PublicKey(COMPUTE_BUDGET_PROGRAM_ID), [0x02, 0x40, 0x42]),\n makeIx(KNOWN_PROGRAM, [0x01, 0x02, 0xaa]),\n ]);\n const { task, getContexts } = makeTask(tx, [\n instructionInfoContext(KNOWN_PROGRAM.toBase58(), \"0102\"),\n ]);\n\n const result = await task.run();\n\n expect(result.mode).toBe(\"full\");\n expect(result.instructionInfoContexts).toHaveLength(1);\n // ComputeBudget is never looked up in CAL.\n expect(getContexts).toHaveBeenCalledWith(\n expect.objectContaining({\n instructions: [{ programId: KNOWN_PROGRAM.toBase58() }],\n }),\n [ClearSignContextType.SOLANA_INSTRUCTION_INFO],\n );\n });\n\n it(\"returns mode `none` when some instructions are unrecognized\", async () => {\n // Any unrecognized instruction causes FINALIZE to fail on the device\n // (cs_transaction_finalize walks all instructions), so we bail to legacy\n // basic sign from a clean state rather than attempting generic clear-signing.\n const tx = makeRawTx([\n makeIx(KNOWN_PROGRAM, [0x01, 0x02]),\n makeIx(UNKNOWN_PROGRAM, [0x09]),\n ]);\n const { task } = makeTask(tx, [\n instructionInfoContext(KNOWN_PROGRAM.toBase58(), \"0102\"),\n ]);\n\n const result = await task.run();\n\n expect(result.mode).toBe(\"none\");\n expect(result.instructionInfoContexts).toHaveLength(0);\n });\n\n it(\"returns mode `none` when nothing is recognized\", async () => {\n const tx = makeRawTx([makeIx(UNKNOWN_PROGRAM, [0x09])]);\n const { task } = makeTask(tx, []);\n\n expect((await task.run()).mode).toBe(\"none\");\n });\n\n it(\"returns mode `none` for a ComputeBudget-only tx without calling CAL\", async () => {\n const tx = makeRawTx([\n makeIx(new PublicKey(COMPUTE_BUDGET_PROGRAM_ID), [0x02, 0x40, 0x42]),\n ]);\n const { task, getContexts } = makeTask(tx, []);\n\n expect((await task.run()).mode).toBe(\"none\");\n expect(getContexts).not.toHaveBeenCalled();\n });\n});\n"],
5
- "mappings": "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",
6
- "names": ["ClearSignContextType", "DeviceModelId", "Keypair", "PublicKey", "Transaction", "TransactionInstruction", "Buffer", "Right", "describe", "expect", "it", "vi", "DefaultBs58Encoder", "BuildGenericClearSignContextTask", "COMPUTE_BUDGET_PROGRAM_ID", "DUMMY_BLOCKHASH", "KNOWN_PROGRAM", "UNKNOWN_PROGRAM", "INFO_HEX", "MIN_IDL_DESCRIPTOR", "makeIx", "programId", "data", "makeRawTx", "ixs", "payer", "tx", "instructionInfoContext", "discriminator", "makeTask", "transaction", "infoContexts", "getContexts", "_input", "types", "contextModule", "task", "result"]
4
+ "sourcesContent": ["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {\n type ClearSignContext,\n ClearSignContextType,\n type ContextModule,\n} from \"@ledgerhq/context-module\";\nimport { DeviceModelId } from \"@ledgerhq/device-management-kit\";\nimport {\n Keypair,\n PublicKey,\n Transaction,\n TransactionInstruction,\n} from \"@solana/web3.js\";\nimport { Buffer } from \"buffer\";\nimport { Right } from \"purify-ts\";\nimport { describe, expect, it, vi } from \"vitest\";\n\nimport { DefaultBs58Encoder } from \"@internal/app-binder/services/bs58Encoder\";\n\nimport {\n BuildGenericClearSignContextTask,\n COMPUTE_BUDGET_PROGRAM_ID,\n} from \"./BuildGenericClearSignContextTask\";\n\nconst DUMMY_BLOCKHASH = DefaultBs58Encoder.encode(\n new Uint8Array(32).fill(0xaa),\n);\nconst KNOWN_PROGRAM = new PublicKey(\n \"9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin\",\n);\nconst UNKNOWN_PROGRAM = new PublicKey(\n \"MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr\",\n);\n\n// Dummy signed TLV hex (streamed to the device; not parsed host-side).\nconst INFO_HEX = \"0001\";\n\n// Minimal-but-valid decoded type pool so buildRequirements returns Right.\nconst MIN_IDL_DESCRIPTOR = {\n typePool: [{ index: 0, kind: \"STRUCT\", refs: [] }],\n rootType: 0,\n};\n\nfunction makeIx(programId: PublicKey, data: number[]): TransactionInstruction {\n return new TransactionInstruction({\n keys: [\n {\n pubkey: Keypair.generate().publicKey,\n isSigner: false,\n isWritable: true,\n },\n ],\n programId,\n data: Buffer.from(data),\n });\n}\n\nfunction makeRawTx(ixs: TransactionInstruction[]): Uint8Array {\n const payer = Keypair.generate();\n const tx = new Transaction();\n tx.recentBlockhash = DUMMY_BLOCKHASH;\n tx.feePayer = payer.publicKey;\n tx.add(...ixs);\n tx.sign(payer);\n return tx.serialize();\n}\n\nfunction instructionInfoContext(\n programId: string,\n discriminator: string,\n infoHex: string = INFO_HEX,\n): ClearSignContext {\n return {\n type: ClearSignContextType.SOLANA_INSTRUCTION_INFO,\n payload: {\n programId,\n discriminator,\n instructionInfo: { data: infoHex, signature: \"00\" },\n substructures: [],\n enumVariants: [],\n idlDescriptor: MIN_IDL_DESCRIPTOR,\n mintAssociations: [],\n valueFlowPorts: [],\n accountResets: [],\n displayFields: [],\n },\n } as any;\n}\n\nfunction makeTask(transaction: Uint8Array, infoContexts: ClearSignContext[]) {\n const getContexts = vi.fn(async (_input: unknown, types: unknown) =>\n (types as ClearSignContextType[]).includes(\n ClearSignContextType.SOLANA_INSTRUCTION_INFO,\n )\n ? infoContexts\n : [],\n );\n const contextModule = { getContexts } as unknown as ContextModule;\n const task = new BuildGenericClearSignContextTask({\n contextModule,\n transaction,\n deviceModelId: DeviceModelId.STAX,\n loggerFactory: () =>\n ({\n debug: vi.fn(),\n info: vi.fn(),\n warn: vi.fn(),\n error: vi.fn(),\n }) as any,\n // Stub the enum decoder (the minimal fixture pool isn't real-decodable).\n selectEnumVariants: () => Right([]),\n });\n return { task, getContexts };\n}\n\ndescribe(\"BuildGenericClearSignContextTask\", () => {\n it(\"returns mode `full` and a template when every non-ComputeBudget instruction is recognized\", async () => {\n const tx = makeRawTx([\n makeIx(new PublicKey(COMPUTE_BUDGET_PROGRAM_ID), [0x02, 0x40, 0x42]),\n makeIx(KNOWN_PROGRAM, [0x01, 0x02, 0xaa]),\n ]);\n const { task, getContexts } = makeTask(tx, [\n instructionInfoContext(KNOWN_PROGRAM.toBase58(), \"0102\"),\n ]);\n\n const result = await task.run();\n\n expect(result.mode).toBe(\"full\");\n expect(result.instructionInfoContexts).toHaveLength(1);\n // ComputeBudget is never looked up in CAL.\n expect(getContexts).toHaveBeenCalledWith(\n expect.objectContaining({\n instructions: [{ programId: KNOWN_PROGRAM.toBase58() }],\n }),\n [ClearSignContextType.SOLANA_INSTRUCTION_INFO],\n );\n });\n\n it(\"matches a descriptor without a discriminator against any instruction data\", async () => {\n // Single-instruction programs (e.g. SPL Memo `addMemo`) have no\n // discriminator: CAL omits `discriminator_hex` and the whole instruction\n // data is arguments.\n const tx = makeRawTx([makeIx(KNOWN_PROGRAM, [0x68, 0x69])]);\n const { task } = makeTask(tx, [\n instructionInfoContext(KNOWN_PROGRAM.toBase58(), \"\"),\n ]);\n\n const result = await task.run();\n\n expect(result.mode).toBe(\"full\");\n expect(result.instructionInfoContexts).toHaveLength(1);\n });\n\n it(\"prefers the most specific descriptor over a discriminator-less one\", async () => {\n const tx = makeRawTx([makeIx(KNOWN_PROGRAM, [0x01, 0x02, 0xaa])]);\n const { task } = makeTask(tx, [\n instructionInfoContext(KNOWN_PROGRAM.toBase58(), \"\", \"aaaa\"),\n instructionInfoContext(KNOWN_PROGRAM.toBase58(), \"0102\", \"bbbb\"),\n ]);\n\n const result = await task.run();\n\n expect(result.mode).toBe(\"full\");\n expect(result.instructionInfoContexts).toEqual([\n instructionInfoContext(KNOWN_PROGRAM.toBase58(), \"0102\", \"bbbb\"),\n ]);\n });\n\n it(\"returns mode `none` when some instructions are unrecognized\", async () => {\n // Any unrecognized instruction causes FINALIZE to fail on the device\n // (cs_transaction_finalize walks all instructions), so we bail to legacy\n // basic sign from a clean state rather than attempting generic clear-signing.\n const tx = makeRawTx([\n makeIx(KNOWN_PROGRAM, [0x01, 0x02]),\n makeIx(UNKNOWN_PROGRAM, [0x09]),\n ]);\n const { task } = makeTask(tx, [\n instructionInfoContext(KNOWN_PROGRAM.toBase58(), \"0102\"),\n ]);\n\n const result = await task.run();\n\n expect(result.mode).toBe(\"none\");\n expect(result.instructionInfoContexts).toHaveLength(0);\n });\n\n it(\"returns mode `none` when nothing is recognized\", async () => {\n const tx = makeRawTx([makeIx(UNKNOWN_PROGRAM, [0x09])]);\n const { task } = makeTask(tx, []);\n\n expect((await task.run()).mode).toBe(\"none\");\n });\n\n it(\"returns mode `none` for a ComputeBudget-only tx without calling CAL\", async () => {\n const tx = makeRawTx([\n makeIx(new PublicKey(COMPUTE_BUDGET_PROGRAM_ID), [0x02, 0x40, 0x42]),\n ]);\n const { task, getContexts } = makeTask(tx, []);\n\n expect((await task.run()).mode).toBe(\"none\");\n expect(getContexts).not.toHaveBeenCalled();\n });\n});\n"],
5
+ "mappings": "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",
6
+ "names": ["ClearSignContextType", "DeviceModelId", "Keypair", "PublicKey", "Transaction", "TransactionInstruction", "Buffer", "Right", "describe", "expect", "it", "vi", "DefaultBs58Encoder", "BuildGenericClearSignContextTask", "COMPUTE_BUDGET_PROGRAM_ID", "DUMMY_BLOCKHASH", "KNOWN_PROGRAM", "UNKNOWN_PROGRAM", "INFO_HEX", "MIN_IDL_DESCRIPTOR", "makeIx", "programId", "data", "makeRawTx", "ixs", "payer", "tx", "instructionInfoContext", "discriminator", "infoHex", "makeTask", "transaction", "infoContexts", "getContexts", "_input", "types", "contextModule", "task", "result"]
7
7
  }
@@ -63,5 +63,5 @@
63
63
  "watch:builds": "pnpm ldmk-tool watch --entryPoints src/index.ts,src/**/*.ts --tsconfig tsconfig.prod.json",
64
64
  "watch:types": "concurrently \"tsc --watch -p tsconfig.prod.json\" \"tsc-alias --watch -p tsconfig.prod.json\""
65
65
  },
66
- "version": "0.0.0-develop-20260811001235"
66
+ "version": "0.0.0-develop-20260813001639"
67
67
  }
@@ -1 +1 @@
1
- {"version":3,"file":"BuildGenericClearSignContextTask.d.ts","sourceRoot":"","sources":["../../../../../src/internal/app-binder/task/BuildGenericClearSignContextTask.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,gBAAgB,EAErB,KAAK,aAAa,EAEnB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,KAAK,aAAa,EAElB,KAAK,sBAAsB,EAC5B,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,kDAAkD,CAAC;AAKtF,OAAO,EACL,KAAK,WAAW,EAEhB,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,EAI5B,MAAM,8CAA8C,CAAC;AAItD;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,gDACS,CAAC;AAEhD,eAAO,MAAM,eAAe,mBAAmB,CAAC;AAGhD,gFAAgF;AAChF,MAAM,MAAM,0BAA0B,GAAG,IAAI,CAC3C,sBAAsB,EACtB,oBAAoB,GAAG,gBAAgB,GAAG,cAAc,CACzD,GAAG;IACF,oFAAoF;IACpF,kBAAkB,EAAE,WAAW,EAAE,CAAC;IAClC,4GAA4G;IAC5G,WAAW,EAAE,WAAW,EAAE,CAAC;CAC5B,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,uBAAuB,GAAG;IACpC,2EAA2E;IAC3E,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,kFAAkF;IAClF,QAAQ,CAAC,YAAY,EAAE,gBAAgB,EAAE,CAAC;IAC1C,6FAA6F;IAC7F,QAAQ,CAAC,uBAAuB,EAAE,gBAAgB,EAAE,CAAC;IACrD,mFAAmF;IACnF,QAAQ,CAAC,0BAA0B,EAAE,0BAA0B,CAAC;CACjE,CAAC;AAEF,MAAM,MAAM,oCAAoC,GAAG;IACjD,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IACtC,QAAQ,CAAC,WAAW,EAAE,UAAU,CAAC;IACjC,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IACtC,QAAQ,CAAC,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,sBAAsB,CAAC;IAChE,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,6EAA6E;IAC7E,QAAQ,CAAC,kBAAkB,CAAC,EAAE,wBAAwB,CAAC,oBAAoB,CAAC,CAAC;CAC9E,CAAC;AAEF;;;;;;;;GAQG;AACH,qBAAa,gCAAgC;IAI/B,OAAO,CAAC,QAAQ,CAAC,IAAI;IAHjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyB;IAChD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAEJ,IAAI,EAAE,oCAAoC;IAKjE,GAAG,IAAI,OAAO,CAAC,uBAAuB,CAAC;IAiM7C,8FAA8F;YAChF,iBAAiB;IAiB/B,8FAA8F;IAC9F,OAAO,CAAC,oBAAoB;IAmC5B,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,oBAAoB;IAY5B,OAAO,CAAC,uBAAuB;IAiB/B,OAAO,CAAC,WAAW;IAenB,OAAO,CAAC,qBAAqB;CAiB9B"}
1
+ {"version":3,"file":"BuildGenericClearSignContextTask.d.ts","sourceRoot":"","sources":["../../../../../src/internal/app-binder/task/BuildGenericClearSignContextTask.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,gBAAgB,EAErB,KAAK,aAAa,EAEnB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,KAAK,aAAa,EAElB,KAAK,sBAAsB,EAC5B,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,kDAAkD,CAAC;AAKtF,OAAO,EACL,KAAK,WAAW,EAEhB,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,EAI5B,MAAM,8CAA8C,CAAC;AAItD;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,gDACS,CAAC;AAEhD,eAAO,MAAM,eAAe,mBAAmB,CAAC;AAGhD,gFAAgF;AAChF,MAAM,MAAM,0BAA0B,GAAG,IAAI,CAC3C,sBAAsB,EACtB,oBAAoB,GAAG,gBAAgB,GAAG,cAAc,CACzD,GAAG;IACF,oFAAoF;IACpF,kBAAkB,EAAE,WAAW,EAAE,CAAC;IAClC,4GAA4G;IAC5G,WAAW,EAAE,WAAW,EAAE,CAAC;CAC5B,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,uBAAuB,GAAG;IACpC,2EAA2E;IAC3E,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,kFAAkF;IAClF,QAAQ,CAAC,YAAY,EAAE,gBAAgB,EAAE,CAAC;IAC1C,6FAA6F;IAC7F,QAAQ,CAAC,uBAAuB,EAAE,gBAAgB,EAAE,CAAC;IACrD,mFAAmF;IACnF,QAAQ,CAAC,0BAA0B,EAAE,0BAA0B,CAAC;CACjE,CAAC;AAEF,MAAM,MAAM,oCAAoC,GAAG;IACjD,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IACtC,QAAQ,CAAC,WAAW,EAAE,UAAU,CAAC;IACjC,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IACtC,QAAQ,CAAC,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,sBAAsB,CAAC;IAChE,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,6EAA6E;IAC7E,QAAQ,CAAC,kBAAkB,CAAC,EAAE,wBAAwB,CAAC,oBAAoB,CAAC,CAAC;CAC9E,CAAC;AAEF;;;;;;;;GAQG;AACH,qBAAa,gCAAgC;IAI/B,OAAO,CAAC,QAAQ,CAAC,IAAI;IAHjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyB;IAChD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAEJ,IAAI,EAAE,oCAAoC;IAKjE,GAAG,IAAI,OAAO,CAAC,uBAAuB,CAAC;IAyM7C,8FAA8F;YAChF,iBAAiB;IAiB/B,8FAA8F;IAC9F,OAAO,CAAC,oBAAoB;IAmC5B,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,oBAAoB;IAe5B,OAAO,CAAC,uBAAuB;IAiB/B,OAAO,CAAC,WAAW;IAenB,OAAO,CAAC,qBAAqB;CAiB9B"}