Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 5 additions & 10 deletions src/OcpClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,18 +133,13 @@ import type {
OcfStockAcceptanceOutput,
OcfStockCancellationOutput,
OcfStockClassAuthorizedSharesAdjustmentOutput,
OcfStockClassConversionRatioAdjustmentOutput,
OcfStockClassOutput,
OcfStockClassSplitOutput,
OcfStockConsolidationOutput,
OcfStockConversionOutput,
OcfStockIssuanceOutput,
OcfStockLegendTemplateOutput,
OcfStockPlanOutput,
OcfStockPlanPoolAdjustmentOutput,
OcfStockPlanReturnToPoolOutput,
OcfStockReissuanceOutput,
OcfStockRepurchaseOutput,
OcfStockRetractionOutput,
OcfStockTransferOutput,
OcfValuationOutput,
Expand Down Expand Up @@ -1133,15 +1128,15 @@ interface OpenCapTableMethods {
// Adjustments
issuerAuthorizedSharesAdjustment: EntityReader<OcfIssuerAuthorizedSharesAdjustmentOutput>;
stockClassAuthorizedSharesAdjustment: EntityReader<OcfStockClassAuthorizedSharesAdjustmentOutput>;
stockClassConversionRatioAdjustment: EntityReader<OcfStockClassConversionRatioAdjustmentOutput>;
stockClassSplit: EntityReader<OcfStockClassSplitOutput>;
stockClassConversionRatioAdjustment: EntityReader<OcfReadDataTypeFor<'stockClassConversionRatioAdjustment'>>;
stockClassSplit: EntityReader<OcfReadDataTypeFor<'stockClassSplit'>>;
stockPlanPoolAdjustment: EntityReader<OcfStockPlanPoolAdjustmentOutput>;
stockPlanReturnToPool: EntityReader<OcfStockPlanReturnToPoolOutput>;

// Other transactions
stockRepurchase: EntityReader<OcfStockRepurchaseOutput>;
stockConsolidation: EntityReader<OcfStockConsolidationOutput>;
stockReissuance: EntityReader<OcfStockReissuanceOutput>;
stockRepurchase: EntityReader<OcfReadDataTypeFor<'stockRepurchase'>>;
stockConsolidation: EntityReader<OcfReadDataTypeFor<'stockConsolidation'>>;
stockReissuance: EntityReader<OcfReadDataTypeFor<'stockReissuance'>>;
equityCompensationRelease: EntityReader<OcfEquityCompensationReleaseOutput>;
equityCompensationRepricing: EntityReader<OcfEquityCompensationRepricingOutput>;

Expand Down
24 changes: 21 additions & 3 deletions src/functions/OpenCapTable/capTable/damlEntityData.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import { Fairmint } from '@fairmint/open-captable-protocol-daml-js';
import { OcpErrorCodes, OcpParseError } from '../../../errors';
import { extractGeneratedCreateArgumentData, requireGeneratedRecord } from '../../../utils/generatedDamlValidation';
import {
assertSafeGeneratedDamlJson,
extractGeneratedCreateArgumentData,
requireGeneratedRecord,
} from '../../../utils/generatedDamlValidation';
import { initialSharesAuthorizedFromDaml } from '../../../utils/typeConversions';
import { projectDamlIssuerDataToNative } from '../issuer/getIssuerAsOcf';
import { parseDamlSafeInteger } from '../shared/damlIntegers';
import { assertCanonicalJsonGraph, requireDecimalString } from '../shared/ocfValues';
import { requireGeneratedDamlNumeric10 } from '../shared/generatedDamlValues';
import { assertCanonicalJsonGraph } from '../shared/ocfValues';
import { damlOptionalStakeholderRelationshipToNative } from '../stakeholderRelationshipChangeEvent/damlToOcf';
import { extractAndDecodeAcceptanceData, isAcceptanceEntityType } from './acceptanceContractData';
import {
Expand All @@ -28,6 +33,10 @@ import {
isComplexIssuanceEntityType,
validateComplexIssuanceDamlDataInput,
} from './issuanceContractData';
import {
extractAndDecodeStockCorporateActionData,
isStockCorporateActionEntityType,
} from './stockCorporateActionContractData';
import {
extractAndDecodeTransferData,
isTransferEntityType,
Expand Down Expand Up @@ -97,7 +106,7 @@ function preflightSemanticDamlEntityData(entityType: OcfEntityType, input: unkno
hasOwnField(input, 'quantity_converted') &&
input.quantity_converted !== null
) {
requireDecimalString(input.quantity_converted, 'convertibleConversion.quantity_converted');
requireGeneratedDamlNumeric10(input.quantity_converted, 'convertibleConversion.quantity_converted');
}
}

Expand All @@ -106,6 +115,11 @@ function createEntityDataDecoder<const EntityType extends OcfEntityType>(
codec: EntityDataCodec<DamlDataTypeFor<EntityType>>
): EntityDataDecoder<DamlDataTypeFor<EntityType>> {
return (input) => {
// Preserve the established corporate-action diagnostic root while the
// common lossless boundary below owns detachment, freezing, and decoding.
if (isStockCorporateActionEntityType(entityType) && input !== undefined) {
assertSafeGeneratedDamlJson(input, `damlToOcf.${entityType}`);
}
const options = {
rootPath: entityType,
description: entityType,
Expand Down Expand Up @@ -396,5 +410,9 @@ export function extractAndDecodeDamlEntityData(
return extractAndDecodeVestingData(entityType, createArgument);
}

if (isStockCorporateActionEntityType(entityType)) {
return extractAndDecodeStockCorporateActionData(entityType, createArgument);
}

return decodeDamlEntityData(entityType, extractEntityData(entityType, createArgument));
}
42 changes: 21 additions & 21 deletions src/functions/OpenCapTable/capTable/damlToOcf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ import { damlStockCancellationToNative } from '../stockCancellation/damlToOcf';
import { damlStockClassDataToNative } from '../stockClass/getStockClassAsOcf';
import { damlStockClassAuthorizedSharesAdjustmentDataToNative } from '../stockClassAuthorizedSharesAdjustment/getStockClassAuthorizedSharesAdjustmentAsOcf';
import { damlStockClassConversionRatioAdjustmentToNative } from '../stockClassConversionRatioAdjustment/damlToStockClassConversionRatioAdjustment';
import { decodeStockClassConversionRatioAdjustmentCreateArgument } from '../stockClassConversionRatioAdjustment/getStockClassConversionRatioAdjustmentAsOcf';
import { damlStockClassSplitToNative } from '../stockClassSplit/damlToStockClassSplit';
import { damlStockConsolidationToNative } from '../stockConsolidation/damlToStockConsolidation';
import { damlStockConversionToNative } from '../stockConversion/damlToOcf';
Expand Down Expand Up @@ -210,6 +209,27 @@ export function convertToOcf(
return damlWarrantExerciseToNative(data as Parameters<typeof damlWarrantExerciseToNative>[0]);
}

// Corporate-action converters own generated-codec losslessness plus their
// schema-specific cardinality and Numeric checks. Keep every public read path
// on the same decoder-backed boundary before the generic JSON guard.
if (type === 'stockClassConversionRatioAdjustment') {
return damlStockClassConversionRatioAdjustmentToNative(
data as Parameters<typeof damlStockClassConversionRatioAdjustmentToNative>[0]
);
}
if (type === 'stockClassSplit') {
return damlStockClassSplitToNative(data as Parameters<typeof damlStockClassSplitToNative>[0]);
}
if (type === 'stockConsolidation') {
return damlStockConsolidationToNative(data as Parameters<typeof damlStockConsolidationToNative>[0]);
}
if (type === 'stockReissuance') {
return damlStockReissuanceToNative(data as Parameters<typeof damlStockReissuanceToNative>[0]);
}
if (type === 'stockRepurchase') {
return damlStockRepurchaseToNative(data as Parameters<typeof damlStockRepurchaseToNative>[0]);
}

assertCanonicalJsonGraph(data, type);
switch (type) {
// ===== Core objects =====
Expand Down Expand Up @@ -238,16 +258,6 @@ export function convertToOcf(
case 'warrantAcceptance':
return damlWarrantAcceptanceToNative(data as Parameters<typeof damlWarrantAcceptanceToNative>[0]);

// Stock class adjustments (with converters from entity folders)
case 'stockClassConversionRatioAdjustment':
return damlStockClassConversionRatioAdjustmentToNative(
data as Parameters<typeof damlStockClassConversionRatioAdjustmentToNative>[0]
);
case 'stockClassSplit':
return damlStockClassSplitToNative(data as Parameters<typeof damlStockClassSplitToNative>[0]);
case 'stockConsolidation':
return damlStockConsolidationToNative(data as Parameters<typeof damlStockConsolidationToNative>[0]);

// Valuation and vesting (with converters from entity folders)
case 'valuation':
return damlValuationToNative(data);
Expand All @@ -257,8 +267,6 @@ export function convertToOcf(
return damlStockRetractionToNative(data as Parameters<typeof damlStockRetractionToNative>[0]);
case 'stockPlanReturnToPool':
return damlStockPlanReturnToPoolToNative(data as Parameters<typeof damlStockPlanReturnToPoolToNative>[0]);
case 'stockReissuance':
return damlStockReissuanceToNative(data as Parameters<typeof damlStockReissuanceToNative>[0]);
case 'warrantRetraction':
return damlWarrantRetractionToNative(data as Parameters<typeof damlWarrantRetractionToNative>[0]);
case 'convertibleRetraction':
Expand Down Expand Up @@ -286,10 +294,6 @@ export function convertToOcf(
case 'convertibleCancellation':
return damlConvertibleCancellationToNative(data as Parameters<typeof damlConvertibleCancellationToNative>[0]);

// Repurchase (with converter from entity folder)
case 'stockRepurchase':
return damlStockRepurchaseToNative(data as Parameters<typeof damlStockRepurchaseToNative>[0]);

// Stakeholder events (with converters from entity folders)
case 'stakeholderRelationshipChangeEvent':
return damlStakeholderRelationshipChangeEventToNative(
Expand Down Expand Up @@ -369,10 +373,6 @@ export async function getEntityAsOcf<T extends SupportedOcfReadType>(

// Convert DAML data to native OCF format
const nativeData = convertToOcf(entityType, decodedEntityData);
if (entityType === 'stockClassConversionRatioAdjustment') {
decodeStockClassConversionRatioAdjustmentCreateArgument(createArgument, `damlToOcf.${entityType}.createArgument`);
}

return Object.freeze({
data: nativeData,
contractId,
Expand Down
7 changes: 6 additions & 1 deletion src/functions/OpenCapTable/capTable/entityTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,14 @@ export type ImmutableOcfReadEntityType =
| 'equityCompensationTransfer'
| 'issuerAuthorizedSharesAdjustment'
| 'stockClassAuthorizedSharesAdjustment'
| 'stockClassConversionRatioAdjustment'
| 'stockClassSplit'
| 'stockConsolidation'
| 'stockConversion'
| 'stockTransfer'
| 'stockPlanPoolAdjustment'
| 'stockReissuance'
| 'stockRepurchase'
| 'stockTransfer'
| 'warrantExercise'
| 'warrantTransfer';

Expand Down
20 changes: 12 additions & 8 deletions src/functions/OpenCapTable/capTable/ocfToDaml.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,18 @@ function convertEntityToDaml(
parseOcfEntityInput(type, data);
return converted;
}
if (type === 'stockClassSplit') {
return stockClassSplitDataToDaml(data as OcfDataTypeFor<'stockClassSplit'>);
}
if (type === 'stockConsolidation') {
return stockConsolidationDataToDaml(data as OcfDataTypeFor<'stockConsolidation'>);
}
if (type === 'stockReissuance') {
return stockReissuanceDataToDaml(data as OcfDataTypeFor<'stockReissuance'>);
}
if (type === 'stockRepurchase') {
return stockRepurchaseDataToDaml(data as OcfDataTypeFor<'stockRepurchase'>);
}
if (type === 'convertibleConversion') {
const converted = convertibleConversionDataToDaml(data as OcfDataTypeFor<'convertibleConversion'>);
parseOcfEntityInput(type, data);
Expand Down Expand Up @@ -203,8 +215,6 @@ function convertEntityToDaml(
return stockPlanDataToDaml(d as OcfDataTypeFor<'stockPlan'>);
case 'stockCancellation':
return stockCancellationDataToDaml(d as OcfDataTypeFor<'stockCancellation'>);
case 'stockRepurchase':
return stockRepurchaseDataToDaml(d as OcfDataTypeFor<'stockRepurchase'>);
case 'issuer':
return issuerDataToDaml(d as OcfDataTypeFor<'issuer'>, { skipSchemaParse: true });
case 'equityCompensationCancellation':
Expand All @@ -219,12 +229,6 @@ function convertEntityToDaml(
return stockAcceptanceDataToDaml(d as OcfDataTypeFor<'stockAcceptance'>);
case 'stockRetraction':
return stockRetractionDataToDaml(d as OcfDataTypeFor<'stockRetraction'>);
case 'stockReissuance':
return stockReissuanceDataToDaml(d as OcfDataTypeFor<'stockReissuance'>);
case 'stockConsolidation':
return stockConsolidationDataToDaml(d as OcfDataTypeFor<'stockConsolidation'>);
case 'stockClassSplit':
return stockClassSplitDataToDaml(d as OcfDataTypeFor<'stockClassSplit'>);
case 'stockPlanReturnToPool':
return stockPlanReturnToPoolDataToDaml(d as OcfDataTypeFor<'stockPlanReturnToPool'>);
case 'valuation':
Expand Down
Loading