@ledgerhq/context-module 0.0.0-develop-20260831155922 → 0.0.0-develop-20260902001426
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.
- package/lib/cjs/package.json +1 -1
- package/lib/cjs/src/modules/solana/instruction-info/data/HttpInstructionInfoDataSource.test.js +1 -1
- package/lib/cjs/src/modules/solana/instruction-info/data/HttpInstructionInfoDataSource.test.js.map +2 -2
- package/lib/cjs/src/modules/solana/instruction-info/data/InstructionInfoDto.js +1 -1
- package/lib/cjs/src/modules/solana/instruction-info/data/InstructionInfoDto.js.map +2 -2
- package/lib/cjs/src/modules/solana/instruction-info/data/InstructionInfoMapper.js +1 -1
- package/lib/cjs/src/modules/solana/instruction-info/data/InstructionInfoMapper.js.map +3 -3
- package/lib/cjs/src/modules/solana/instruction-info/data/InstructionInfoMapper.test.js +1 -1
- package/lib/cjs/src/modules/solana/instruction-info/data/InstructionInfoMapper.test.js.map +2 -2
- package/lib/cjs/src/modules/solana/instruction-info/domain/InstructionInfoContextLoader.test.js +1 -1
- package/lib/cjs/src/modules/solana/instruction-info/domain/InstructionInfoContextLoader.test.js.map +2 -2
- package/lib/cjs/src/modules/solana/model/SolanaClearSignContext.js +1 -1
- package/lib/cjs/src/modules/solana/model/SolanaClearSignContext.js.map +2 -2
- package/lib/cjs/src/modules/solana/model/SolanaPayloads.js +1 -1
- package/lib/cjs/src/modules/solana/model/SolanaPayloads.js.map +2 -2
- package/lib/esm/package.json +1 -1
- package/lib/esm/src/modules/solana/instruction-info/data/HttpInstructionInfoDataSource.test.js +1 -1
- package/lib/esm/src/modules/solana/instruction-info/data/HttpInstructionInfoDataSource.test.js.map +2 -2
- package/lib/esm/src/modules/solana/instruction-info/data/InstructionInfoDto.js +1 -1
- package/lib/esm/src/modules/solana/instruction-info/data/InstructionInfoDto.js.map +2 -2
- package/lib/esm/src/modules/solana/instruction-info/data/InstructionInfoMapper.js +1 -1
- package/lib/esm/src/modules/solana/instruction-info/data/InstructionInfoMapper.js.map +3 -3
- package/lib/esm/src/modules/solana/instruction-info/data/InstructionInfoMapper.test.js +1 -1
- package/lib/esm/src/modules/solana/instruction-info/data/InstructionInfoMapper.test.js.map +3 -3
- package/lib/esm/src/modules/solana/instruction-info/domain/InstructionInfoContextLoader.test.js +1 -1
- package/lib/esm/src/modules/solana/instruction-info/domain/InstructionInfoContextLoader.test.js.map +2 -2
- package/lib/esm/src/modules/solana/model/SolanaClearSignContext.js +1 -1
- package/lib/esm/src/modules/solana/model/SolanaClearSignContext.js.map +2 -2
- package/lib/esm/src/modules/solana/model/SolanaPayloads.js.map +2 -2
- package/lib/types/src/modules/solana/instruction-info/data/InstructionInfoDto.d.ts +19 -2
- package/lib/types/src/modules/solana/instruction-info/data/InstructionInfoDto.d.ts.map +1 -1
- package/lib/types/src/modules/solana/instruction-info/data/InstructionInfoMapper.d.ts +18 -2
- package/lib/types/src/modules/solana/instruction-info/data/InstructionInfoMapper.d.ts.map +1 -1
- package/lib/types/src/modules/solana/model/SolanaClearSignContext.d.ts +1 -1
- package/lib/types/src/modules/solana/model/SolanaClearSignContext.d.ts.map +1 -1
- package/lib/types/src/modules/solana/model/SolanaPayloads.d.ts +39 -0
- package/lib/types/src/modules/solana/model/SolanaPayloads.d.ts.map +1 -1
- package/lib/types/tsconfig.prod.tsbuildinfo +1 -1
- package/package.json +4 -4
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/modules/solana/model/SolanaClearSignContext.ts"],
|
|
4
|
-
"sourcesContent": ["import { type PkiCertificate } from \"@/modules/multichain/pki/model/PkiCertificate\";\nimport {\n type SolanaAltResolutionPayload,\n type SolanaEnumVariantPayload,\n type SolanaInstructionInfoPayload,\n type SolanaLifiPayload,\n type SolanaTokenAccountStatePayload,\n type SolanaTokenData,\n type SolanaTokenInfoPayload,\n type SolanaTransactionCheckPayload,\n} from \"@/modules/solana/model/SolanaPayloads\";\nimport {\n type ClearSignContext,\n type ClearSignContextSuccess,\n ClearSignContextType,\n} from \"@/shared/model/ClearSignContext\";\n\n// Re-export Solana payload types so consumers can import from this file\nexport type {\n SolanaAltResolutionPayload,\n SolanaCalAccountReset,\n SolanaCalDisplayField,\n SolanaCalMintAssociation,\n SolanaCalTokenValue,\n SolanaCalTypePoolEntry,\n SolanaCalValue,\n SolanaCalValueFlowPort,\n SolanaEnumVariantPayload,\n SolanaInstructionEnumVariant,\n SolanaInstructionInfoPayload,\n SolanaInstructionSubstructure,\n SolanaLifiInstructionMeta,\n SolanaLifiPayload,\n SolanaSignedDescriptor,\n SolanaTokenAccountStatePayload,\n SolanaTokenData,\n SolanaTokenInfoPayload,\n SolanaTransactionCheckPayload,\n SolanaTransactionDescriptor,\n} from \"@/modules/solana/model/SolanaPayloads\";\nexport { SolanaInstructionSubstructureKind } from \"@/modules/solana/model/SolanaPayloads\";\n\n/**\n * Solana-specific payload overrides \u2014 contributed to the shared\n * ClearSignContextSuccessPayloads map at the integration boundary.\n */\nexport type SolanaPayloadOverrides = {\n [ClearSignContextType.SOLANA_TOKEN]: {\n payload: SolanaTokenData;\n certificate?: PkiCertificate;\n };\n [ClearSignContextType.SOLANA_LIFI]: {\n payload: SolanaLifiPayload;\n certificate?: PkiCertificate;\n };\n [ClearSignContextType.SOLANA_TRUSTED_NAME]: {\n payload: Uint8Array;\n certificate?: PkiCertificate;\n };\n [ClearSignContextType.SOLANA_BASIC_TRUSTED_NAME]: {\n payload: Uint8Array;\n certificate?: PkiCertificate;\n };\n [ClearSignContextType.SOLANA_TRANSACTION_CHECK]: {\n payload: SolanaTransactionCheckPayload;\n certificate?: PkiCertificate;\n };\n [ClearSignContextType.SOLANA_INSTRUCTION_INFO]: {\n payload: SolanaInstructionInfoPayload;\n certificate?: PkiCertificate;\n };\n [ClearSignContextType.SOLANA_ENUM_VARIANT]: {\n payload: SolanaEnumVariantPayload;\n certificate?: PkiCertificate;\n };\n [ClearSignContextType.SOLANA_TOKEN_INFO]: {\n payload: SolanaTokenInfoPayload;\n certificate?: PkiCertificate;\n };\n [ClearSignContextType.SOLANA_TOKEN_ACCOUNT_STATE]: {\n payload: SolanaTokenAccountStatePayload;\n certificate?: PkiCertificate;\n };\n [ClearSignContextType.SOLANA_ALT_RESOLUTION]: {\n payload: SolanaAltResolutionPayload;\n certificate?: PkiCertificate;\n };\n};\n\nexport const SolanaContextType = {\n TOKEN: ClearSignContextType.SOLANA_TOKEN,\n LIFI: ClearSignContextType.SOLANA_LIFI,\n TRUSTED_NAME: ClearSignContextType.SOLANA_TRUSTED_NAME,\n BASIC_TRUSTED_NAME: ClearSignContextType.SOLANA_BASIC_TRUSTED_NAME,\n TRANSACTION_CHECK: ClearSignContextType.SOLANA_TRANSACTION_CHECK,\n INSTRUCTION_INFO: ClearSignContextType.SOLANA_INSTRUCTION_INFO,\n ENUM_VARIANT: ClearSignContextType.SOLANA_ENUM_VARIANT,\n TOKEN_INFO: ClearSignContextType.SOLANA_TOKEN_INFO,\n TOKEN_ACCOUNT_STATE: ClearSignContextType.SOLANA_TOKEN_ACCOUNT_STATE,\n ALT_RESOLUTION: ClearSignContextType.SOLANA_ALT_RESOLUTION,\n} as const;\n\n/**\n * Union of all Solana-relevant success context types.\n */\nexport type SolanaClearSignContextSuccessType =\n (typeof SolanaContextType)[keyof typeof SolanaContextType];\n\n/**\n * A ClearSignContextSuccess narrowed to only Solana-relevant types.\n */\nexport type SolanaClearSignContextSuccess =\n ClearSignContextSuccess<SolanaClearSignContextSuccessType>;\n\n/**\n * Set of all Solana-relevant success ClearSignContextType values.\n * Used by the type guard below to filter out non-Solana contexts at runtime.\n */\nexport const SOLANA_CLEAR_SIGN_CONTEXT_SUCCESS_TYPES =\n new Set<ClearSignContextType>(Object.values(SolanaContextType));\n\n/**\n * Type guard that narrows a ClearSignContextSuccess to a\n * SolanaClearSignContextSuccess, filtering out non-Solana types.\n */\nexport function isSolanaContextSuccess(\n ctx: ClearSignContext,\n): ctx is SolanaClearSignContextSuccess {\n return SOLANA_CLEAR_SIGN_CONTEXT_SUCCESS_TYPES.has(ctx.type);\n}\n"],
|
|
5
|
-
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,6CAAAE,EAAA,sBAAAC,EAAA,qGAAAC,IAAA,eAAAC,EAAAL,GAWA,IAAAM,EAIO,
|
|
4
|
+
"sourcesContent": ["import { type PkiCertificate } from \"@/modules/multichain/pki/model/PkiCertificate\";\nimport {\n type SolanaAltResolutionPayload,\n type SolanaEnumVariantPayload,\n type SolanaInstructionInfoPayload,\n type SolanaLifiPayload,\n type SolanaTokenAccountStatePayload,\n type SolanaTokenData,\n type SolanaTokenInfoPayload,\n type SolanaTransactionCheckPayload,\n} from \"@/modules/solana/model/SolanaPayloads\";\nimport {\n type ClearSignContext,\n type ClearSignContextSuccess,\n ClearSignContextType,\n} from \"@/shared/model/ClearSignContext\";\n\n// Re-export Solana payload types so consumers can import from this file\nexport type {\n SolanaAltResolutionPayload,\n SolanaCalAccountReset,\n SolanaCalActiveWhenPredicate,\n SolanaCalDisplayField,\n SolanaCalHideRule,\n SolanaCalMintAssociation,\n SolanaCalOwnerAssociation,\n SolanaCalTokenValue,\n SolanaCalTypePoolEntry,\n SolanaCalValue,\n SolanaCalValueFlowPort,\n SolanaEnumVariantPayload,\n SolanaInstructionEnumVariant,\n SolanaInstructionInfoPayload,\n SolanaInstructionSubstructure,\n SolanaLifiInstructionMeta,\n SolanaLifiPayload,\n SolanaSignedDescriptor,\n SolanaTokenAccountStatePayload,\n SolanaTokenData,\n SolanaTokenInfoPayload,\n SolanaTransactionCheckPayload,\n SolanaTransactionDescriptor,\n} from \"@/modules/solana/model/SolanaPayloads\";\nexport { SolanaInstructionSubstructureKind } from \"@/modules/solana/model/SolanaPayloads\";\n\n/**\n * Solana-specific payload overrides \u2014 contributed to the shared\n * ClearSignContextSuccessPayloads map at the integration boundary.\n */\nexport type SolanaPayloadOverrides = {\n [ClearSignContextType.SOLANA_TOKEN]: {\n payload: SolanaTokenData;\n certificate?: PkiCertificate;\n };\n [ClearSignContextType.SOLANA_LIFI]: {\n payload: SolanaLifiPayload;\n certificate?: PkiCertificate;\n };\n [ClearSignContextType.SOLANA_TRUSTED_NAME]: {\n payload: Uint8Array;\n certificate?: PkiCertificate;\n };\n [ClearSignContextType.SOLANA_BASIC_TRUSTED_NAME]: {\n payload: Uint8Array;\n certificate?: PkiCertificate;\n };\n [ClearSignContextType.SOLANA_TRANSACTION_CHECK]: {\n payload: SolanaTransactionCheckPayload;\n certificate?: PkiCertificate;\n };\n [ClearSignContextType.SOLANA_INSTRUCTION_INFO]: {\n payload: SolanaInstructionInfoPayload;\n certificate?: PkiCertificate;\n };\n [ClearSignContextType.SOLANA_ENUM_VARIANT]: {\n payload: SolanaEnumVariantPayload;\n certificate?: PkiCertificate;\n };\n [ClearSignContextType.SOLANA_TOKEN_INFO]: {\n payload: SolanaTokenInfoPayload;\n certificate?: PkiCertificate;\n };\n [ClearSignContextType.SOLANA_TOKEN_ACCOUNT_STATE]: {\n payload: SolanaTokenAccountStatePayload;\n certificate?: PkiCertificate;\n };\n [ClearSignContextType.SOLANA_ALT_RESOLUTION]: {\n payload: SolanaAltResolutionPayload;\n certificate?: PkiCertificate;\n };\n};\n\nexport const SolanaContextType = {\n TOKEN: ClearSignContextType.SOLANA_TOKEN,\n LIFI: ClearSignContextType.SOLANA_LIFI,\n TRUSTED_NAME: ClearSignContextType.SOLANA_TRUSTED_NAME,\n BASIC_TRUSTED_NAME: ClearSignContextType.SOLANA_BASIC_TRUSTED_NAME,\n TRANSACTION_CHECK: ClearSignContextType.SOLANA_TRANSACTION_CHECK,\n INSTRUCTION_INFO: ClearSignContextType.SOLANA_INSTRUCTION_INFO,\n ENUM_VARIANT: ClearSignContextType.SOLANA_ENUM_VARIANT,\n TOKEN_INFO: ClearSignContextType.SOLANA_TOKEN_INFO,\n TOKEN_ACCOUNT_STATE: ClearSignContextType.SOLANA_TOKEN_ACCOUNT_STATE,\n ALT_RESOLUTION: ClearSignContextType.SOLANA_ALT_RESOLUTION,\n} as const;\n\n/**\n * Union of all Solana-relevant success context types.\n */\nexport type SolanaClearSignContextSuccessType =\n (typeof SolanaContextType)[keyof typeof SolanaContextType];\n\n/**\n * A ClearSignContextSuccess narrowed to only Solana-relevant types.\n */\nexport type SolanaClearSignContextSuccess =\n ClearSignContextSuccess<SolanaClearSignContextSuccessType>;\n\n/**\n * Set of all Solana-relevant success ClearSignContextType values.\n * Used by the type guard below to filter out non-Solana contexts at runtime.\n */\nexport const SOLANA_CLEAR_SIGN_CONTEXT_SUCCESS_TYPES =\n new Set<ClearSignContextType>(Object.values(SolanaContextType));\n\n/**\n * Type guard that narrows a ClearSignContextSuccess to a\n * SolanaClearSignContextSuccess, filtering out non-Solana types.\n */\nexport function isSolanaContextSuccess(\n ctx: ClearSignContext,\n): ctx is SolanaClearSignContextSuccess {\n return SOLANA_CLEAR_SIGN_CONTEXT_SUCCESS_TYPES.has(ctx.type);\n}\n"],
|
|
5
|
+
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,6CAAAE,EAAA,sBAAAC,EAAA,qGAAAC,IAAA,eAAAC,EAAAL,GAWA,IAAAM,EAIO,2CA4BPC,EAAkD,iDAiD3C,MAAMJ,EAAoB,CAC/B,MAAO,uBAAqB,aAC5B,KAAM,uBAAqB,YAC3B,aAAc,uBAAqB,oBACnC,mBAAoB,uBAAqB,0BACzC,kBAAmB,uBAAqB,yBACxC,iBAAkB,uBAAqB,wBACvC,aAAc,uBAAqB,oBACnC,WAAY,uBAAqB,kBACjC,oBAAqB,uBAAqB,2BAC1C,eAAgB,uBAAqB,qBACvC,EAkBaD,EACX,IAAI,IAA0B,OAAO,OAAOC,CAAiB,CAAC,EAMzD,SAASC,EACdI,EACsC,CACtC,OAAON,EAAwC,IAAIM,EAAI,IAAI,CAC7D",
|
|
6
6
|
"names": ["SolanaClearSignContext_exports", "__export", "SOLANA_CLEAR_SIGN_CONTEXT_SUCCESS_TYPES", "SolanaContextType", "isSolanaContextSuccess", "__toCommonJS", "import_ClearSignContext", "import_SolanaPayloads", "ctx"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var o=Object.defineProperty;var
|
|
1
|
+
"use strict";var o=Object.defineProperty;var l=Object.getOwnPropertyDescriptor;var s=Object.getOwnPropertyNames;var p=Object.prototype.hasOwnProperty;var c=(e,n)=>{for(var t in n)o(e,t,{get:n[t],enumerable:!0})},d=(e,n,t,r)=>{if(n&&typeof n=="object"||typeof n=="function")for(let a of s(n))!p.call(e,a)&&a!==t&&o(e,a,{get:()=>n[a],enumerable:!(r=l(n,a))||r.enumerable});return e};var g=e=>d(o({},"__esModule",{value:!0}),e);var u={};c(u,{SolanaInstructionSubstructureKind:()=>i});module.exports=g(u);var i=(a=>(a[a.DISPLAY_FIELD=0]="DISPLAY_FIELD",a[a.VALUE_FLOW_PORT=1]="VALUE_FLOW_PORT",a[a.HIDE_RULE=2]="HIDE_RULE",a[a.ACCOUNT_RESET=3]="ACCOUNT_RESET",a))(i||{});0&&(module.exports={SolanaInstructionSubstructureKind});
|
|
2
2
|
//# sourceMappingURL=SolanaPayloads.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/modules/solana/model/SolanaPayloads.ts"],
|
|
4
|
-
"sourcesContent": ["// Solana payload types \u2014 used both by Solana loaders and (type-only)\n// referenced by the shared ClearSignContext union for typed-payload variants.\n\nexport type SolanaTokenData = {\n solanaTokenDescriptor: {\n data: string;\n signature: string;\n };\n};\n\nexport type SolanaTransactionDescriptor = {\n data: string;\n descriptorType: string;\n descriptorVersion: string;\n signature: string;\n has_basis_point?: boolean;\n};\n\nexport type SolanaLifiInstructionMeta = {\n program_id: string;\n discriminator_hex?: string;\n has_basis_point?: boolean;\n};\n\nexport type SolanaLifiPayload = {\n descriptors: Record<string, SolanaTransactionDescriptor[]>;\n instructions: SolanaLifiInstructionMeta[];\n};\n\nexport type SolanaTransactionCheckPayload = {\n descriptor: string;\n};\n\n// --- Generic clear-signing payloads ---\n\n// CAL static descriptor payloads. `data` is the signed TLV (hex string);\n// `signature` is the resolved signature for the configured CAL signature\n// kind (`prod` | `test`).\n\nexport type SolanaSignedDescriptor = {\n data: string;\n signature: string;\n};\n\n/**\n * One enum-variant descriptor bundled with an instruction descriptor by CAL.\n * The signed TLV (`descriptor.data`) feeds the host-side type-pool decode\n * cache, `enumId`/`variantIndex` identify which variant it describes (and let\n * the host stream the selected variant's signed descriptor to the device).\n */\nexport type SolanaInstructionEnumVariant = {\n enumId: string;\n variantIndex: number;\n descriptor: SolanaSignedDescriptor;\n};\n\n/**\n * Payload for ClearSignContextType.SOLANA_INSTRUCTION_INFO.\n *\n * `instructionInfo` + `substructures` are the signed TLVs streamed to the\n * device, and `enumVariants` are the signed enum-variant descriptors CAL\n * bundles for the program's enums (used to build the host decode cache). The\n * remaining fields are CAL's decoded JSON consumed host-side by the\n * requirement builder.\n */\nexport type SolanaInstructionInfoPayload = {\n programId: string;\n discriminator: string;\n instructionName?: string;\n instructionInfo: SolanaSignedDescriptor;\n substructures: SolanaInstructionSubstructure[];\n enumVariants: SolanaInstructionEnumVariant[];\n idlDescriptor: {\n typePool: SolanaCalTypePoolEntry[];\n rootType: number;\n };\n mintAssociations: SolanaCalMintAssociation[];\n valueFlowPorts: SolanaCalValueFlowPort[];\n accountResets: SolanaCalAccountReset[];\n displayFields: SolanaCalDisplayField[];\n};\n\nexport enum SolanaInstructionSubstructureKind {\n DISPLAY_FIELD = 0x00,\n VALUE_FLOW_PORT = 0x01,\n HIDE_RULE = 0x02,\n ACCOUNT_RESET = 0x03,\n}\n\nexport type SolanaInstructionSubstructure = {\n kind: SolanaInstructionSubstructureKind;\n // TLV payload (hex string) for the substructure.\n data: string;\n};\n\n// --- Decoded CAL JSON (snake_case mirrors the CAL response) ---\n\nexport type SolanaCalValue = {\n source: string;\n /** ACCOUNT_PATH: index into the instruction's accounts. */\n account_index?: number;\n /** CONSTANT: hex-encoded bytes. */\n data?: string;\n /** ARGUMENT_PATH: decoded steps. */\n path?: { steps: number[] };\n};\n\nexport type SolanaCalTokenValue = {\n kind: string;\n value?: SolanaCalValue;\n account_index?: number;\n};\n\nexport type SolanaCalValueFlowPort = {\n /** Ordered candidate list of account indices (length 1 for a single-account port). */\n account_indices: number[];\n optional_account_strategy?: string;\n token_value: SolanaCalTokenValue;\n};\n\nexport type SolanaCalAccountReset = {\n account_index: number;\n require_pre_balance_zero?: boolean;\n};\n\nexport type SolanaCalDisplayField = {\n name?: string;\n param: { type: string; value?: SolanaCalValue; token?: SolanaCalValue };\n};\n\nexport type SolanaCalTypePoolEntry = {\n index: number;\n kind: string;\n refs?: number[];\n size?: number;\n encoding?: number;\n len_kind?: string;\n flag_kind?: string;\n sentinel?: string;\n disc_kind?: string;\n total_variants?: number;\n enum_id?: string;\n};\n\nexport type SolanaCalMintAssociation = {\n account_index: number;\n mint_index: number;\n};\n\n/**\n * Payload for ClearSignContextType.SOLANA_ENUM_VARIANT: one signed\n * ENUM_VARIANT descriptor for a `(programId, enumId, variantIndex)` triple.\n */\nexport type SolanaEnumVariantPayload = {\n programId: string;\n enumId: string;\n variantIndex: number;\n descriptor: SolanaSignedDescriptor;\n};\n\n/**\n * Payload for ClearSignContextType.SOLANA_TOKEN_INFO, keyed by mint pubkey.\n * Distinct from the legacy SOLANA_TOKEN context.\n */\nexport type SolanaTokenInfoPayload = {\n mint: string;\n descriptor: SolanaSignedDescriptor;\n};\n\n// --- Dynamic descriptor payloads (challenge-bound) ---\n//\n// Each payload carries the raw signed TLV bytes decoded from the backend's\n// hex `signedDescriptor`.\n\nexport type SolanaTokenAccountStatePayload = {\n descriptor: Uint8Array;\n mint?: string;\n};\n\nexport type SolanaAltResolutionPayload = {\n descriptor: Uint8Array;\n resolvedAddress?: string;\n};\n\n// SOLANA_TRUSTED_NAME (generic flow, with 2-byte length prefix) is emitted by\n// SolanaTrustedNameContextLoader. SOLANA_BASIC_TRUSTED_NAME (basic flow, raw\n// bytes) is emitted by OwnerInfoContextLoader. Both carry `payload: Uint8Array`.\n"],
|
|
5
|
-
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,uCAAAE,IAAA,eAAAC,EAAAH,
|
|
4
|
+
"sourcesContent": ["// Solana payload types \u2014 used both by Solana loaders and (type-only)\n// referenced by the shared ClearSignContext union for typed-payload variants.\n\nexport type SolanaTokenData = {\n solanaTokenDescriptor: {\n data: string;\n signature: string;\n };\n};\n\nexport type SolanaTransactionDescriptor = {\n data: string;\n descriptorType: string;\n descriptorVersion: string;\n signature: string;\n has_basis_point?: boolean;\n};\n\nexport type SolanaLifiInstructionMeta = {\n program_id: string;\n discriminator_hex?: string;\n has_basis_point?: boolean;\n};\n\nexport type SolanaLifiPayload = {\n descriptors: Record<string, SolanaTransactionDescriptor[]>;\n instructions: SolanaLifiInstructionMeta[];\n};\n\nexport type SolanaTransactionCheckPayload = {\n descriptor: string;\n};\n\n// --- Generic clear-signing payloads ---\n\n// CAL static descriptor payloads. `data` is the signed TLV (hex string);\n// `signature` is the resolved signature for the configured CAL signature\n// kind (`prod` | `test`).\n\nexport type SolanaSignedDescriptor = {\n data: string;\n signature: string;\n};\n\n/**\n * One enum-variant descriptor bundled with an instruction descriptor by CAL.\n * The signed TLV (`descriptor.data`) feeds the host-side type-pool decode\n * cache, `enumId`/`variantIndex` identify which variant it describes (and let\n * the host stream the selected variant's signed descriptor to the device).\n */\nexport type SolanaInstructionEnumVariant = {\n enumId: string;\n variantIndex: number;\n descriptor: SolanaSignedDescriptor;\n};\n\n/**\n * Payload for ClearSignContextType.SOLANA_INSTRUCTION_INFO.\n *\n * `instructionInfo` + `substructures` are the signed TLVs streamed to the\n * device, and `enumVariants` are the signed enum-variant descriptors CAL\n * bundles for the program's enums (used to build the host decode cache). The\n * remaining fields are CAL's decoded JSON consumed host-side by the\n * requirement builder.\n */\nexport type SolanaInstructionInfoPayload = {\n programId: string;\n discriminator: string;\n instructionName?: string;\n instructionInfo: SolanaSignedDescriptor;\n substructures: SolanaInstructionSubstructure[];\n enumVariants: SolanaInstructionEnumVariant[];\n idlDescriptor: {\n typePool: SolanaCalTypePoolEntry[];\n rootType: number;\n };\n mintAssociations: SolanaCalMintAssociation[];\n ownerAssociations: SolanaCalOwnerAssociation[];\n valueFlowPorts: SolanaCalValueFlowPort[];\n accountResets: SolanaCalAccountReset[];\n displayFields: SolanaCalDisplayField[];\n hideRules: SolanaCalHideRule[];\n};\n\nexport enum SolanaInstructionSubstructureKind {\n DISPLAY_FIELD = 0x00,\n VALUE_FLOW_PORT = 0x01,\n HIDE_RULE = 0x02,\n ACCOUNT_RESET = 0x03,\n}\n\nexport type SolanaInstructionSubstructure = {\n kind: SolanaInstructionSubstructureKind;\n // TLV payload (hex string) for the substructure.\n data: string;\n};\n\n// --- Decoded CAL JSON (snake_case mirrors the CAL response) ---\n\nexport type SolanaCalValue = {\n source: string;\n /** ACCOUNT_PATH: index into the instruction's accounts. */\n account_index?: number;\n /** CONSTANT: hex-encoded bytes. */\n data?: string;\n /** ARGUMENT_PATH: decoded steps. */\n path?: { steps: number[] };\n};\n\nexport type SolanaCalTokenValue = {\n kind: string;\n value?: SolanaCalValue;\n account_index?: number;\n /**\n * `RESOLVE` only: account index whose *address* the device uses as the mint\n * when the binding lookup fails through both the mint-association map and\n * `TOKEN_ACCOUNT_STATE` (`accountMintTokenNode.fallbackAccount`).\n */\n fallback_account?: number;\n};\n\n/**\n * One `VALUE_FLOW_PORT.ACTIVE_WHEN` predicate: a bare `ActiveWhenPredicate`\n * name, or `MINT_PREDICATE` with its trailing mint.\n */\nexport type SolanaCalActiveWhenPredicate =\n | string\n | { kind: string; mint?: string };\n\nexport type SolanaCalValueFlowPort = {\n /** Ordered candidate list of account indices (length 1 for a single-account port). */\n account_indices: number[];\n optional_account_strategy?: string;\n token_value: SolanaCalTokenValue;\n /** Port activation predicates; all must pass for the port to be active. */\n active_when?: SolanaCalActiveWhenPredicate[];\n};\n\n/**\n * One `HIDE_RULE` substructure: a `(rule_set_index, target, condition)` triple.\n * `condition` is non-optional in the TLV, but it stays optional here: the signed\n * substructure reaches the device either way, so a rule whose condition CAL\n * failed to name must still be surfaced \u2014 dropping it would lose the `target`\n * the device resolves for every rule.\n */\nexport type SolanaCalHideRule = {\n rule_set_index?: number;\n target?: SolanaCalValue;\n condition?: string;\n};\n\n/**\n * An `OWNER_ASSOC_ACCOUNT` / `OWNER_ASSOC_OWNER` pair: binds a token account to\n * its owner, seeding the transaction-scoped owner map the `IS_SIGNER` /\n * `IS_ANOTHER_SIGNER` predicates read.\n */\nexport type SolanaCalOwnerAssociation = {\n account_index: number;\n owner: SolanaCalValue;\n};\n\nexport type SolanaCalAccountReset = {\n account_index: number;\n require_pre_balance_zero?: boolean;\n};\n\nexport type SolanaCalDisplayField = {\n name?: string;\n param: { type: string; value?: SolanaCalValue; token?: SolanaCalValue };\n};\n\nexport type SolanaCalTypePoolEntry = {\n index: number;\n kind: string;\n refs?: number[];\n size?: number;\n encoding?: number;\n len_kind?: string;\n flag_kind?: string;\n sentinel?: string;\n disc_kind?: string;\n total_variants?: number;\n enum_id?: string;\n};\n\nexport type SolanaCalMintAssociation = {\n account_index: number;\n mint_index: number;\n};\n\n/**\n * Payload for ClearSignContextType.SOLANA_ENUM_VARIANT: one signed\n * ENUM_VARIANT descriptor for a `(programId, enumId, variantIndex)` triple.\n */\nexport type SolanaEnumVariantPayload = {\n programId: string;\n enumId: string;\n variantIndex: number;\n descriptor: SolanaSignedDescriptor;\n};\n\n/**\n * Payload for ClearSignContextType.SOLANA_TOKEN_INFO, keyed by mint pubkey.\n * Distinct from the legacy SOLANA_TOKEN context.\n */\nexport type SolanaTokenInfoPayload = {\n mint: string;\n descriptor: SolanaSignedDescriptor;\n};\n\n// --- Dynamic descriptor payloads (challenge-bound) ---\n//\n// Each payload carries the raw signed TLV bytes decoded from the backend's\n// hex `signedDescriptor`.\n\nexport type SolanaTokenAccountStatePayload = {\n descriptor: Uint8Array;\n mint?: string;\n};\n\nexport type SolanaAltResolutionPayload = {\n descriptor: Uint8Array;\n resolvedAddress?: string;\n};\n\n// SOLANA_TRUSTED_NAME (generic flow, with 2-byte length prefix) is emitted by\n// SolanaTrustedNameContextLoader. SOLANA_BASIC_TRUSTED_NAME (basic flow, raw\n// bytes) is emitted by OwnerInfoContextLoader. Both carry `payload: Uint8Array`.\n"],
|
|
5
|
+
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,uCAAAE,IAAA,eAAAC,EAAAH,GAoFO,IAAKE,OACVA,IAAA,cAAgB,GAAhB,gBACAA,IAAA,gBAAkB,GAAlB,kBACAA,IAAA,UAAY,GAAZ,YACAA,IAAA,cAAgB,GAAhB,gBAJUA,OAAA",
|
|
6
6
|
"names": ["SolanaPayloads_exports", "__export", "SolanaInstructionSubstructureKind", "__toCommonJS"]
|
|
7
7
|
}
|
package/lib/esm/package.json
CHANGED
|
@@ -58,5 +58,5 @@
|
|
|
58
58
|
"watch:builds": "pnpm ldmk-tool watch --entryPoints index.ts,src/**/*.ts --tsconfig tsconfig.prod.json",
|
|
59
59
|
"watch:types": "concurrently \"tsc --watch -p tsconfig.prod.json\" \"tsc-alias --watch -p tsconfig.prod.json\""
|
|
60
60
|
},
|
|
61
|
-
"version": "0.0.0-develop-
|
|
61
|
+
"version": "0.0.0-develop-20260902001426"
|
|
62
62
|
}
|
package/lib/esm/src/modules/solana/instruction-info/data/HttpInstructionInfoDataSource.test.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{Left as u,Right as l}from"purify-ts";import{beforeEach as g,describe as f,expect as e,it as s,vi as p}from"vitest";import{SolanaTransactionScanChainId as i}from"../../../../modules/solana/model/SolanaTransactionScanChainId";import{HttpInstructionInfoDataSource as h}from"./HttpInstructionInfoDataSource";f("HttpInstructionInfoDataSource",()=>{let r,o;const t="11111111111111111111111111111111",a="solana-mainnet",m={cal:{url:"https://global.api.prd.ledger.com/cal/v1",mode:"prod",branch:"main"}},c=[{id:t,chain_id:i.MAINNET,instructions:[{discriminator_hex:"00000000",instruction_name:"createAccount",descriptor:{data:"00010101",signatures:{prod:"prodsig",test:"testsig"}},display_fields:[],value_flow_ports:[],hide_rules:[],account_resets:[]}]}];g(()=>{p.clearAllMocks(),o={get:p.fn()},r=new h(m,o)}),s("calls CAL /solana_programs with id, chain_id and output params",async()=>{o.get.mockResolvedValue(c),await r.getInstructionInfo({programId:t,network:a}),e(o.get).toHaveBeenCalledTimes(1),e(o.get).toHaveBeenCalledWith("https://global.api.prd.ledger.com/cal/v1/solana_programs",{params:{id:t,chain_id:i.MAINNET,output:"id,chain_id,instructions",ref:"branch:main"}})}),s("maps devnet/testnet networks to their numeric chain ids",async()=>{o.get.mockResolvedValue(c),await r.getInstructionInfo({programId:t,network:"solana-devnet"}),e(o.get).toHaveBeenCalledWith("https://global.api.prd.ledger.com/cal/v1/solana_programs",e.objectContaining({params:e.objectContaining({chain_id:901})}))}),s("returns Right with each descriptor transformed into the core payload on success",async()=>{o.get.mockResolvedValue(c);const n=await r.getInstructionInfo({programId:t,network:a});e(n).toEqual(l({programId:t,descriptors:{"00000000":l({programId:t,discriminator:"00000000",instructionName:"createAccount",instructionInfo:{data:"00010101",signature:"prodsig"},substructures:[],enumVariants:[],idlDescriptor:{typePool:[],rootType:0},mintAssociations:[],valueFlowPorts:[],accountResets:[],displayFields:[]})},enumVariants:[]}))}),s("keys a descriptor without `discriminator_hex` under the empty string",async()=>{o.get.mockResolvedValue([{id:t,chain_id:i.MAINNET,instructions:[{instruction_name:"addMemo",descriptor:{data:"00010101",signatures:{prod:"prodsig",test:"testsig"}}}]}]);const n=await r.getInstructionInfo({programId:t,network:a});e(n.isRight()).toBe(!0);const{descriptors:d}=n.unsafeCoerce();e(Object.keys(d)).toEqual([""]),e(d[""].unsafeCoerce()).toEqual(e.objectContaining({programId:t,discriminator:"",instructionInfo:{data:"00010101",signature:"prodsig"}}))}),s("returns Left when the response array is empty",async()=>{o.get.mockResolvedValue([]);const n=await r.getInstructionInfo({programId:t,network:a});e(n).toEqual(u(new Error(`[ContextModule] HttpInstructionInfoDataSource: empty response for program ${t}`)))}),s("returns Left when no program object matches the requested programId",async()=>{o.get.mockResolvedValue([{id:"OtherProgram",chain_id:i.MAINNET,instructions:[]}]);const n=await r.getInstructionInfo({programId:t,network:a});e(n).toEqual(u(new Error(`[ContextModule] HttpInstructionInfoDataSource: no descriptors for program ${t}`)))}),s("returns Left (not a throw) when an instruction descriptor is malformed",async()=>{o.get.mockResolvedValue([{id:t,chain_id:i.MAINNET,instructions:[{discriminator_hex:"00000000"}]}]);const n=await r.getInstructionInfo({programId:t,network:a});e(n.isLeft()).toBe(!0),e(n.extract().message).toMatch(new RegExp(String.raw`\[ContextModule\] HttpInstructionInfoDataSource: malformed descriptors for program ${t}:`))}),s("returns Left when the HTTP client throws",async()=>{o.get.mockRejectedValue(new Error("network"));const n=await r.getInstructionInfo({programId:t,network:a});e(n).toEqual(u(new Error("[ContextModule] HttpInstructionInfoDataSource: Failed to fetch instruction descriptors: network")))})});
|
|
1
|
+
import{Left as u,Right as l}from"purify-ts";import{beforeEach as g,describe as f,expect as e,it as s,vi as p}from"vitest";import{SolanaTransactionScanChainId as i}from"../../../../modules/solana/model/SolanaTransactionScanChainId";import{HttpInstructionInfoDataSource as h}from"./HttpInstructionInfoDataSource";f("HttpInstructionInfoDataSource",()=>{let r,o;const t="11111111111111111111111111111111",a="solana-mainnet",m={cal:{url:"https://global.api.prd.ledger.com/cal/v1",mode:"prod",branch:"main"}},c=[{id:t,chain_id:i.MAINNET,instructions:[{discriminator_hex:"00000000",instruction_name:"createAccount",descriptor:{data:"00010101",signatures:{prod:"prodsig",test:"testsig"}},display_fields:[],value_flow_ports:[],hide_rules:[],account_resets:[]}]}];g(()=>{p.clearAllMocks(),o={get:p.fn()},r=new h(m,o)}),s("calls CAL /solana_programs with id, chain_id and output params",async()=>{o.get.mockResolvedValue(c),await r.getInstructionInfo({programId:t,network:a}),e(o.get).toHaveBeenCalledTimes(1),e(o.get).toHaveBeenCalledWith("https://global.api.prd.ledger.com/cal/v1/solana_programs",{params:{id:t,chain_id:i.MAINNET,output:"id,chain_id,instructions",ref:"branch:main"}})}),s("maps devnet/testnet networks to their numeric chain ids",async()=>{o.get.mockResolvedValue(c),await r.getInstructionInfo({programId:t,network:"solana-devnet"}),e(o.get).toHaveBeenCalledWith("https://global.api.prd.ledger.com/cal/v1/solana_programs",e.objectContaining({params:e.objectContaining({chain_id:901})}))}),s("returns Right with each descriptor transformed into the core payload on success",async()=>{o.get.mockResolvedValue(c);const n=await r.getInstructionInfo({programId:t,network:a});e(n).toEqual(l({programId:t,descriptors:{"00000000":l({programId:t,discriminator:"00000000",instructionName:"createAccount",instructionInfo:{data:"00010101",signature:"prodsig"},substructures:[],enumVariants:[],idlDescriptor:{typePool:[],rootType:0},mintAssociations:[],ownerAssociations:[],valueFlowPorts:[],accountResets:[],displayFields:[],hideRules:[]})},enumVariants:[]}))}),s("keys a descriptor without `discriminator_hex` under the empty string",async()=>{o.get.mockResolvedValue([{id:t,chain_id:i.MAINNET,instructions:[{instruction_name:"addMemo",descriptor:{data:"00010101",signatures:{prod:"prodsig",test:"testsig"}}}]}]);const n=await r.getInstructionInfo({programId:t,network:a});e(n.isRight()).toBe(!0);const{descriptors:d}=n.unsafeCoerce();e(Object.keys(d)).toEqual([""]),e(d[""].unsafeCoerce()).toEqual(e.objectContaining({programId:t,discriminator:"",instructionInfo:{data:"00010101",signature:"prodsig"}}))}),s("returns Left when the response array is empty",async()=>{o.get.mockResolvedValue([]);const n=await r.getInstructionInfo({programId:t,network:a});e(n).toEqual(u(new Error(`[ContextModule] HttpInstructionInfoDataSource: empty response for program ${t}`)))}),s("returns Left when no program object matches the requested programId",async()=>{o.get.mockResolvedValue([{id:"OtherProgram",chain_id:i.MAINNET,instructions:[]}]);const n=await r.getInstructionInfo({programId:t,network:a});e(n).toEqual(u(new Error(`[ContextModule] HttpInstructionInfoDataSource: no descriptors for program ${t}`)))}),s("returns Left (not a throw) when an instruction descriptor is malformed",async()=>{o.get.mockResolvedValue([{id:t,chain_id:i.MAINNET,instructions:[{discriminator_hex:"00000000"}]}]);const n=await r.getInstructionInfo({programId:t,network:a});e(n.isLeft()).toBe(!0),e(n.extract().message).toMatch(new RegExp(String.raw`\[ContextModule\] HttpInstructionInfoDataSource: malformed descriptors for program ${t}:`))}),s("returns Left when the HTTP client throws",async()=>{o.get.mockRejectedValue(new Error("network"));const n=await r.getInstructionInfo({programId:t,network:a});e(n).toEqual(u(new Error("[ContextModule] HttpInstructionInfoDataSource: Failed to fetch instruction descriptors: network")))})});
|
|
2
2
|
//# sourceMappingURL=HttpInstructionInfoDataSource.test.js.map
|
package/lib/esm/src/modules/solana/instruction-info/data/HttpInstructionInfoDataSource.test.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../../src/modules/solana/instruction-info/data/HttpInstructionInfoDataSource.test.ts"],
|
|
4
|
-
"sourcesContent": ["import { type DmkNetworkClient } from \"@ledgerhq/device-management-kit\";\nimport { Left, Right } from \"purify-ts\";\nimport { beforeEach, describe, expect, it, vi } from \"vitest\";\n\nimport { type ContextModuleServiceConfig } from \"@/config/model/ContextModuleConfig\";\nimport { SolanaTransactionScanChainId } from \"@/modules/solana/model/SolanaTransactionScanChainId\";\n\nimport { HttpInstructionInfoDataSource } from \"./HttpInstructionInfoDataSource\";\nimport { type InstructionInfoDataSource } from \"./InstructionInfoDataSource\";\nimport { type CalInstructionInfoResponseDto } from \"./InstructionInfoDto\";\n\ndescribe(\"HttpInstructionInfoDataSource\", () => {\n let datasource: InstructionInfoDataSource;\n let httpMock: { get: ReturnType<typeof vi.fn> };\n const programId = \"11111111111111111111111111111111\";\n const network = \"solana-mainnet\";\n const config: ContextModuleServiceConfig = {\n cal: {\n url: \"https://global.api.prd.ledger.com/cal/v1\",\n mode: \"prod\",\n branch: \"main\",\n },\n } as ContextModuleServiceConfig;\n\n const successResponse: CalInstructionInfoResponseDto = [\n {\n id: programId,\n chain_id: SolanaTransactionScanChainId.MAINNET,\n instructions: [\n {\n discriminator_hex: \"00000000\",\n instruction_name: \"createAccount\",\n descriptor: {\n data: \"00010101\",\n signatures: { prod: \"prodsig\", test: \"testsig\" },\n },\n display_fields: [],\n value_flow_ports: [],\n hide_rules: [],\n account_resets: [],\n },\n ],\n },\n ];\n\n beforeEach(() => {\n vi.clearAllMocks();\n httpMock = { get: vi.fn() };\n datasource = new HttpInstructionInfoDataSource(\n config,\n httpMock as unknown as DmkNetworkClient,\n );\n });\n\n it(\"calls CAL /solana_programs with id, chain_id and output params\", async () => {\n httpMock.get.mockResolvedValue(successResponse);\n\n await datasource.getInstructionInfo({ programId, network });\n\n expect(httpMock.get).toHaveBeenCalledTimes(1);\n expect(httpMock.get).toHaveBeenCalledWith(\n \"https://global.api.prd.ledger.com/cal/v1/solana_programs\",\n {\n params: {\n id: programId,\n chain_id: SolanaTransactionScanChainId.MAINNET,\n output: \"id,chain_id,instructions\",\n ref: \"branch:main\",\n },\n },\n );\n });\n\n it(\"maps devnet/testnet networks to their numeric chain ids\", async () => {\n httpMock.get.mockResolvedValue(successResponse);\n\n await datasource.getInstructionInfo({\n programId,\n network: \"solana-devnet\",\n });\n\n expect(httpMock.get).toHaveBeenCalledWith(\n \"https://global.api.prd.ledger.com/cal/v1/solana_programs\",\n expect.objectContaining({\n params: expect.objectContaining({ chain_id: 901 }),\n }),\n );\n });\n\n it(\"returns Right with each descriptor transformed into the core payload on success\", async () => {\n httpMock.get.mockResolvedValue(successResponse);\n\n const result = await datasource.getInstructionInfo({ programId, network });\n\n expect(result).toEqual(\n Right({\n programId,\n descriptors: {\n \"00000000\": Right({\n programId,\n discriminator: \"00000000\",\n instructionName: \"createAccount\",\n instructionInfo: { data: \"00010101\", signature: \"prodsig\" },\n substructures: [],\n enumVariants: [],\n idlDescriptor: { typePool: [], rootType: 0 },\n mintAssociations: [],\n valueFlowPorts: [],\n accountResets: [],\n displayFields: [],\n }),\n },\n enumVariants: [],\n }),\n );\n });\n\n it(\"keys a descriptor without `discriminator_hex` under the empty string\", async () => {\n // Single-instruction programs (e.g. SPL Memo `addMemo`) genuinely have no\n // discriminator, so CAL omits the field.\n httpMock.get.mockResolvedValue([\n {\n id: programId,\n chain_id: SolanaTransactionScanChainId.MAINNET,\n instructions: [\n {\n instruction_name: \"addMemo\",\n descriptor: {\n data: \"00010101\",\n signatures: { prod: \"prodsig\", test: \"testsig\" },\n },\n },\n ],\n },\n ]);\n\n const result = await datasource.getInstructionInfo({ programId, network });\n\n expect(result.isRight()).toBe(true);\n const { descriptors } = result.unsafeCoerce();\n expect(Object.keys(descriptors)).toEqual([\"\"]);\n expect(descriptors[\"\"]!.unsafeCoerce()).toEqual(\n expect.objectContaining({\n programId,\n discriminator: \"\",\n instructionInfo: { data: \"00010101\", signature: \"prodsig\" },\n }),\n );\n });\n\n it(\"returns Left when the response array is empty\", async () => {\n httpMock.get.mockResolvedValue([]);\n\n const result = await datasource.getInstructionInfo({ programId, network });\n\n expect(result).toEqual(\n Left(\n new Error(\n `[ContextModule] HttpInstructionInfoDataSource: empty response for program ${programId}`,\n ),\n ),\n );\n });\n\n it(\"returns Left when no program object matches the requested programId\", async () => {\n httpMock.get.mockResolvedValue([\n {\n id: \"OtherProgram\",\n chain_id: SolanaTransactionScanChainId.MAINNET,\n instructions: [],\n },\n ]);\n\n const result = await datasource.getInstructionInfo({ programId, network });\n\n expect(result).toEqual(\n Left(\n new Error(\n `[ContextModule] HttpInstructionInfoDataSource: no descriptors for program ${programId}`,\n ),\n ),\n );\n });\n\n it(\"returns Left (not a throw) when an instruction descriptor is malformed\", async () => {\n // `descriptor` missing on the instruction \u2014 would crash the loader if the\n // datasource handed it through unvalidated.\n httpMock.get.mockResolvedValue([\n {\n id: programId,\n chain_id: SolanaTransactionScanChainId.MAINNET,\n instructions: [{ discriminator_hex: \"00000000\" }],\n },\n ]);\n\n const result = await datasource.getInstructionInfo({ programId, network });\n\n expect(result.isLeft()).toBe(true);\n expect((result.extract() as Error).message).toMatch(\n new RegExp(\n String.raw`\\[ContextModule\\] HttpInstructionInfoDataSource: malformed descriptors for program ${programId}:`,\n ),\n );\n });\n\n it(\"returns Left when the HTTP client throws\", async () => {\n httpMock.get.mockRejectedValue(new Error(\"network\"));\n\n const result = await datasource.getInstructionInfo({ programId, network });\n\n expect(result).toEqual(\n Left(\n new Error(\n \"[ContextModule] HttpInstructionInfoDataSource: Failed to fetch instruction descriptors: network\",\n ),\n ),\n );\n });\n});\n"],
|
|
5
|
-
"mappings": "AACA,OAAS,QAAAA,EAAM,SAAAC,MAAa,YAC5B,OAAS,cAAAC,EAAY,YAAAC,EAAU,UAAAC,EAAQ,MAAAC,EAAI,MAAAC,MAAU,SAGrD,OAAS,gCAAAC,MAAoC,sDAE7C,OAAS,iCAAAC,MAAqC,kCAI9CL,EAAS,gCAAiC,IAAM,CAC9C,IAAIM,EACAC,EACJ,MAAMC,EAAY,mCACZC,EAAU,iBACVC,EAAqC,CACzC,IAAK,CACH,IAAK,2CACL,KAAM,OACN,OAAQ,MACV,CACF,EAEMC,EAAiD,CACrD,CACE,GAAIH,EACJ,SAAUJ,EAA6B,QACvC,aAAc,CACZ,CACE,kBAAmB,WACnB,iBAAkB,gBAClB,WAAY,CACV,KAAM,WACN,WAAY,CAAE,KAAM,UAAW,KAAM,SAAU,CACjD,EACA,eAAgB,CAAC,EACjB,iBAAkB,CAAC,EACnB,WAAY,CAAC,EACb,eAAgB,CAAC,CACnB,CACF,CACF,CACF,EAEAL,EAAW,IAAM,CACfI,EAAG,cAAc,EACjBI,EAAW,CAAE,IAAKJ,EAAG,GAAG,CAAE,EAC1BG,EAAa,IAAID,EACfK,EACAH,CACF,CACF,CAAC,EAEDL,EAAG,iEAAkE,SAAY,CAC/EK,EAAS,IAAI,kBAAkBI,CAAe,EAE9C,MAAML,EAAW,mBAAmB,CAAE,UAAAE,EAAW,QAAAC,CAAQ,CAAC,EAE1DR,EAAOM,EAAS,GAAG,EAAE,sBAAsB,CAAC,EAC5CN,EAAOM,EAAS,GAAG,EAAE,qBACnB,2DACA,CACE,OAAQ,CACN,GAAIC,EACJ,SAAUJ,EAA6B,QACvC,OAAQ,2BACR,IAAK,aACP,CACF,CACF,CACF,CAAC,EAEDF,EAAG,0DAA2D,SAAY,CACxEK,EAAS,IAAI,kBAAkBI,CAAe,EAE9C,MAAML,EAAW,mBAAmB,CAClC,UAAAE,EACA,QAAS,eACX,CAAC,EAEDP,EAAOM,EAAS,GAAG,EAAE,qBACnB,2DACAN,EAAO,iBAAiB,CACtB,OAAQA,EAAO,iBAAiB,CAAE,SAAU,GAAI,CAAC,CACnD,CAAC,CACH,CACF,CAAC,EAEDC,EAAG,kFAAmF,SAAY,CAChGK,EAAS,IAAI,kBAAkBI,CAAe,EAE9C,MAAMC,EAAS,MAAMN,EAAW,mBAAmB,CAAE,UAAAE,EAAW,QAAAC,CAAQ,CAAC,EAEzER,EAAOW,CAAM,EAAE,QACbd,EAAM,CACJ,UAAAU,EACA,YAAa,CACX,WAAYV,EAAM,CAChB,UAAAU,EACA,cAAe,WACf,gBAAiB,gBACjB,gBAAiB,CAAE,KAAM,WAAY,UAAW,SAAU,EAC1D,cAAe,CAAC,EAChB,aAAc,CAAC,EACf,cAAe,CAAE,SAAU,CAAC,EAAG,SAAU,CAAE,EAC3C,iBAAkB,CAAC,EACnB,eAAgB,CAAC,EACjB,cAAe,CAAC,EAChB,cAAe,CAAC,
|
|
4
|
+
"sourcesContent": ["import { type DmkNetworkClient } from \"@ledgerhq/device-management-kit\";\nimport { Left, Right } from \"purify-ts\";\nimport { beforeEach, describe, expect, it, vi } from \"vitest\";\n\nimport { type ContextModuleServiceConfig } from \"@/config/model/ContextModuleConfig\";\nimport { SolanaTransactionScanChainId } from \"@/modules/solana/model/SolanaTransactionScanChainId\";\n\nimport { HttpInstructionInfoDataSource } from \"./HttpInstructionInfoDataSource\";\nimport { type InstructionInfoDataSource } from \"./InstructionInfoDataSource\";\nimport { type CalInstructionInfoResponseDto } from \"./InstructionInfoDto\";\n\ndescribe(\"HttpInstructionInfoDataSource\", () => {\n let datasource: InstructionInfoDataSource;\n let httpMock: { get: ReturnType<typeof vi.fn> };\n const programId = \"11111111111111111111111111111111\";\n const network = \"solana-mainnet\";\n const config: ContextModuleServiceConfig = {\n cal: {\n url: \"https://global.api.prd.ledger.com/cal/v1\",\n mode: \"prod\",\n branch: \"main\",\n },\n } as ContextModuleServiceConfig;\n\n const successResponse: CalInstructionInfoResponseDto = [\n {\n id: programId,\n chain_id: SolanaTransactionScanChainId.MAINNET,\n instructions: [\n {\n discriminator_hex: \"00000000\",\n instruction_name: \"createAccount\",\n descriptor: {\n data: \"00010101\",\n signatures: { prod: \"prodsig\", test: \"testsig\" },\n },\n display_fields: [],\n value_flow_ports: [],\n hide_rules: [],\n account_resets: [],\n },\n ],\n },\n ];\n\n beforeEach(() => {\n vi.clearAllMocks();\n httpMock = { get: vi.fn() };\n datasource = new HttpInstructionInfoDataSource(\n config,\n httpMock as unknown as DmkNetworkClient,\n );\n });\n\n it(\"calls CAL /solana_programs with id, chain_id and output params\", async () => {\n httpMock.get.mockResolvedValue(successResponse);\n\n await datasource.getInstructionInfo({ programId, network });\n\n expect(httpMock.get).toHaveBeenCalledTimes(1);\n expect(httpMock.get).toHaveBeenCalledWith(\n \"https://global.api.prd.ledger.com/cal/v1/solana_programs\",\n {\n params: {\n id: programId,\n chain_id: SolanaTransactionScanChainId.MAINNET,\n output: \"id,chain_id,instructions\",\n ref: \"branch:main\",\n },\n },\n );\n });\n\n it(\"maps devnet/testnet networks to their numeric chain ids\", async () => {\n httpMock.get.mockResolvedValue(successResponse);\n\n await datasource.getInstructionInfo({\n programId,\n network: \"solana-devnet\",\n });\n\n expect(httpMock.get).toHaveBeenCalledWith(\n \"https://global.api.prd.ledger.com/cal/v1/solana_programs\",\n expect.objectContaining({\n params: expect.objectContaining({ chain_id: 901 }),\n }),\n );\n });\n\n it(\"returns Right with each descriptor transformed into the core payload on success\", async () => {\n httpMock.get.mockResolvedValue(successResponse);\n\n const result = await datasource.getInstructionInfo({ programId, network });\n\n expect(result).toEqual(\n Right({\n programId,\n descriptors: {\n \"00000000\": Right({\n programId,\n discriminator: \"00000000\",\n instructionName: \"createAccount\",\n instructionInfo: { data: \"00010101\", signature: \"prodsig\" },\n substructures: [],\n enumVariants: [],\n idlDescriptor: { typePool: [], rootType: 0 },\n mintAssociations: [],\n ownerAssociations: [],\n valueFlowPorts: [],\n accountResets: [],\n displayFields: [],\n hideRules: [],\n }),\n },\n enumVariants: [],\n }),\n );\n });\n\n it(\"keys a descriptor without `discriminator_hex` under the empty string\", async () => {\n // Single-instruction programs (e.g. SPL Memo `addMemo`) genuinely have no\n // discriminator, so CAL omits the field.\n httpMock.get.mockResolvedValue([\n {\n id: programId,\n chain_id: SolanaTransactionScanChainId.MAINNET,\n instructions: [\n {\n instruction_name: \"addMemo\",\n descriptor: {\n data: \"00010101\",\n signatures: { prod: \"prodsig\", test: \"testsig\" },\n },\n },\n ],\n },\n ]);\n\n const result = await datasource.getInstructionInfo({ programId, network });\n\n expect(result.isRight()).toBe(true);\n const { descriptors } = result.unsafeCoerce();\n expect(Object.keys(descriptors)).toEqual([\"\"]);\n expect(descriptors[\"\"]!.unsafeCoerce()).toEqual(\n expect.objectContaining({\n programId,\n discriminator: \"\",\n instructionInfo: { data: \"00010101\", signature: \"prodsig\" },\n }),\n );\n });\n\n it(\"returns Left when the response array is empty\", async () => {\n httpMock.get.mockResolvedValue([]);\n\n const result = await datasource.getInstructionInfo({ programId, network });\n\n expect(result).toEqual(\n Left(\n new Error(\n `[ContextModule] HttpInstructionInfoDataSource: empty response for program ${programId}`,\n ),\n ),\n );\n });\n\n it(\"returns Left when no program object matches the requested programId\", async () => {\n httpMock.get.mockResolvedValue([\n {\n id: \"OtherProgram\",\n chain_id: SolanaTransactionScanChainId.MAINNET,\n instructions: [],\n },\n ]);\n\n const result = await datasource.getInstructionInfo({ programId, network });\n\n expect(result).toEqual(\n Left(\n new Error(\n `[ContextModule] HttpInstructionInfoDataSource: no descriptors for program ${programId}`,\n ),\n ),\n );\n });\n\n it(\"returns Left (not a throw) when an instruction descriptor is malformed\", async () => {\n // `descriptor` missing on the instruction \u2014 would crash the loader if the\n // datasource handed it through unvalidated.\n httpMock.get.mockResolvedValue([\n {\n id: programId,\n chain_id: SolanaTransactionScanChainId.MAINNET,\n instructions: [{ discriminator_hex: \"00000000\" }],\n },\n ]);\n\n const result = await datasource.getInstructionInfo({ programId, network });\n\n expect(result.isLeft()).toBe(true);\n expect((result.extract() as Error).message).toMatch(\n new RegExp(\n String.raw`\\[ContextModule\\] HttpInstructionInfoDataSource: malformed descriptors for program ${programId}:`,\n ),\n );\n });\n\n it(\"returns Left when the HTTP client throws\", async () => {\n httpMock.get.mockRejectedValue(new Error(\"network\"));\n\n const result = await datasource.getInstructionInfo({ programId, network });\n\n expect(result).toEqual(\n Left(\n new Error(\n \"[ContextModule] HttpInstructionInfoDataSource: Failed to fetch instruction descriptors: network\",\n ),\n ),\n );\n });\n});\n"],
|
|
5
|
+
"mappings": "AACA,OAAS,QAAAA,EAAM,SAAAC,MAAa,YAC5B,OAAS,cAAAC,EAAY,YAAAC,EAAU,UAAAC,EAAQ,MAAAC,EAAI,MAAAC,MAAU,SAGrD,OAAS,gCAAAC,MAAoC,sDAE7C,OAAS,iCAAAC,MAAqC,kCAI9CL,EAAS,gCAAiC,IAAM,CAC9C,IAAIM,EACAC,EACJ,MAAMC,EAAY,mCACZC,EAAU,iBACVC,EAAqC,CACzC,IAAK,CACH,IAAK,2CACL,KAAM,OACN,OAAQ,MACV,CACF,EAEMC,EAAiD,CACrD,CACE,GAAIH,EACJ,SAAUJ,EAA6B,QACvC,aAAc,CACZ,CACE,kBAAmB,WACnB,iBAAkB,gBAClB,WAAY,CACV,KAAM,WACN,WAAY,CAAE,KAAM,UAAW,KAAM,SAAU,CACjD,EACA,eAAgB,CAAC,EACjB,iBAAkB,CAAC,EACnB,WAAY,CAAC,EACb,eAAgB,CAAC,CACnB,CACF,CACF,CACF,EAEAL,EAAW,IAAM,CACfI,EAAG,cAAc,EACjBI,EAAW,CAAE,IAAKJ,EAAG,GAAG,CAAE,EAC1BG,EAAa,IAAID,EACfK,EACAH,CACF,CACF,CAAC,EAEDL,EAAG,iEAAkE,SAAY,CAC/EK,EAAS,IAAI,kBAAkBI,CAAe,EAE9C,MAAML,EAAW,mBAAmB,CAAE,UAAAE,EAAW,QAAAC,CAAQ,CAAC,EAE1DR,EAAOM,EAAS,GAAG,EAAE,sBAAsB,CAAC,EAC5CN,EAAOM,EAAS,GAAG,EAAE,qBACnB,2DACA,CACE,OAAQ,CACN,GAAIC,EACJ,SAAUJ,EAA6B,QACvC,OAAQ,2BACR,IAAK,aACP,CACF,CACF,CACF,CAAC,EAEDF,EAAG,0DAA2D,SAAY,CACxEK,EAAS,IAAI,kBAAkBI,CAAe,EAE9C,MAAML,EAAW,mBAAmB,CAClC,UAAAE,EACA,QAAS,eACX,CAAC,EAEDP,EAAOM,EAAS,GAAG,EAAE,qBACnB,2DACAN,EAAO,iBAAiB,CACtB,OAAQA,EAAO,iBAAiB,CAAE,SAAU,GAAI,CAAC,CACnD,CAAC,CACH,CACF,CAAC,EAEDC,EAAG,kFAAmF,SAAY,CAChGK,EAAS,IAAI,kBAAkBI,CAAe,EAE9C,MAAMC,EAAS,MAAMN,EAAW,mBAAmB,CAAE,UAAAE,EAAW,QAAAC,CAAQ,CAAC,EAEzER,EAAOW,CAAM,EAAE,QACbd,EAAM,CACJ,UAAAU,EACA,YAAa,CACX,WAAYV,EAAM,CAChB,UAAAU,EACA,cAAe,WACf,gBAAiB,gBACjB,gBAAiB,CAAE,KAAM,WAAY,UAAW,SAAU,EAC1D,cAAe,CAAC,EAChB,aAAc,CAAC,EACf,cAAe,CAAE,SAAU,CAAC,EAAG,SAAU,CAAE,EAC3C,iBAAkB,CAAC,EACnB,kBAAmB,CAAC,EACpB,eAAgB,CAAC,EACjB,cAAe,CAAC,EAChB,cAAe,CAAC,EAChB,UAAW,CAAC,CACd,CAAC,CACH,EACA,aAAc,CAAC,CACjB,CAAC,CACH,CACF,CAAC,EAEDN,EAAG,uEAAwE,SAAY,CAGrFK,EAAS,IAAI,kBAAkB,CAC7B,CACE,GAAIC,EACJ,SAAUJ,EAA6B,QACvC,aAAc,CACZ,CACE,iBAAkB,UAClB,WAAY,CACV,KAAM,WACN,WAAY,CAAE,KAAM,UAAW,KAAM,SAAU,CACjD,CACF,CACF,CACF,CACF,CAAC,EAED,MAAMQ,EAAS,MAAMN,EAAW,mBAAmB,CAAE,UAAAE,EAAW,QAAAC,CAAQ,CAAC,EAEzER,EAAOW,EAAO,QAAQ,CAAC,EAAE,KAAK,EAAI,EAClC,KAAM,CAAE,YAAAC,CAAY,EAAID,EAAO,aAAa,EAC5CX,EAAO,OAAO,KAAKY,CAAW,CAAC,EAAE,QAAQ,CAAC,EAAE,CAAC,EAC7CZ,EAAOY,EAAY,EAAE,EAAG,aAAa,CAAC,EAAE,QACtCZ,EAAO,iBAAiB,CACtB,UAAAO,EACA,cAAe,GACf,gBAAiB,CAAE,KAAM,WAAY,UAAW,SAAU,CAC5D,CAAC,CACH,CACF,CAAC,EAEDN,EAAG,gDAAiD,SAAY,CAC9DK,EAAS,IAAI,kBAAkB,CAAC,CAAC,EAEjC,MAAMK,EAAS,MAAMN,EAAW,mBAAmB,CAAE,UAAAE,EAAW,QAAAC,CAAQ,CAAC,EAEzER,EAAOW,CAAM,EAAE,QACbf,EACE,IAAI,MACF,6EAA6EW,CAAS,EACxF,CACF,CACF,CACF,CAAC,EAEDN,EAAG,sEAAuE,SAAY,CACpFK,EAAS,IAAI,kBAAkB,CAC7B,CACE,GAAI,eACJ,SAAUH,EAA6B,QACvC,aAAc,CAAC,CACjB,CACF,CAAC,EAED,MAAMQ,EAAS,MAAMN,EAAW,mBAAmB,CAAE,UAAAE,EAAW,QAAAC,CAAQ,CAAC,EAEzER,EAAOW,CAAM,EAAE,QACbf,EACE,IAAI,MACF,6EAA6EW,CAAS,EACxF,CACF,CACF,CACF,CAAC,EAEDN,EAAG,yEAA0E,SAAY,CAGvFK,EAAS,IAAI,kBAAkB,CAC7B,CACE,GAAIC,EACJ,SAAUJ,EAA6B,QACvC,aAAc,CAAC,CAAE,kBAAmB,UAAW,CAAC,CAClD,CACF,CAAC,EAED,MAAMQ,EAAS,MAAMN,EAAW,mBAAmB,CAAE,UAAAE,EAAW,QAAAC,CAAQ,CAAC,EAEzER,EAAOW,EAAO,OAAO,CAAC,EAAE,KAAK,EAAI,EACjCX,EAAQW,EAAO,QAAQ,EAAY,OAAO,EAAE,QAC1C,IAAI,OACF,OAAO,yFAAyFJ,CAAS,GAC3G,CACF,CACF,CAAC,EAEDN,EAAG,2CAA4C,SAAY,CACzDK,EAAS,IAAI,kBAAkB,IAAI,MAAM,SAAS,CAAC,EAEnD,MAAMK,EAAS,MAAMN,EAAW,mBAAmB,CAAE,UAAAE,EAAW,QAAAC,CAAQ,CAAC,EAEzER,EAAOW,CAAM,EAAE,QACbf,EACE,IAAI,MACF,iGACF,CACF,CACF,CACF,CAAC,CACH,CAAC",
|
|
6
6
|
"names": ["Left", "Right", "beforeEach", "describe", "expect", "it", "vi", "SolanaTransactionScanChainId", "HttpInstructionInfoDataSource", "datasource", "httpMock", "programId", "network", "config", "successResponse", "result", "descriptors"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{array as n,Codec as r,number as s,optional as t,record as i,string as e}from"purify-ts";const c=r.interface({prod:t(e),test:t(e)}),a=r.interface({data:e,signatures:c}),
|
|
1
|
+
import{array as n,Codec as r,number as s,optional as t,record as i,string as e}from"purify-ts";const c=r.interface({prod:t(e),test:t(e)}),a=r.interface({data:e,signatures:c}),l=r.interface({descriptor:a}),o=r.interface({descriptor:e}),u=r.interface({discriminator_hex:t(e),descriptor:a,enum_variants:t(i(e,i(e,l))),display_fields:t(n(o)),value_flow_ports:t(n(o)),hide_rules:t(n(o)),account_resets:t(n(o))}),d=r.interface({id:e,chain_id:s,instructions:n(u)});export{d as calInstructionProgramCodec};
|
|
2
2
|
//# sourceMappingURL=InstructionInfoDto.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../../src/modules/solana/instruction-info/data/InstructionInfoDto.ts"],
|
|
4
|
-
"sourcesContent": ["// DTO + codecs for the CAL instruction-descriptors response (one object per\n// `programId`, wrapped in a JSON array).\n//\n// The hand-written types describe the consumed shape (with genuinely optional\n// `?:` fields); the codecs below validate that shape at runtime so\n// `HttpInstructionInfoDataSource` can hand the loaders a payload they can\n// dereference without runtime-throwing on a malformed descriptor.\n\nimport { array, Codec, number, optional, record, string } from \"purify-ts\";\n\nexport type CalSignatures = {\n prod?: string;\n test?: string;\n};\n\nexport type CalSignedDescriptorDto = {\n data: string;\n signatures: CalSignatures;\n};\n\n// Decoded CAL JSON shapes (snake_case mirrors the CAL response) that drive\n// host-side requirement building.\n\nexport type CalValueDto = {\n source: string;\n account_index?: number;\n data?: string;\n path?: { steps: number[] };\n};\n\nexport type CalTokenValueDto = {\n kind: string;\n value?: CalValueDto;\n account_index?: number;\n};\n\nexport type CalMintAssociationDto = {\n account_index: number;\n mint_index: number;\n};\n\nexport type CalTypePoolEntryDto = {\n index: number;\n kind: string;\n refs?: number[];\n size?: number;\n encoding?: number;\n len_kind?: string;\n flag_kind?: string;\n sentinel?: string;\n disc_kind?: string;\n total_variants?: number;\n enum_id?: string;\n};\n\nexport type CalEnumVariantDto = {\n variant_name: string;\n payload_kind?: string;\n descriptor: CalSignedDescriptorDto;\n};\n\n/** A substructure CAL serves only as opaque TLV (e.g. HIDE_RULE). */\nexport type CalSubstructureDto = {\n descriptor: string;\n};\n\nexport type CalValueFlowPortDto = CalSubstructureDto & {\n account_indices: number[];\n optional_account_strategy?: string;\n token_value: CalTokenValueDto;\n};\n\nexport type CalAccountResetDto = CalSubstructureDto & {\n account_index?: number;\n require_pre_balance_zero?: boolean;\n};\n\nexport type CalDisplayFieldDto = CalSubstructureDto & {\n name?: string;\n param?: { type: string; value?: CalValueDto; token?: CalValueDto };\n};\n\nexport type CalInstructionDescriptorDto = {\n discriminator_hex?: string;\n instruction_name?: string;\n descriptor: CalSignedDescriptorDto;\n idl_descriptor?: {\n type_pool?: CalTypePoolEntryDto[];\n root_type?: number;\n };\n mint_association?: CalMintAssociationDto;\n owner_association?:
|
|
5
|
-
"mappings": "AAQA,OAAS,SAAAA,EAAO,SAAAC,EAAO,UAAAC,EAAQ,YAAAC,EAAU,UAAAC,EAAQ,UAAAC,MAAc,
|
|
4
|
+
"sourcesContent": ["// DTO + codecs for the CAL instruction-descriptors response (one object per\n// `programId`, wrapped in a JSON array).\n//\n// The hand-written types describe the consumed shape (with genuinely optional\n// `?:` fields); the codecs below validate that shape at runtime so\n// `HttpInstructionInfoDataSource` can hand the loaders a payload they can\n// dereference without runtime-throwing on a malformed descriptor.\n\nimport { array, Codec, number, optional, record, string } from \"purify-ts\";\n\nexport type CalSignatures = {\n prod?: string;\n test?: string;\n};\n\nexport type CalSignedDescriptorDto = {\n data: string;\n signatures: CalSignatures;\n};\n\n// Decoded CAL JSON shapes (snake_case mirrors the CAL response) that drive\n// host-side requirement building.\n\nexport type CalValueDto = {\n source: string;\n account_index?: number;\n data?: string;\n path?: { steps: number[] };\n};\n\nexport type CalTokenValueDto = {\n kind: string;\n value?: CalValueDto;\n account_index?: number;\n /** `RESOLVE` only: account index whose address is the mint of last resort. */\n fallback_account?: number;\n};\n\nexport type CalMintAssociationDto = {\n account_index: number;\n mint_index: number;\n};\n\n// Neither half is codec-validated, and the spec requires both or neither, so\n// both are optional here and the mapper drops a half-declared pair.\nexport type CalOwnerAssociationDto = {\n account_index?: number;\n owner?: CalValueDto;\n};\n\n/** One `ACTIVE_WHEN` predicate: a bare name, or `MINT_PREDICATE` + its mint. */\nexport type CalActiveWhenPredicateDto =\n | string\n | { kind: string; mint?: string };\n\nexport type CalTypePoolEntryDto = {\n index: number;\n kind: string;\n refs?: number[];\n size?: number;\n encoding?: number;\n len_kind?: string;\n flag_kind?: string;\n sentinel?: string;\n disc_kind?: string;\n total_variants?: number;\n enum_id?: string;\n};\n\nexport type CalEnumVariantDto = {\n variant_name: string;\n payload_kind?: string;\n descriptor: CalSignedDescriptorDto;\n};\n\n/** A substructure CAL serves only as opaque TLV (e.g. HIDE_RULE). */\nexport type CalSubstructureDto = {\n descriptor: string;\n};\n\nexport type CalValueFlowPortDto = CalSubstructureDto & {\n account_indices: number[];\n optional_account_strategy?: string;\n token_value: CalTokenValueDto;\n active_when?: CalActiveWhenPredicateDto[];\n};\n\nexport type CalHideRuleDto = CalSubstructureDto & {\n rule_set_index?: number;\n target?: CalValueDto;\n condition?: string;\n};\n\nexport type CalAccountResetDto = CalSubstructureDto & {\n account_index?: number;\n require_pre_balance_zero?: boolean;\n};\n\nexport type CalDisplayFieldDto = CalSubstructureDto & {\n name?: string;\n param?: { type: string; value?: CalValueDto; token?: CalValueDto };\n};\n\nexport type CalInstructionDescriptorDto = {\n discriminator_hex?: string;\n instruction_name?: string;\n descriptor: CalSignedDescriptorDto;\n idl_descriptor?: {\n type_pool?: CalTypePoolEntryDto[];\n root_type?: number;\n };\n mint_association?: CalMintAssociationDto;\n owner_association?: CalOwnerAssociationDto;\n enum_variants?: Record<string, Record<string, CalEnumVariantDto>>;\n display_fields?: CalDisplayFieldDto[];\n value_flow_ports?: CalValueFlowPortDto[];\n hide_rules?: CalHideRuleDto[];\n account_resets?: CalAccountResetDto[];\n};\n\n// One program object of the `solana_programs` response: the program `id`, its\n// `chain_id`, and the flat `instructions` array (keyed downstream by\n// `discriminator_hex`).\nexport type CalInstructionProgramDto = {\n id: string;\n chain_id: number;\n instructions: CalInstructionDescriptorDto[];\n};\n\n// Outer shape: array of program objects (one per requested `id`).\nexport type CalInstructionInfoResponseDto = CalInstructionProgramDto[];\n\n// --- Validation codecs (runtime). Validate only the fields the loaders read;\n// `Codec.interface` ignores unknown extras so CAL can add fields freely. ---\n\nconst calSignaturesCodec = Codec.interface({\n prod: optional(string),\n test: optional(string),\n});\n\nconst calSignedDescriptorCodec = Codec.interface({\n data: string,\n signatures: calSignaturesCodec,\n});\n\nconst calEnumVariantCodec = Codec.interface({\n descriptor: calSignedDescriptorCodec,\n});\n\nconst calSubstructureCodec = Codec.interface({\n descriptor: string,\n});\n\nconst calInstructionDescriptorCodec = Codec.interface({\n discriminator_hex: optional(string),\n descriptor: calSignedDescriptorCodec,\n enum_variants: optional(record(string, record(string, calEnumVariantCodec))),\n display_fields: optional(array(calSubstructureCodec)),\n value_flow_ports: optional(array(calSubstructureCodec)),\n hide_rules: optional(array(calSubstructureCodec)),\n account_resets: optional(array(calSubstructureCodec)),\n});\n\n/**\n * Codec for one program object of the `solana_programs` response. Used by the\n * datasource to validate the CAL payload before handing it to the loaders.\n * Only loader-consumed fields are validated; unrelated CAL fields\n * (`idl_descriptor`, `mint_association`, \u2026) are ignored.\n */\nexport const calInstructionProgramCodec = Codec.interface({\n id: string,\n chain_id: number,\n instructions: array(calInstructionDescriptorCodec),\n});\n"],
|
|
5
|
+
"mappings": "AAQA,OAAS,SAAAA,EAAO,SAAAC,EAAO,UAAAC,EAAQ,YAAAC,EAAU,UAAAC,EAAQ,UAAAC,MAAc,YA+H/D,MAAMC,EAAqBL,EAAM,UAAU,CACzC,KAAME,EAASE,CAAM,EACrB,KAAMF,EAASE,CAAM,CACvB,CAAC,EAEKE,EAA2BN,EAAM,UAAU,CAC/C,KAAMI,EACN,WAAYC,CACd,CAAC,EAEKE,EAAsBP,EAAM,UAAU,CAC1C,WAAYM,CACd,CAAC,EAEKE,EAAuBR,EAAM,UAAU,CAC3C,WAAYI,CACd,CAAC,EAEKK,EAAgCT,EAAM,UAAU,CACpD,kBAAmBE,EAASE,CAAM,EAClC,WAAYE,EACZ,cAAeJ,EAASC,EAAOC,EAAQD,EAAOC,EAAQG,CAAmB,CAAC,CAAC,EAC3E,eAAgBL,EAASH,EAAMS,CAAoB,CAAC,EACpD,iBAAkBN,EAASH,EAAMS,CAAoB,CAAC,EACtD,WAAYN,EAASH,EAAMS,CAAoB,CAAC,EAChD,eAAgBN,EAASH,EAAMS,CAAoB,CAAC,CACtD,CAAC,EAQYE,EAA6BV,EAAM,UAAU,CACxD,GAAII,EACJ,SAAUH,EACV,aAAcF,EAAMU,CAA6B,CACnD,CAAC",
|
|
6
6
|
"names": ["array", "Codec", "number", "optional", "record", "string", "calSignaturesCodec", "calSignedDescriptorCodec", "calEnumVariantCodec", "calSubstructureCodec", "calInstructionDescriptorCodec", "calInstructionProgramCodec"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{Left as p,Right as d}from"purify-ts";import{SolanaInstructionSubstructureKind as
|
|
1
|
+
import{Left as p,Right as d}from"purify-ts";import{SolanaInstructionSubstructureKind as r}from"../../../../modules/solana/model/SolanaPayloads";import{u16Codec as _}from"../../../../shared/utils/uIntCodec";function u(n,t){return n[t]}function f(n=[]){return n.map(t=>({account_indices:t.account_indices,optional_account_strategy:t.optional_account_strategy,token_value:t.token_value,active_when:t.active_when}))}function C(n=[]){return n.flatMap(t=>t.account_index===void 0?[]:[{account_index:t.account_index,require_pre_balance_zero:t.require_pre_balance_zero}])}function y(n=[]){return n.map(t=>({rule_set_index:t.rule_set_index,target:t.target,condition:t.condition}))}function m(n){return n===void 0?[]:n.account_index===void 0||n.owner===void 0?[]:[{account_index:n.account_index,owner:n.owner}]}function D(n=[]){return n.map(t=>({name:t.name,param:t.param??{type:""}}))}function S(n){return[...(n.display_fields??[]).map(t=>({kind:r.DISPLAY_FIELD,data:t.descriptor})),...(n.value_flow_ports??[]).map(t=>({kind:r.VALUE_FLOW_PORT,data:t.descriptor})),...(n.hide_rules??[]).map(t=>({kind:r.HIDE_RULE,data:t.descriptor})),...(n.account_resets??[]).map(t=>({kind:r.ACCOUNT_RESET,data:t.descriptor}))]}function c(n,t){const e=[];for(const[a,o]of Object.entries(n.enum_variants??{}))for(const[l,i]of Object.entries(o)){const s=Number(l);_.decode(s).isLeft()||e.push({enumId:a,variantIndex:s,descriptor:{data:i.descriptor.data,signature:u(i.descriptor.signatures,t)??""}})}return e}function g(n,t){return Object.values(n).flatMap(e=>c(e,t))}function R(n,t,e,a){const o=u(e.descriptor.signatures,a);return o?d({programId:n,discriminator:t,instructionName:e.instruction_name,instructionInfo:{data:e.descriptor.data,signature:o},substructures:S(e),enumVariants:c(e,a),idlDescriptor:{typePool:e.idl_descriptor?.type_pool??[],rootType:e.idl_descriptor?.root_type??0},mintAssociations:e.mint_association?[e.mint_association]:[],ownerAssociations:m(e.owner_association),valueFlowPorts:f(e.value_flow_ports),accountResets:C(e.account_resets),displayFields:D(e.display_fields),hideRules:y(e.hide_rules)}):p(new Error(`[ContextModule] InstructionInfoDataSource: missing '${a}' signature for (${n}, ${t})`))}export{C as toAccountResets,D as toDisplayFields,y as toHideRules,R as toInstructionInfoPayload,m as toOwnerAssociations,g as toProgramEnumVariants,f as toValueFlowPorts};
|
|
2
2
|
//# sourceMappingURL=InstructionInfoMapper.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../../src/modules/solana/instruction-info/data/InstructionInfoMapper.ts"],
|
|
4
|
-
"sourcesContent": ["// Maps the validated CAL instruction-descriptor DTOs into the core\n// `SolanaInstructionInfoPayload` model. Keeping this in the data layer means\n// the domain `InstructionInfoContextLoader` never has to know the CAL DTO\n// shapes \u2014 it consumes core models only.\n\nimport { type Either, Left, Right } from \"purify-ts\";\n\nimport {\n type SolanaCalAccountReset,\n type SolanaCalDisplayField,\n type SolanaCalValueFlowPort,\n type SolanaInstructionEnumVariant,\n type SolanaInstructionInfoPayload,\n type SolanaInstructionSubstructure,\n SolanaInstructionSubstructureKind,\n} from \"@/modules/solana/model/SolanaPayloads\";\nimport { u16Codec } from \"@/shared/utils/uIntCodec\";\n\nimport {\n type CalAccountResetDto,\n type CalDisplayFieldDto,\n type CalInstructionDescriptorDto,\n type CalSignatures,\n type CalValueFlowPortDto,\n} from \"./InstructionInfoDto\";\n\nexport type CalMode = \"prod\" | \"test\";\n\nfunction pickSignature(\n signatures: CalSignatures,\n mode: CalMode,\n): string | undefined {\n return signatures[mode];\n}\n\n// --- DTO \u2192 decoded-payload projections. Pick only the fields the host-side\n// requirement builder reads, dropping the signed-TLV `descriptor` carried by\n// the DTO. ---\n\nexport function toValueFlowPorts(\n dtos: CalValueFlowPortDto[] = [],\n): SolanaCalValueFlowPort[] {\n return dtos.map((port) => ({\n account_indices: port.account_indices,\n optional_account_strategy: port.optional_account_strategy,\n token_value: port.token_value,\n }));\n}\n\nexport function toAccountResets(\n dtos: CalAccountResetDto[] = [],\n): SolanaCalAccountReset[] {\n // Drop malformed resets (missing account_index) rather than defaulting to\n // slot 0, which would create an unintended TOKEN_ACCOUNT_STATE requirement.\n return dtos.flatMap((reset) =>\n reset.account_index === undefined\n ? []\n : [\n {\n account_index: reset.account_index,\n require_pre_balance_zero: reset.require_pre_balance_zero,\n },\n ],\n );\n}\n\nexport function toDisplayFields(\n dtos: CalDisplayFieldDto[] = [],\n): SolanaCalDisplayField[] {\n return dtos.map((field) => ({\n name: field.name,\n param: field.param ?? { type: \"\" },\n }));\n}\n\nfunction toSubstructures(\n dto: CalInstructionDescriptorDto,\n): SolanaInstructionSubstructure[] {\n return [\n ...(dto.display_fields ?? []).map((s) => ({\n kind: SolanaInstructionSubstructureKind.DISPLAY_FIELD,\n data: s.descriptor,\n })),\n ...(dto.value_flow_ports ?? []).map((s) => ({\n kind: SolanaInstructionSubstructureKind.VALUE_FLOW_PORT,\n data: s.descriptor,\n })),\n ...(dto.hide_rules ?? []).map((s) => ({\n kind: SolanaInstructionSubstructureKind.HIDE_RULE,\n data: s.descriptor,\n })),\n ...(dto.account_resets ?? []).map((s) => ({\n kind: SolanaInstructionSubstructureKind.ACCOUNT_RESET,\n data: s.descriptor,\n })),\n ];\n}\n\n/**\n * Flatten the CAL-bundled enum variants (keyed enumId \u2192 variantIndex). Keys\n * that don't validate as a u16 are skipped rather than leaking NaN/out-of-range\n * indices into the payload.\n */\nfunction toEnumVariants(\n dto: CalInstructionDescriptorDto,\n mode: CalMode,\n): SolanaInstructionEnumVariant[] {\n const enumVariants: SolanaInstructionEnumVariant[] = [];\n for (const [enumId, variants] of Object.entries(dto.enum_variants ?? {})) {\n for (const [variantIndex, variant] of Object.entries(variants)) {\n const index = Number(variantIndex);\n if (u16Codec.decode(index).isLeft()) {\n continue;\n }\n enumVariants.push({\n enumId,\n variantIndex: index,\n descriptor: {\n data: variant.descriptor.data,\n signature: pickSignature(variant.descriptor.signatures, mode) ?? \"\",\n },\n });\n }\n }\n return enumVariants;\n}\n\n/**\n * Flatten the enum variants of every descriptor in a program into a single\n * list. CAL nests `enum_variants` inside each instruction descriptor but\n * guarantees `(enumId, variantIndex)` is unique across a program, so the enum\n * loader resolves a selection against this program-level list \u2014 independently\n * of whether any individual instruction descriptor carried a usable signature.\n */\nexport function toProgramEnumVariants(\n descriptors: Record<string, CalInstructionDescriptorDto>,\n mode: CalMode,\n): SolanaInstructionEnumVariant[] {\n return Object.values(descriptors).flatMap((dto) => toEnumVariants(dto, mode));\n}\n\n/**\n * Transform one validated CAL descriptor DTO into the core\n * {@link SolanaInstructionInfoPayload}. Returns a `Left` when the descriptor is\n * unusable (no signature for the configured `mode`), so the caller can surface\n * a per-descriptor ERROR rather than emitting an empty signature.\n *\n * `programId` comes from the enclosing `solana_programs` envelope `id`;\n * `discriminator` from the instruction's `discriminator_hex`.\n */\nexport function toInstructionInfoPayload(\n programId: string,\n discriminator: string,\n dto: CalInstructionDescriptorDto,\n mode: CalMode,\n): Either<Error, SolanaInstructionInfoPayload> {\n const signature = pickSignature(dto.descriptor.signatures, mode);\n if (!signature) {\n return Left(\n new Error(\n `[ContextModule] InstructionInfoDataSource: missing '${mode}' signature for (${programId}, ${discriminator})`,\n ),\n );\n }\n\n return Right({\n programId,\n discriminator,\n instructionName: dto.instruction_name,\n instructionInfo: {\n data: dto.descriptor.data,\n signature,\n },\n substructures: toSubstructures(dto),\n enumVariants: toEnumVariants(dto, mode),\n idlDescriptor: {\n typePool: dto.idl_descriptor?.type_pool ?? [],\n rootType: dto.idl_descriptor?.root_type ?? 0,\n },\n mintAssociations: dto.mint_association ? [dto.mint_association] : [],\n valueFlowPorts: toValueFlowPorts(dto.value_flow_ports),\n accountResets: toAccountResets(dto.account_resets),\n displayFields: toDisplayFields(dto.display_fields),\n });\n}\n"],
|
|
5
|
-
"mappings": "AAKA,OAAsB,QAAAA,EAAM,SAAAC,MAAa,YAEzC,
|
|
6
|
-
"names": ["Left", "Right", "SolanaInstructionSubstructureKind", "u16Codec", "pickSignature", "signatures", "mode", "toValueFlowPorts", "dtos", "port", "toAccountResets", "reset", "
|
|
4
|
+
"sourcesContent": ["// Maps the validated CAL instruction-descriptor DTOs into the core\n// `SolanaInstructionInfoPayload` model. Keeping this in the data layer means\n// the domain `InstructionInfoContextLoader` never has to know the CAL DTO\n// shapes \u2014 it consumes core models only.\n\nimport { type Either, Left, Right } from \"purify-ts\";\n\nimport {\n type SolanaCalAccountReset,\n type SolanaCalDisplayField,\n type SolanaCalHideRule,\n type SolanaCalOwnerAssociation,\n type SolanaCalValueFlowPort,\n type SolanaInstructionEnumVariant,\n type SolanaInstructionInfoPayload,\n type SolanaInstructionSubstructure,\n SolanaInstructionSubstructureKind,\n} from \"@/modules/solana/model/SolanaPayloads\";\nimport { u16Codec } from \"@/shared/utils/uIntCodec\";\n\nimport {\n type CalAccountResetDto,\n type CalDisplayFieldDto,\n type CalHideRuleDto,\n type CalInstructionDescriptorDto,\n type CalOwnerAssociationDto,\n type CalSignatures,\n type CalValueFlowPortDto,\n} from \"./InstructionInfoDto\";\n\nexport type CalMode = \"prod\" | \"test\";\n\nfunction pickSignature(\n signatures: CalSignatures,\n mode: CalMode,\n): string | undefined {\n return signatures[mode];\n}\n\n// --- DTO \u2192 decoded-payload projections. Pick only the fields the host-side\n// requirement builder reads, dropping the signed-TLV `descriptor` carried by\n// the DTO. ---\n\nexport function toValueFlowPorts(\n dtos: CalValueFlowPortDto[] = [],\n): SolanaCalValueFlowPort[] {\n return dtos.map((port) => ({\n account_indices: port.account_indices,\n optional_account_strategy: port.optional_account_strategy,\n token_value: port.token_value,\n active_when: port.active_when,\n }));\n}\n\nexport function toAccountResets(\n dtos: CalAccountResetDto[] = [],\n): SolanaCalAccountReset[] {\n // Drop malformed resets (missing account_index) rather than defaulting to\n // slot 0, which would create an unintended TOKEN_ACCOUNT_STATE requirement.\n return dtos.flatMap((reset) =>\n reset.account_index === undefined\n ? []\n : [\n {\n account_index: reset.account_index,\n require_pre_balance_zero: reset.require_pre_balance_zero,\n },\n ],\n );\n}\n\n/**\n * Every rule is carried, including one CAL served without a `condition`. The\n * rule's signed TLV goes to the device through {@link toSubstructures}\n * regardless, and the device resolves the `target` of every rule it receives \u2014\n * so dropping the entry here would cost the host the `ALT_RESOLUTION` for that\n * target and make the device refuse to sign. A missing condition only means no\n * requirement keys off this rule's predicate.\n */\nexport function toHideRules(dtos: CalHideRuleDto[] = []): SolanaCalHideRule[] {\n return dtos.map((rule) => ({\n rule_set_index: rule.rule_set_index,\n target: rule.target,\n condition: rule.condition,\n }));\n}\n\n/**\n * CAL carries at most one `owner_association` per descriptor; the payload holds\n * a list so the transaction-wide owner map is built the same way as the mint\n * map. Both halves of the pair are required (spec: \"must both be present or\n * both absent\"), so a half-declared association is dropped.\n */\nexport function toOwnerAssociations(\n dto: CalOwnerAssociationDto | undefined,\n): SolanaCalOwnerAssociation[] {\n if (dto === undefined) return [];\n if (dto.account_index === undefined || dto.owner === undefined) return [];\n return [{ account_index: dto.account_index, owner: dto.owner }];\n}\n\nexport function toDisplayFields(\n dtos: CalDisplayFieldDto[] = [],\n): SolanaCalDisplayField[] {\n return dtos.map((field) => ({\n name: field.name,\n param: field.param ?? { type: \"\" },\n }));\n}\n\nfunction toSubstructures(\n dto: CalInstructionDescriptorDto,\n): SolanaInstructionSubstructure[] {\n return [\n ...(dto.display_fields ?? []).map((s) => ({\n kind: SolanaInstructionSubstructureKind.DISPLAY_FIELD,\n data: s.descriptor,\n })),\n ...(dto.value_flow_ports ?? []).map((s) => ({\n kind: SolanaInstructionSubstructureKind.VALUE_FLOW_PORT,\n data: s.descriptor,\n })),\n ...(dto.hide_rules ?? []).map((s) => ({\n kind: SolanaInstructionSubstructureKind.HIDE_RULE,\n data: s.descriptor,\n })),\n ...(dto.account_resets ?? []).map((s) => ({\n kind: SolanaInstructionSubstructureKind.ACCOUNT_RESET,\n data: s.descriptor,\n })),\n ];\n}\n\n/**\n * Flatten the CAL-bundled enum variants (keyed enumId \u2192 variantIndex). Keys\n * that don't validate as a u16 are skipped rather than leaking NaN/out-of-range\n * indices into the payload.\n */\nfunction toEnumVariants(\n dto: CalInstructionDescriptorDto,\n mode: CalMode,\n): SolanaInstructionEnumVariant[] {\n const enumVariants: SolanaInstructionEnumVariant[] = [];\n for (const [enumId, variants] of Object.entries(dto.enum_variants ?? {})) {\n for (const [variantIndex, variant] of Object.entries(variants)) {\n const index = Number(variantIndex);\n if (u16Codec.decode(index).isLeft()) {\n continue;\n }\n enumVariants.push({\n enumId,\n variantIndex: index,\n descriptor: {\n data: variant.descriptor.data,\n signature: pickSignature(variant.descriptor.signatures, mode) ?? \"\",\n },\n });\n }\n }\n return enumVariants;\n}\n\n/**\n * Flatten the enum variants of every descriptor in a program into a single\n * list. CAL nests `enum_variants` inside each instruction descriptor but\n * guarantees `(enumId, variantIndex)` is unique across a program, so the enum\n * loader resolves a selection against this program-level list \u2014 independently\n * of whether any individual instruction descriptor carried a usable signature.\n */\nexport function toProgramEnumVariants(\n descriptors: Record<string, CalInstructionDescriptorDto>,\n mode: CalMode,\n): SolanaInstructionEnumVariant[] {\n return Object.values(descriptors).flatMap((dto) => toEnumVariants(dto, mode));\n}\n\n/**\n * Transform one validated CAL descriptor DTO into the core\n * {@link SolanaInstructionInfoPayload}. Returns a `Left` when the descriptor is\n * unusable (no signature for the configured `mode`), so the caller can surface\n * a per-descriptor ERROR rather than emitting an empty signature.\n *\n * `programId` comes from the enclosing `solana_programs` envelope `id`;\n * `discriminator` from the instruction's `discriminator_hex`.\n */\nexport function toInstructionInfoPayload(\n programId: string,\n discriminator: string,\n dto: CalInstructionDescriptorDto,\n mode: CalMode,\n): Either<Error, SolanaInstructionInfoPayload> {\n const signature = pickSignature(dto.descriptor.signatures, mode);\n if (!signature) {\n return Left(\n new Error(\n `[ContextModule] InstructionInfoDataSource: missing '${mode}' signature for (${programId}, ${discriminator})`,\n ),\n );\n }\n\n return Right({\n programId,\n discriminator,\n instructionName: dto.instruction_name,\n instructionInfo: {\n data: dto.descriptor.data,\n signature,\n },\n substructures: toSubstructures(dto),\n enumVariants: toEnumVariants(dto, mode),\n idlDescriptor: {\n typePool: dto.idl_descriptor?.type_pool ?? [],\n rootType: dto.idl_descriptor?.root_type ?? 0,\n },\n mintAssociations: dto.mint_association ? [dto.mint_association] : [],\n ownerAssociations: toOwnerAssociations(dto.owner_association),\n valueFlowPorts: toValueFlowPorts(dto.value_flow_ports),\n accountResets: toAccountResets(dto.account_resets),\n displayFields: toDisplayFields(dto.display_fields),\n hideRules: toHideRules(dto.hide_rules),\n });\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["Left", "Right", "SolanaInstructionSubstructureKind", "u16Codec", "pickSignature", "signatures", "mode", "toValueFlowPorts", "dtos", "port", "toAccountResets", "reset", "toHideRules", "rule", "toOwnerAssociations", "dto", "toDisplayFields", "field", "toSubstructures", "s", "toEnumVariants", "enumVariants", "enumId", "variants", "variantIndex", "variant", "index", "toProgramEnumVariants", "descriptors", "toInstructionInfoPayload", "programId", "discriminator", "signature"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{describe as
|
|
1
|
+
import{describe as r,expect as e,it as t}from"vitest";import{toAccountResets as c,toDisplayFields as u,toHideRules as _,toInstructionInfoPayload as s,toOwnerAssociations as d,toProgramEnumVariants as l,toValueFlowPorts as p}from"./InstructionInfoMapper";const i="11111111111111111111111111111111";function o(n={}){return{discriminator_hex:"00000000",instruction_name:"createAccount",descriptor:{data:"0001sys_data",signatures:{prod:"prodsig",test:"testsig"}},...n}}r("InstructionInfoMapper",()=>{r("toValueFlowPorts",()=>{t("returns an empty list for undefined input",()=>{e(p()).toEqual([])}),t("picks only the decoded fields, dropping the signed-TLV descriptor",()=>{e(p([{descriptor:"vfp1",account_indices:[0,1],optional_account_strategy:"OMITTED",token_value:{kind:"RESOLVE",fallback_account:5},active_when:["IS_SIGNER"]}])).toEqual([{account_indices:[0,1],optional_account_strategy:"OMITTED",token_value:{kind:"RESOLVE",fallback_account:5},active_when:["IS_SIGNER"]}])}),t("leaves the absent optional strategy as undefined",()=>{e(p([{descriptor:"vfp1",account_indices:[0],token_value:{kind:"NATIVE"}}])).toEqual([{account_indices:[0],optional_account_strategy:void 0,token_value:{kind:"NATIVE"},active_when:void 0}])})}),r("toHideRules",()=>{t("returns an empty list for undefined input",()=>{e(_()).toEqual([])}),t("maps the decoded fields, dropping the signed-TLV descriptor",()=>{e(_([{descriptor:"hr1",rule_set_index:1,target:{source:"ACCOUNT_PATH",account_index:2},condition:"IS_SIGNER"}])).toEqual([{rule_set_index:1,target:{source:"ACCOUNT_PATH",account_index:2},condition:"IS_SIGNER"}])}),t("keeps a rule with no condition so its target stays in the requirement set",()=>{e(_([{descriptor:"hrNoCondition",target:{source:"ACCOUNT_PATH",account_index:4}}])).toEqual([{rule_set_index:void 0,target:{source:"ACCOUNT_PATH",account_index:4},condition:void 0}])})}),r("toOwnerAssociations",()=>{t("returns an empty list for undefined input",()=>{e(d(void 0)).toEqual([])}),t("wraps CAL's single association into a list",()=>{e(d({account_index:1,owner:{source:"ACCOUNT_PATH",account_index:0}})).toEqual([{account_index:1,owner:{source:"ACCOUNT_PATH",account_index:0}}])}),t("drops a half-declared pair",()=>{e(d({account_index:1})).toEqual([]),e(d({owner:{source:"ACCOUNT_PATH"}})).toEqual([])})}),r("toAccountResets",()=>{t("returns an empty list for undefined input",()=>{e(c()).toEqual([])}),t("maps the decoded fields, dropping the signed-TLV descriptor",()=>{e(c([{descriptor:"ar1",account_index:2,require_pre_balance_zero:!0}])).toEqual([{account_index:2,require_pre_balance_zero:!0}])}),t("drops entries missing account_index instead of defaulting to slot 0",()=>{e(c([{descriptor:"ar0",account_index:0},{descriptor:"arBad"},{descriptor:"ar1",account_index:1}])).toEqual([{account_index:0,require_pre_balance_zero:void 0},{account_index:1,require_pre_balance_zero:void 0}])})}),r("toDisplayFields",()=>{t("returns an empty list for undefined input",()=>{e(u()).toEqual([])}),t("picks name and param, dropping the signed-TLV descriptor",()=>{e(u([{descriptor:"df1",name:"New Account",param:{type:"ACCOUNT",value:{source:"ACCOUNT_PATH",account_index:1}}}])).toEqual([{name:"New Account",param:{type:"ACCOUNT",value:{source:"ACCOUNT_PATH",account_index:1}}}])}),t("falls back to an empty-type param when param is absent",()=>{e(u([{descriptor:"df1"}])).toEqual([{name:void 0,param:{type:""}}])})}),r("toInstructionInfoPayload",()=>{t("surfaces CAL's decoded JSON (type pool, mint assoc, ports, resets, fields) and ordered substructures",()=>{const n=o({idl_descriptor:{root_type:3,type_pool:[{index:0,kind:"STRUCT",refs:[1]},{index:1,kind:"U64"}]},mint_association:{account_index:1,mint_index:3},owner_association:{account_index:1,owner:{source:"ACCOUNT_PATH",account_index:0}},display_fields:[{descriptor:"df1",name:"New Account",param:{type:"ACCOUNT",value:{source:"ACCOUNT_PATH",account_index:1}}}],value_flow_ports:[{descriptor:"vfp1",account_indices:[0],token_value:{kind:"NATIVE"}}],hide_rules:[{descriptor:"hr1",rule_set_index:0,target:{source:"ACCOUNT_PATH",account_index:1},condition:"ACCOUNT_EFFECTS_DISPLAYED_ELSEWHERE"}],account_resets:[{descriptor:"ar1",account_index:1,require_pre_balance_zero:!0}]}),a=s(i,"00000000",n,"prod").unsafeCoerce();e(a).toMatchObject({programId:i,discriminator:"00000000",instructionInfo:{data:"0001sys_data",signature:"prodsig"},idlDescriptor:{rootType:3,typePool:[{index:0,kind:"STRUCT",refs:[1]},{index:1,kind:"U64"}]},mintAssociations:[{account_index:1,mint_index:3}],ownerAssociations:[{account_index:1,owner:{source:"ACCOUNT_PATH",account_index:0}}],valueFlowPorts:[{account_indices:[0],optional_account_strategy:void 0,token_value:{kind:"NATIVE"}}],hideRules:[{rule_set_index:0,target:{source:"ACCOUNT_PATH",account_index:1},condition:"ACCOUNT_EFFECTS_DISPLAYED_ELSEWHERE"}],accountResets:[{account_index:1,require_pre_balance_zero:!0}],displayFields:[{name:"New Account",param:{type:"ACCOUNT",value:{source:"ACCOUNT_PATH",account_index:1}}}]}),e(a.substructures).toEqual([{kind:0,data:"df1"},{kind:1,data:"vfp1"},{kind:2,data:"hr1"},{kind:3,data:"ar1"}])}),t("defaults idlDescriptor when CAL omits it",()=>{const n=s(i,"00000000",o(),"prod").unsafeCoerce();e(n.idlDescriptor).toEqual({typePool:[],rootType:0}),e(n.mintAssociations).toEqual([])}),t("bundles CAL enum_variants into the payload with the mode signature",()=>{const n=o({enum_variants:{swap:{46:{variant_name:"raydiumCP",descriptor:{data:"01_raydium_tlv",signatures:{prod:"prodsig_v46",test:"testsig_v46"}}}}}}),a=s(i,"00000000",n,"prod").unsafeCoerce();e(a.enumVariants).toEqual([{enumId:"swap",variantIndex:46,descriptor:{data:"01_raydium_tlv",signature:"prodsig_v46"}}])}),t("skips enum_variants keyed by a non-u16 index instead of leaking NaN",()=>{const n=o({enum_variants:{swap:{46:{variant_name:"raydiumCP",descriptor:{data:"01_raydium_tlv",signatures:{prod:"prodsig_v46",test:"testsig_v46"}}},"7abc":{variant_name:"junk",descriptor:{data:"junk_tlv",signatures:{prod:"x",test:"x"}}},7e4:{variant_name:"overflow",descriptor:{data:"overflow_tlv",signatures:{prod:"x",test:"x"}}}}}}),a=s(i,"00000000",n,"prod").unsafeCoerce();e(a.enumVariants).toEqual([{enumId:"swap",variantIndex:46,descriptor:{data:"01_raydium_tlv",signature:"prodsig_v46"}}])}),t("selects the signature for the configured mode",()=>{const n=s(i,"00000000",o(),"test").unsafeCoerce();e(n.instructionInfo.signature).toBe("testsig")}),t("returns Left when the configured mode signature is missing",()=>{const n=o();delete n.descriptor.signatures.test;const a=s(i,"00000000",n,"test");e(a.isLeft()).toBe(!0),e(a.swap().unsafeCoerce().message).toMatch(/missing 'test' signature/)})}),r("toProgramEnumVariants",()=>{t("flattens enum variants across all descriptors, dropping malformed keys",()=>{const n={"00000000":o({enum_variants:{swap:{46:{variant_name:"raydiumCP",descriptor:{data:"01_raydium_tlv",signatures:{prod:"prodsig_v46",test:"testsig_v46"}}},bad:{variant_name:"junk",descriptor:{data:"junk_tlv",signatures:{prod:"x",test:"x"}}}}}}),"00000001":o({enum_variants:{route:{12:{variant_name:"orca",descriptor:{data:"02_orca_tlv",signatures:{prod:"prodsig_v12",test:"testsig_v12"}}}}}})};e(l(n,"prod")).toEqual([{enumId:"swap",variantIndex:46,descriptor:{data:"01_raydium_tlv",signature:"prodsig_v46"}},{enumId:"route",variantIndex:12,descriptor:{data:"02_orca_tlv",signature:"prodsig_v12"}}])}),t("leaves the signature empty when CAL has none for the configured mode",()=>{const n=o({enum_variants:{swap:{46:{variant_name:"raydiumCP",descriptor:{data:"01_raydium_tlv",signatures:{prod:"prodsig_v46"}}}}}});e(l({"00000000":n},"test")).toEqual([{enumId:"swap",variantIndex:46,descriptor:{data:"01_raydium_tlv",signature:""}}])})})});
|
|
2
2
|
//# sourceMappingURL=InstructionInfoMapper.test.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../../src/modules/solana/instruction-info/data/InstructionInfoMapper.test.ts"],
|
|
4
|
-
"sourcesContent": ["import { describe, expect, it } from \"vitest\";\n\nimport { type CalInstructionDescriptorDto } from \"./InstructionInfoDto\";\nimport {\n toAccountResets,\n toDisplayFields,\n toInstructionInfoPayload,\n toProgramEnumVariants,\n toValueFlowPorts,\n} from \"./InstructionInfoMapper\";\n\nconst PROGRAM = \"11111111111111111111111111111111\";\n\nfunction makeDescriptor(\n overrides: Partial<CalInstructionDescriptorDto> = {},\n): CalInstructionDescriptorDto {\n return {\n discriminator_hex: \"00000000\",\n instruction_name: \"createAccount\",\n descriptor: {\n data: \"0001sys_data\",\n signatures: { prod: \"prodsig\", test: \"testsig\" },\n },\n ...overrides,\n };\n}\n\ndescribe(\"InstructionInfoMapper\", () => {\n describe(\"toValueFlowPorts\", () => {\n it(\"returns an empty list for undefined input\", () => {\n expect(toValueFlowPorts()).toEqual([]);\n });\n\n it(\"picks only the decoded fields, dropping the signed-TLV descriptor\", () => {\n expect(\n toValueFlowPorts([\n {\n descriptor: \"vfp1\",\n account_indices: [0, 1],\n optional_account_strategy: \"OMITTED\",\n token_value: { kind: \"NATIVE\" },\n },\n ]),\n ).toEqual([\n {\n account_indices: [0, 1],\n optional_account_strategy: \"OMITTED\",\n token_value: { kind: \"NATIVE\" },\n },\n ]);\n });\n\n it(\"leaves the absent optional strategy as undefined\", () => {\n expect(\n toValueFlowPorts([\n {\n descriptor: \"vfp1\",\n account_indices: [0],\n token_value: { kind: \"NATIVE\" },\n },\n ]),\n ).toEqual([\n {\n account_indices: [0],\n optional_account_strategy: undefined,\n token_value: { kind: \"NATIVE\" },\n },\n ]);\n });\n });\n\n describe(\"toAccountResets\", () => {\n it(\"returns an empty list for undefined input\", () => {\n expect(toAccountResets()).toEqual([]);\n });\n\n it(\"maps the decoded fields, dropping the signed-TLV descriptor\", () => {\n expect(\n toAccountResets([\n {\n descriptor: \"ar1\",\n account_index: 2,\n require_pre_balance_zero: true,\n },\n ]),\n ).toEqual([{ account_index: 2, require_pre_balance_zero: true }]);\n });\n\n it(\"drops entries missing account_index instead of defaulting to slot 0\", () => {\n expect(\n toAccountResets([\n { descriptor: \"ar0\", account_index: 0 },\n { descriptor: \"arBad\" },\n { descriptor: \"ar1\", account_index: 1 },\n ]),\n ).toEqual([\n { account_index: 0, require_pre_balance_zero: undefined },\n { account_index: 1, require_pre_balance_zero: undefined },\n ]);\n });\n });\n\n describe(\"toDisplayFields\", () => {\n it(\"returns an empty list for undefined input\", () => {\n expect(toDisplayFields()).toEqual([]);\n });\n\n it(\"picks name and param, dropping the signed-TLV descriptor\", () => {\n expect(\n toDisplayFields([\n {\n descriptor: \"df1\",\n name: \"New Account\",\n param: {\n type: \"ACCOUNT\",\n value: { source: \"ACCOUNT_PATH\", account_index: 1 },\n },\n },\n ]),\n ).toEqual([\n {\n name: \"New Account\",\n param: {\n type: \"ACCOUNT\",\n value: { source: \"ACCOUNT_PATH\", account_index: 1 },\n },\n },\n ]);\n });\n\n it(\"falls back to an empty-type param when param is absent\", () => {\n expect(toDisplayFields([{ descriptor: \"df1\" }])).toEqual([\n { name: undefined, param: { type: \"\" } },\n ]);\n });\n });\n\n describe(\"toInstructionInfoPayload\", () => {\n it(\"surfaces CAL's decoded JSON (type pool, mint assoc, ports, resets, fields) and ordered substructures\", () => {\n const dto = makeDescriptor({\n idl_descriptor: {\n root_type: 3,\n type_pool: [\n { index: 0, kind: \"STRUCT\", refs: [1] },\n { index: 1, kind: \"U64\" },\n ],\n },\n mint_association: { account_index: 1, mint_index: 3 },\n display_fields: [\n {\n descriptor: \"df1\",\n name: \"New Account\",\n param: {\n type: \"ACCOUNT\",\n value: { source: \"ACCOUNT_PATH\", account_index: 1 },\n },\n },\n ],\n value_flow_ports: [\n {\n descriptor: \"vfp1\",\n account_indices: [0],\n token_value: { kind: \"NATIVE\" },\n },\n ],\n hide_rules: [{ descriptor: \"hr1\" }],\n account_resets: [\n {\n descriptor: \"ar1\",\n account_index: 1,\n require_pre_balance_zero: true,\n },\n ],\n });\n\n const payload = toInstructionInfoPayload(\n PROGRAM,\n \"00000000\",\n dto,\n \"prod\",\n ).unsafeCoerce();\n\n expect(payload).toMatchObject({\n programId: PROGRAM,\n discriminator: \"00000000\",\n instructionInfo: { data: \"0001sys_data\", signature: \"prodsig\" },\n idlDescriptor: {\n rootType: 3,\n typePool: [\n { index: 0, kind: \"STRUCT\", refs: [1] },\n { index: 1, kind: \"U64\" },\n ],\n },\n mintAssociations: [{ account_index: 1, mint_index: 3 }],\n valueFlowPorts: [\n {\n account_indices: [0],\n optional_account_strategy: undefined,\n token_value: { kind: \"NATIVE\" },\n },\n ],\n accountResets: [{ account_index: 1, require_pre_balance_zero: true }],\n displayFields: [\n {\n name: \"New Account\",\n param: {\n type: \"ACCOUNT\",\n value: { source: \"ACCOUNT_PATH\", account_index: 1 },\n },\n },\n ],\n });\n // Substructures carry the signed TLVs for the device, in order.\n expect(payload.substructures).toEqual([\n { kind: 0x00, data: \"df1\" },\n { kind: 0x01, data: \"vfp1\" },\n { kind: 0x02, data: \"hr1\" },\n { kind: 0x03, data: \"ar1\" },\n ]);\n });\n\n it(\"defaults idlDescriptor when CAL omits it\", () => {\n const payload = toInstructionInfoPayload(\n PROGRAM,\n \"00000000\",\n makeDescriptor(),\n \"prod\",\n ).unsafeCoerce();\n expect(payload.idlDescriptor).toEqual({ typePool: [], rootType: 0 });\n expect(payload.mintAssociations).toEqual([]);\n });\n\n it(\"bundles CAL enum_variants into the payload with the mode signature\", () => {\n const dto = makeDescriptor({\n enum_variants: {\n swap: {\n \"46\": {\n variant_name: \"raydiumCP\",\n descriptor: {\n data: \"01_raydium_tlv\",\n signatures: { prod: \"prodsig_v46\", test: \"testsig_v46\" },\n },\n },\n },\n },\n });\n const payload = toInstructionInfoPayload(\n PROGRAM,\n \"00000000\",\n dto,\n \"prod\",\n ).unsafeCoerce();\n expect(payload.enumVariants).toEqual([\n {\n enumId: \"swap\",\n variantIndex: 46,\n descriptor: { data: \"01_raydium_tlv\", signature: \"prodsig_v46\" },\n },\n ]);\n });\n\n it(\"skips enum_variants keyed by a non-u16 index instead of leaking NaN\", () => {\n const dto = makeDescriptor({\n enum_variants: {\n swap: {\n \"46\": {\n variant_name: \"raydiumCP\",\n descriptor: {\n data: \"01_raydium_tlv\",\n signatures: { prod: \"prodsig_v46\", test: \"testsig_v46\" },\n },\n },\n \"7abc\": {\n variant_name: \"junk\",\n descriptor: {\n data: \"junk_tlv\",\n signatures: { prod: \"x\", test: \"x\" },\n },\n },\n \"70000\": {\n variant_name: \"overflow\",\n descriptor: {\n data: \"overflow_tlv\",\n signatures: { prod: \"x\", test: \"x\" },\n },\n },\n },\n },\n });\n const payload = toInstructionInfoPayload(\n PROGRAM,\n \"00000000\",\n dto,\n \"prod\",\n ).unsafeCoerce();\n expect(payload.enumVariants).toEqual([\n {\n enumId: \"swap\",\n variantIndex: 46,\n descriptor: { data: \"01_raydium_tlv\", signature: \"prodsig_v46\" },\n },\n ]);\n });\n\n it(\"selects the signature for the configured mode\", () => {\n const payload = toInstructionInfoPayload(\n PROGRAM,\n \"00000000\",\n makeDescriptor(),\n \"test\",\n ).unsafeCoerce();\n expect(payload.instructionInfo.signature).toBe(\"testsig\");\n });\n\n it(\"returns Left when the configured mode signature is missing\", () => {\n const dto = makeDescriptor();\n delete (dto.descriptor.signatures as { test?: string }).test;\n const result = toInstructionInfoPayload(PROGRAM, \"00000000\", dto, \"test\");\n expect(result.isLeft()).toBe(true);\n expect(result.swap().unsafeCoerce().message).toMatch(\n /missing 'test' signature/,\n );\n });\n });\n\n describe(\"toProgramEnumVariants\", () => {\n it(\"flattens enum variants across all descriptors, dropping malformed keys\", () => {\n const descriptors: Record<string, CalInstructionDescriptorDto> = {\n \"00000000\": makeDescriptor({\n enum_variants: {\n swap: {\n \"46\": {\n variant_name: \"raydiumCP\",\n descriptor: {\n data: \"01_raydium_tlv\",\n signatures: { prod: \"prodsig_v46\", test: \"testsig_v46\" },\n },\n },\n bad: {\n variant_name: \"junk\",\n descriptor: {\n data: \"junk_tlv\",\n signatures: { prod: \"x\", test: \"x\" },\n },\n },\n },\n },\n }),\n \"00000001\": makeDescriptor({\n enum_variants: {\n route: {\n \"12\": {\n variant_name: \"orca\",\n descriptor: {\n data: \"02_orca_tlv\",\n signatures: { prod: \"prodsig_v12\", test: \"testsig_v12\" },\n },\n },\n },\n },\n }),\n };\n expect(toProgramEnumVariants(descriptors, \"prod\")).toEqual([\n {\n enumId: \"swap\",\n variantIndex: 46,\n descriptor: { data: \"01_raydium_tlv\", signature: \"prodsig_v46\" },\n },\n {\n enumId: \"route\",\n variantIndex: 12,\n descriptor: { data: \"02_orca_tlv\", signature: \"prodsig_v12\" },\n },\n ]);\n });\n\n it(\"leaves the signature empty when CAL has none for the configured mode\", () => {\n const dto = makeDescriptor({\n enum_variants: {\n swap: {\n \"46\": {\n variant_name: \"raydiumCP\",\n descriptor: {\n data: \"01_raydium_tlv\",\n signatures: { prod: \"prodsig_v46\" },\n },\n },\n },\n },\n });\n expect(toProgramEnumVariants({ \"00000000\": dto }, \"test\")).toEqual([\n {\n enumId: \"swap\",\n variantIndex: 46,\n descriptor: { data: \"01_raydium_tlv\", signature: \"\" },\n },\n ]);\n });\n });\n});\n"],
|
|
5
|
-
"mappings": "AAAA,OAAS,YAAAA,EAAU,UAAAC,EAAQ,MAAAC,MAAU,SAGrC,OACE,mBAAAC,EACA,mBAAAC,EACA,4BAAAC,EACA,yBAAAC,EACA,oBAAAC,MACK,0BAEP,MAAMC,EAAU,mCAEhB,SAASC,EACPC,EAAkD,CAAC,EACtB,CAC7B,MAAO,CACL,kBAAmB,WACnB,iBAAkB,gBAClB,WAAY,CACV,KAAM,eACN,WAAY,CAAE,KAAM,UAAW,KAAM,SAAU,CACjD,EACA,GAAGA,CACL,CACF,
|
|
6
|
-
"names": ["describe", "expect", "it", "toAccountResets", "toDisplayFields", "toInstructionInfoPayload", "toProgramEnumVariants", "toValueFlowPorts", "PROGRAM", "makeDescriptor", "overrides", "dto", "payload", "result", "descriptors"]
|
|
4
|
+
"sourcesContent": ["import { describe, expect, it } from \"vitest\";\n\nimport { type CalInstructionDescriptorDto } from \"./InstructionInfoDto\";\nimport {\n toAccountResets,\n toDisplayFields,\n toHideRules,\n toInstructionInfoPayload,\n toOwnerAssociations,\n toProgramEnumVariants,\n toValueFlowPorts,\n} from \"./InstructionInfoMapper\";\n\nconst PROGRAM = \"11111111111111111111111111111111\";\n\nfunction makeDescriptor(\n overrides: Partial<CalInstructionDescriptorDto> = {},\n): CalInstructionDescriptorDto {\n return {\n discriminator_hex: \"00000000\",\n instruction_name: \"createAccount\",\n descriptor: {\n data: \"0001sys_data\",\n signatures: { prod: \"prodsig\", test: \"testsig\" },\n },\n ...overrides,\n };\n}\n\ndescribe(\"InstructionInfoMapper\", () => {\n describe(\"toValueFlowPorts\", () => {\n it(\"returns an empty list for undefined input\", () => {\n expect(toValueFlowPorts()).toEqual([]);\n });\n\n it(\"picks only the decoded fields, dropping the signed-TLV descriptor\", () => {\n expect(\n toValueFlowPorts([\n {\n descriptor: \"vfp1\",\n account_indices: [0, 1],\n optional_account_strategy: \"OMITTED\",\n token_value: { kind: \"RESOLVE\", fallback_account: 5 },\n active_when: [\"IS_SIGNER\"],\n },\n ]),\n ).toEqual([\n {\n account_indices: [0, 1],\n optional_account_strategy: \"OMITTED\",\n token_value: { kind: \"RESOLVE\", fallback_account: 5 },\n active_when: [\"IS_SIGNER\"],\n },\n ]);\n });\n\n it(\"leaves the absent optional strategy as undefined\", () => {\n expect(\n toValueFlowPorts([\n {\n descriptor: \"vfp1\",\n account_indices: [0],\n token_value: { kind: \"NATIVE\" },\n },\n ]),\n ).toEqual([\n {\n account_indices: [0],\n optional_account_strategy: undefined,\n token_value: { kind: \"NATIVE\" },\n active_when: undefined,\n },\n ]);\n });\n });\n\n describe(\"toHideRules\", () => {\n it(\"returns an empty list for undefined input\", () => {\n expect(toHideRules()).toEqual([]);\n });\n\n it(\"maps the decoded fields, dropping the signed-TLV descriptor\", () => {\n expect(\n toHideRules([\n {\n descriptor: \"hr1\",\n rule_set_index: 1,\n target: { source: \"ACCOUNT_PATH\", account_index: 2 },\n condition: \"IS_SIGNER\",\n },\n ]),\n ).toEqual([\n {\n rule_set_index: 1,\n target: { source: \"ACCOUNT_PATH\", account_index: 2 },\n condition: \"IS_SIGNER\",\n },\n ]);\n });\n\n it(\"keeps a rule with no condition so its target stays in the requirement set\", () => {\n // The signed TLV reaches the device regardless, and the device resolves\n // the target of every rule it receives.\n expect(\n toHideRules([\n {\n descriptor: \"hrNoCondition\",\n target: { source: \"ACCOUNT_PATH\", account_index: 4 },\n },\n ]),\n ).toEqual([\n {\n rule_set_index: undefined,\n target: { source: \"ACCOUNT_PATH\", account_index: 4 },\n condition: undefined,\n },\n ]);\n });\n });\n\n describe(\"toOwnerAssociations\", () => {\n it(\"returns an empty list for undefined input\", () => {\n expect(toOwnerAssociations(undefined)).toEqual([]);\n });\n\n it(\"wraps CAL's single association into a list\", () => {\n expect(\n toOwnerAssociations({\n account_index: 1,\n owner: { source: \"ACCOUNT_PATH\", account_index: 0 },\n }),\n ).toEqual([\n {\n account_index: 1,\n owner: { source: \"ACCOUNT_PATH\", account_index: 0 },\n },\n ]);\n });\n\n it(\"drops a half-declared pair\", () => {\n expect(toOwnerAssociations({ account_index: 1 })).toEqual([]);\n expect(\n toOwnerAssociations({ owner: { source: \"ACCOUNT_PATH\" } }),\n ).toEqual([]);\n });\n });\n\n describe(\"toAccountResets\", () => {\n it(\"returns an empty list for undefined input\", () => {\n expect(toAccountResets()).toEqual([]);\n });\n\n it(\"maps the decoded fields, dropping the signed-TLV descriptor\", () => {\n expect(\n toAccountResets([\n {\n descriptor: \"ar1\",\n account_index: 2,\n require_pre_balance_zero: true,\n },\n ]),\n ).toEqual([{ account_index: 2, require_pre_balance_zero: true }]);\n });\n\n it(\"drops entries missing account_index instead of defaulting to slot 0\", () => {\n expect(\n toAccountResets([\n { descriptor: \"ar0\", account_index: 0 },\n { descriptor: \"arBad\" },\n { descriptor: \"ar1\", account_index: 1 },\n ]),\n ).toEqual([\n { account_index: 0, require_pre_balance_zero: undefined },\n { account_index: 1, require_pre_balance_zero: undefined },\n ]);\n });\n });\n\n describe(\"toDisplayFields\", () => {\n it(\"returns an empty list for undefined input\", () => {\n expect(toDisplayFields()).toEqual([]);\n });\n\n it(\"picks name and param, dropping the signed-TLV descriptor\", () => {\n expect(\n toDisplayFields([\n {\n descriptor: \"df1\",\n name: \"New Account\",\n param: {\n type: \"ACCOUNT\",\n value: { source: \"ACCOUNT_PATH\", account_index: 1 },\n },\n },\n ]),\n ).toEqual([\n {\n name: \"New Account\",\n param: {\n type: \"ACCOUNT\",\n value: { source: \"ACCOUNT_PATH\", account_index: 1 },\n },\n },\n ]);\n });\n\n it(\"falls back to an empty-type param when param is absent\", () => {\n expect(toDisplayFields([{ descriptor: \"df1\" }])).toEqual([\n { name: undefined, param: { type: \"\" } },\n ]);\n });\n });\n\n describe(\"toInstructionInfoPayload\", () => {\n it(\"surfaces CAL's decoded JSON (type pool, mint assoc, ports, resets, fields) and ordered substructures\", () => {\n const dto = makeDescriptor({\n idl_descriptor: {\n root_type: 3,\n type_pool: [\n { index: 0, kind: \"STRUCT\", refs: [1] },\n { index: 1, kind: \"U64\" },\n ],\n },\n mint_association: { account_index: 1, mint_index: 3 },\n owner_association: {\n account_index: 1,\n owner: { source: \"ACCOUNT_PATH\", account_index: 0 },\n },\n display_fields: [\n {\n descriptor: \"df1\",\n name: \"New Account\",\n param: {\n type: \"ACCOUNT\",\n value: { source: \"ACCOUNT_PATH\", account_index: 1 },\n },\n },\n ],\n value_flow_ports: [\n {\n descriptor: \"vfp1\",\n account_indices: [0],\n token_value: { kind: \"NATIVE\" },\n },\n ],\n hide_rules: [\n {\n descriptor: \"hr1\",\n rule_set_index: 0,\n target: { source: \"ACCOUNT_PATH\", account_index: 1 },\n condition: \"ACCOUNT_EFFECTS_DISPLAYED_ELSEWHERE\",\n },\n ],\n account_resets: [\n {\n descriptor: \"ar1\",\n account_index: 1,\n require_pre_balance_zero: true,\n },\n ],\n });\n\n const payload = toInstructionInfoPayload(\n PROGRAM,\n \"00000000\",\n dto,\n \"prod\",\n ).unsafeCoerce();\n\n expect(payload).toMatchObject({\n programId: PROGRAM,\n discriminator: \"00000000\",\n instructionInfo: { data: \"0001sys_data\", signature: \"prodsig\" },\n idlDescriptor: {\n rootType: 3,\n typePool: [\n { index: 0, kind: \"STRUCT\", refs: [1] },\n { index: 1, kind: \"U64\" },\n ],\n },\n mintAssociations: [{ account_index: 1, mint_index: 3 }],\n ownerAssociations: [\n {\n account_index: 1,\n owner: { source: \"ACCOUNT_PATH\", account_index: 0 },\n },\n ],\n valueFlowPorts: [\n {\n account_indices: [0],\n optional_account_strategy: undefined,\n token_value: { kind: \"NATIVE\" },\n },\n ],\n hideRules: [\n {\n rule_set_index: 0,\n target: { source: \"ACCOUNT_PATH\", account_index: 1 },\n condition: \"ACCOUNT_EFFECTS_DISPLAYED_ELSEWHERE\",\n },\n ],\n accountResets: [{ account_index: 1, require_pre_balance_zero: true }],\n displayFields: [\n {\n name: \"New Account\",\n param: {\n type: \"ACCOUNT\",\n value: { source: \"ACCOUNT_PATH\", account_index: 1 },\n },\n },\n ],\n });\n // Substructures carry the signed TLVs for the device, in order.\n expect(payload.substructures).toEqual([\n { kind: 0x00, data: \"df1\" },\n { kind: 0x01, data: \"vfp1\" },\n { kind: 0x02, data: \"hr1\" },\n { kind: 0x03, data: \"ar1\" },\n ]);\n });\n\n it(\"defaults idlDescriptor when CAL omits it\", () => {\n const payload = toInstructionInfoPayload(\n PROGRAM,\n \"00000000\",\n makeDescriptor(),\n \"prod\",\n ).unsafeCoerce();\n expect(payload.idlDescriptor).toEqual({ typePool: [], rootType: 0 });\n expect(payload.mintAssociations).toEqual([]);\n });\n\n it(\"bundles CAL enum_variants into the payload with the mode signature\", () => {\n const dto = makeDescriptor({\n enum_variants: {\n swap: {\n \"46\": {\n variant_name: \"raydiumCP\",\n descriptor: {\n data: \"01_raydium_tlv\",\n signatures: { prod: \"prodsig_v46\", test: \"testsig_v46\" },\n },\n },\n },\n },\n });\n const payload = toInstructionInfoPayload(\n PROGRAM,\n \"00000000\",\n dto,\n \"prod\",\n ).unsafeCoerce();\n expect(payload.enumVariants).toEqual([\n {\n enumId: \"swap\",\n variantIndex: 46,\n descriptor: { data: \"01_raydium_tlv\", signature: \"prodsig_v46\" },\n },\n ]);\n });\n\n it(\"skips enum_variants keyed by a non-u16 index instead of leaking NaN\", () => {\n const dto = makeDescriptor({\n enum_variants: {\n swap: {\n \"46\": {\n variant_name: \"raydiumCP\",\n descriptor: {\n data: \"01_raydium_tlv\",\n signatures: { prod: \"prodsig_v46\", test: \"testsig_v46\" },\n },\n },\n \"7abc\": {\n variant_name: \"junk\",\n descriptor: {\n data: \"junk_tlv\",\n signatures: { prod: \"x\", test: \"x\" },\n },\n },\n \"70000\": {\n variant_name: \"overflow\",\n descriptor: {\n data: \"overflow_tlv\",\n signatures: { prod: \"x\", test: \"x\" },\n },\n },\n },\n },\n });\n const payload = toInstructionInfoPayload(\n PROGRAM,\n \"00000000\",\n dto,\n \"prod\",\n ).unsafeCoerce();\n expect(payload.enumVariants).toEqual([\n {\n enumId: \"swap\",\n variantIndex: 46,\n descriptor: { data: \"01_raydium_tlv\", signature: \"prodsig_v46\" },\n },\n ]);\n });\n\n it(\"selects the signature for the configured mode\", () => {\n const payload = toInstructionInfoPayload(\n PROGRAM,\n \"00000000\",\n makeDescriptor(),\n \"test\",\n ).unsafeCoerce();\n expect(payload.instructionInfo.signature).toBe(\"testsig\");\n });\n\n it(\"returns Left when the configured mode signature is missing\", () => {\n const dto = makeDescriptor();\n delete (dto.descriptor.signatures as { test?: string }).test;\n const result = toInstructionInfoPayload(PROGRAM, \"00000000\", dto, \"test\");\n expect(result.isLeft()).toBe(true);\n expect(result.swap().unsafeCoerce().message).toMatch(\n /missing 'test' signature/,\n );\n });\n });\n\n describe(\"toProgramEnumVariants\", () => {\n it(\"flattens enum variants across all descriptors, dropping malformed keys\", () => {\n const descriptors: Record<string, CalInstructionDescriptorDto> = {\n \"00000000\": makeDescriptor({\n enum_variants: {\n swap: {\n \"46\": {\n variant_name: \"raydiumCP\",\n descriptor: {\n data: \"01_raydium_tlv\",\n signatures: { prod: \"prodsig_v46\", test: \"testsig_v46\" },\n },\n },\n bad: {\n variant_name: \"junk\",\n descriptor: {\n data: \"junk_tlv\",\n signatures: { prod: \"x\", test: \"x\" },\n },\n },\n },\n },\n }),\n \"00000001\": makeDescriptor({\n enum_variants: {\n route: {\n \"12\": {\n variant_name: \"orca\",\n descriptor: {\n data: \"02_orca_tlv\",\n signatures: { prod: \"prodsig_v12\", test: \"testsig_v12\" },\n },\n },\n },\n },\n }),\n };\n expect(toProgramEnumVariants(descriptors, \"prod\")).toEqual([\n {\n enumId: \"swap\",\n variantIndex: 46,\n descriptor: { data: \"01_raydium_tlv\", signature: \"prodsig_v46\" },\n },\n {\n enumId: \"route\",\n variantIndex: 12,\n descriptor: { data: \"02_orca_tlv\", signature: \"prodsig_v12\" },\n },\n ]);\n });\n\n it(\"leaves the signature empty when CAL has none for the configured mode\", () => {\n const dto = makeDescriptor({\n enum_variants: {\n swap: {\n \"46\": {\n variant_name: \"raydiumCP\",\n descriptor: {\n data: \"01_raydium_tlv\",\n signatures: { prod: \"prodsig_v46\" },\n },\n },\n },\n },\n });\n expect(toProgramEnumVariants({ \"00000000\": dto }, \"test\")).toEqual([\n {\n enumId: \"swap\",\n variantIndex: 46,\n descriptor: { data: \"01_raydium_tlv\", signature: \"\" },\n },\n ]);\n });\n });\n});\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["describe", "expect", "it", "toAccountResets", "toDisplayFields", "toHideRules", "toInstructionInfoPayload", "toOwnerAssociations", "toProgramEnumVariants", "toValueFlowPorts", "PROGRAM", "makeDescriptor", "overrides", "dto", "payload", "result", "descriptors"]
|
|
7
7
|
}
|
package/lib/esm/src/modules/solana/instruction-info/domain/InstructionInfoContextLoader.test.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{DeviceModelId as u}from"@ledgerhq/device-management-kit";import{Left as g,Right as d}from"purify-ts";import{beforeEach as v,describe as O,expect as e,it as I,vi as s}from"vitest";import{ClearSignContextType as i}from"../../../../shared/model/ClearSignContext";import{InstructionInfoContextLoader as S}from"./InstructionInfoContextLoader";const w=()=>({debug:s.fn(),info:s.fn(),warn:s.fn(),error:s.fn(),subscribers:[]}),
|
|
1
|
+
import{DeviceModelId as u}from"@ledgerhq/device-management-kit";import{Left as g,Right as d}from"purify-ts";import{beforeEach as v,describe as O,expect as e,it as I,vi as s}from"vitest";import{ClearSignContextType as i}from"../../../../shared/model/ClearSignContext";import{InstructionInfoContextLoader as S}from"./InstructionInfoContextLoader";const w=()=>({debug:s.fn(),info:s.fn(),warn:s.fn(),error:s.fn(),subscribers:[]}),A={keyUsageNumber:8,payload:new Uint8Array([66])},a="11111111111111111111111111111111",m="JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4";function y(){return{programId:a,discriminator:"00000000",instructionInfo:{data:"0001sys_data",signature:"prodsig_sys"},substructures:[{kind:0,data:"df1"},{kind:0,data:"df2"},{kind:1,data:"vfp1"}],enumVariants:[],idlDescriptor:{typePool:[],rootType:0},mintAssociations:[],ownerAssociations:[],valueFlowPorts:[],accountResets:[],displayFields:[],hideRules:[]}}function f(){return{programId:a,descriptors:{"00000000":d(y())},enumVariants:[]}}function _(){return{programId:m,discriminator:"e517cb977ae3ad2a",instructionInfo:{data:"0001jup_data",signature:"prodsig_jup"},substructures:[],enumVariants:[],idlDescriptor:{typePool:[],rootType:0},mintAssociations:[],ownerAssociations:[],valueFlowPorts:[],accountResets:[],displayFields:[],hideRules:[]}}function h(){return{programId:m,descriptors:{e517cb977ae3ad2a:d(_())},enumVariants:[]}}function R(c=[]){return{programId:m,descriptors:{e517cb977ae3ad2a:d({..._(),enumVariants:c})},enumVariants:c}}O("InstructionInfoContextLoader",()=>{let c,N;v(()=>{s.restoreAllMocks(),c={getInstructionInfo:s.fn()},N={loadCertificate:s.fn().mockResolvedValue(A)}});const l=()=>new S(c,N,w);O("canHandle",()=>{I("returns true when SOLANA_INSTRUCTION_INFO is requested and instructions are present",()=>{e(l().canHandle({deviceModelId:u.NANO_X,instructions:[{programId:a}]},[i.SOLANA_INSTRUCTION_INFO])).toBe(!0)}),I("returns false when SOLANA_INSTRUCTION_INFO is not requested",()=>{e(l().canHandle({deviceModelId:u.NANO_X,instructions:[{programId:a}]},[i.SOLANA_TOKEN])).toBe(!1)}),I("returns false on missing / empty / malformed instructions",()=>{const o=l(),t=[i.SOLANA_INSTRUCTION_INFO];e(o.canHandle({},t)).toBe(!1),e(o.canHandle({instructions:[]},t)).toBe(!1),e(o.canHandle({instructions:[{programId:""}]},t)).toBe(!1),e(o.canHandle(null,t)).toBe(!1),e(o.canHandle("string",t)).toBe(!1)})}),O("load",()=>{I("fans out one CAL call per distinct programId in parallel",async()=>{const o=l(),t=s.spyOn(c,"getInstructionInfo").mockImplementation(async({programId:r})=>r===a?d(f()):r===m?d(h()):g(new Error("unknown program"))),n=await o.load({deviceModelId:u.NANO_X,instructions:[{programId:a,discriminator:"00000000"},{programId:a,discriminator:"00000000"},{programId:m,discriminator:"e517cb977ae3ad2a"}],network:"solana-mainnet"});e(t).toHaveBeenCalledTimes(2),e(t).toHaveBeenCalledWith({programId:a,network:"solana-mainnet"}),e(t).toHaveBeenCalledWith({programId:m,network:"solana-mainnet"}),e(n.every(r=>r.type===i.SOLANA_INSTRUCTION_INFO||r.type===i.ERROR)).toBe(!0),e(n.filter(r=>r.type===i.SOLANA_INSTRUCTION_INFO)).toHaveLength(2)}),I("emits one SOLANA_INSTRUCTION_INFO per matching (programId, discriminator), passing the decoded payload through with the certificate",async()=>{const o=l();s.spyOn(c,"getInstructionInfo").mockResolvedValue(d(f()));const n=(await o.load({deviceModelId:u.NANO_X,instructions:[{programId:a,discriminator:"00000000"}]})).find(r=>r.type===i.SOLANA_INSTRUCTION_INFO);e(n).toBeDefined(),e(n).toMatchObject({type:i.SOLANA_INSTRUCTION_INFO,certificate:A}),e(n.payload).toEqual(y())}),I("does NOT emit SOLANA_ENUM_VARIANT contexts (those come from EnumVariantContextLoader)",async()=>{const o=l(),t=R([{enumId:"swap",variantIndex:46,descriptor:{data:"01_raydium_tlv",signature:"prodsig_v46"}}]);s.spyOn(c,"getInstructionInfo").mockResolvedValue(d(t));const n=await o.load({deviceModelId:u.NANO_X,instructions:[{programId:m,discriminator:"e517cb977ae3ad2a"}]});e(n.filter(r=>r.type===i.SOLANA_ENUM_VARIANT)).toHaveLength(0)}),I("bundles CAL enum_variants into the SOLANA_INSTRUCTION_INFO payload (host decode cache)",async()=>{const o=l(),t=[{enumId:"swap",variantIndex:46,descriptor:{data:"01_raydium_tlv",signature:"prodsig_v46"}}];s.spyOn(c,"getInstructionInfo").mockResolvedValue(d(R(t)));const r=(await o.load({deviceModelId:u.NANO_X,instructions:[{programId:m,discriminator:"e517cb977ae3ad2a"}]})).find(p=>p.type===i.SOLANA_INSTRUCTION_INFO);e(r.payload.enumVariants).toEqual(t)}),I("forwards exactly the enumVariants the data source decoded \u2014 no NaN indices",async()=>{const o=l(),t={enumId:"swap",variantIndex:46,descriptor:{data:"01_raydium_tlv",signature:"prodsig_v46"}};s.spyOn(c,"getInstructionInfo").mockResolvedValue(d(R([t])));const r=(await o.load({deviceModelId:u.NANO_X,instructions:[{programId:m,discriminator:"e517cb977ae3ad2a"}]})).find(p=>p.type===i.SOLANA_INSTRUCTION_INFO);e(r.payload.enumVariants).toEqual([t])}),I("filters descriptors by requested discriminator",async()=>{const o=l(),t={programId:a,descriptors:{"00000000":d(y()),"00000001":d({...y(),discriminator:"00000001",instructionInfo:{data:"0001other",signature:"p"}})},enumVariants:[]};s.spyOn(c,"getInstructionInfo").mockResolvedValue(d(t));const r=(await o.load({deviceModelId:u.NANO_X,instructions:[{programId:a,discriminator:"00000000"}]})).filter(p=>p.type===i.SOLANA_INSTRUCTION_INFO);e(r).toHaveLength(1),e(r[0].payload.discriminator).toBe("00000000")}),I("emits an ERROR context for a descriptor the data source could not decode",async()=>{const o=l(),t={programId:a,descriptors:{"00000000":g(new Error("missing 'test' signature"))},enumVariants:[]};s.spyOn(c,"getInstructionInfo").mockResolvedValue(d(t));const n=await o.load({deviceModelId:u.NANO_X,instructions:[{programId:a,discriminator:"00000000"}]});e(n).toHaveLength(1),e(n[0]?.type).toBe(i.ERROR),e(n[0].error.message).toMatch(/missing 'test' signature/)}),I("emits one ERROR context when CAL fails for a program but keeps processing the others",async()=>{const o=l();s.spyOn(c,"getInstructionInfo").mockImplementation(async({programId:p})=>p===a?d(f()):g(new Error("upstream-500")));const t=await o.load({deviceModelId:u.NANO_X,instructions:[{programId:a,discriminator:"00000000"},{programId:m,discriminator:"e517cb977ae3ad2a"}]}),n=t.filter(p=>p.type===i.ERROR),r=t.filter(p=>p.type===i.SOLANA_INSTRUCTION_INFO);e(n).toHaveLength(1),e(r).toHaveLength(1)}),I("degrades every program to ERROR when certificate loading fails",async()=>{s.spyOn(N,"loadCertificate").mockRejectedValue(new Error("pki-down")),s.spyOn(c,"getInstructionInfo").mockResolvedValue(d(f()));const t=await l().load({deviceModelId:u.NANO_X,instructions:[{programId:a},{programId:m}]});e(t).toHaveLength(2),e(t.every(n=>n.type===i.ERROR)).toBe(!0)}),I("degrades every program to ERROR when the certificate resolves undefined",async()=>{s.spyOn(N,"loadCertificate").mockResolvedValue(void 0),s.spyOn(c,"getInstructionInfo").mockResolvedValue(d(f()));const t=await l().load({deviceModelId:u.NANO_X,instructions:[{programId:a},{programId:m}]});e(t).toHaveLength(2),e(t.every(n=>n.type===i.ERROR)).toBe(!0),e(t[0].error.message).toMatch(/certificate is missing/)}),I("falls back to default network when input.network is omitted or empty string",async()=>{const o=l(),t=s.spyOn(c,"getInstructionInfo").mockResolvedValue(d(f()));await o.load({deviceModelId:u.NANO_X,instructions:[{programId:a}]}),e(t).toHaveBeenLastCalledWith({programId:a,network:"solana-mainnet"}),await o.load({deviceModelId:u.NANO_X,instructions:[{programId:a}],network:""}),e(t).toHaveBeenLastCalledWith({programId:a,network:"solana-mainnet"})})})});
|
|
2
2
|
//# sourceMappingURL=InstructionInfoContextLoader.test.js.map
|