Skip to content
Closed
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
2 changes: 1 addition & 1 deletion OpenCapTable-v34/daml.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
sdk-version: 3.4.10
name: OpenCapTable-v34
source: daml
version: 0.0.3
version: 0.0.4
build-options:
- -Wno-crypto-text-is-alpha
- --typecheck-upgrades=no
Expand Down
2 changes: 1 addition & 1 deletion Test/daml.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ dependencies:
- daml-stdlib
- daml-script
data-dependencies:
- ../OpenCapTable-v34/.daml/dist/OpenCapTable-v34-0.0.3.dar
- ../OpenCapTable-v34/.daml/dist/OpenCapTable-v34-0.0.4.dar
build-options:
- -Wno-template-interface-depends-on-daml-script
72 changes: 39 additions & 33 deletions Test/daml/OpenCapTable/TestConversionMechanisms.daml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import Fairmint.OpenCapTable.Types.Monetary (OcfMonetary(..))
import Fairmint.OpenCapTable.Types.Stock (OcfInitialSharesAuthorized(..), OcfQuantitySourceType(..), OcfRatio(..), OcfStockClassType(..))
import OpenCapTable.HelpersTriggers (ocfTriggerElectiveAtWill)
import OpenCapTable.Setup
import OpenCapTable.TestHelpers (addDefaultStakeholder)
import OpenCapTable.TestHelpers (addDefaultStakeholder, defaultStockClass)

testTime : Time
testTime = DT.time (DA.date 2024 Jan 1) 0 0 0
Expand Down Expand Up @@ -392,22 +392,25 @@ testConversionMechanismRights_AllValidVariantsCreate = script do
capTableCid <- addDefaultStakeholder issuer cap_table
result1 <- submit issuer do
exerciseCmd capTableCid CT.UpdateCapTable with
creates = [CT.OcfCreateStockClass StockClassOcfData with
id = "SC_PREFERRED_ALL_CONVERSION_MECHANISMS"
name = "Preferred All Conversion Mechanisms"
class_type = OcfStockClassTypePreferred
default_id_prefix = "PAM-"
initial_shares_authorized = OcfInitialSharesNumeric 1_000_000.0
votes_per_share = 1.0
seniority = 2.0
board_approval_date = None
stockholder_approval_date = None
par_value = None
price_per_share = None
liquidation_preference_multiple = None
participation_cap_multiple = None
conversion_rights = validStockClassRights
comments = []]
creates =
[ CT.OcfCreateStockClass (defaultStockClass "SC_COMMON")
, CT.OcfCreateStockClass (StockClassOcfData with
id = "SC_PREFERRED_ALL_CONVERSION_MECHANISMS"
name = "Preferred All Conversion Mechanisms"
class_type = OcfStockClassTypePreferred
default_id_prefix = "PAM-"
initial_shares_authorized = OcfInitialSharesNumeric 1_000_000.0
votes_per_share = 1.0
seniority = 2.0
board_approval_date = None
stockholder_approval_date = None
par_value = None
price_per_share = None
liquidation_preference_multiple = None
participation_cap_multiple = None
conversion_rights = validStockClassRights
comments = [])
]
edits = []
deletes = []
result2 <- submit issuer do
Expand Down Expand Up @@ -460,22 +463,25 @@ testConversionMechanismRights_InvalidVariantsReject = script do
capTableCid <- addDefaultStakeholder issuer cap_table
stockControl <- submit issuer do
exerciseCmd capTableCid CT.UpdateCapTable with
creates = [CT.OcfCreateStockClass StockClassOcfData with
id = "SC_VALID_CONVERSION_MECHANISM_CONTROL"
name = "Valid Conversion Mechanism Control"
class_type = OcfStockClassTypePreferred
default_id_prefix = "VCM-"
initial_shares_authorized = OcfInitialSharesNumeric 1_000_000.0
votes_per_share = 1.0
seniority = 2.0
board_approval_date = None
stockholder_approval_date = None
par_value = None
price_per_share = None
liquidation_preference_multiple = None
participation_cap_multiple = None
conversion_rights = [stockClassRightWith OcfConversionMechanismRatioConversion None None (Some validRatio) None None None None None]
comments = []]
creates =
[ CT.OcfCreateStockClass (defaultStockClass "SC_COMMON")
, CT.OcfCreateStockClass (StockClassOcfData with
id = "SC_VALID_CONVERSION_MECHANISM_CONTROL"
name = "Valid Conversion Mechanism Control"
class_type = OcfStockClassTypePreferred
default_id_prefix = "VCM-"
initial_shares_authorized = OcfInitialSharesNumeric 1_000_000.0
votes_per_share = 1.0
seniority = 2.0
board_approval_date = None
stockholder_approval_date = None
par_value = None
price_per_share = None
liquidation_preference_multiple = None
participation_cap_multiple = None
conversion_rights = [stockClassRightWith OcfConversionMechanismRatioConversion None None (Some validRatio) None None None None None]
comments = [])
]
edits = []
deletes = []
submitMustFail issuer do
Expand Down
107 changes: 107 additions & 0 deletions Test/daml/OpenCapTable/TestConvertibleConversionRightReferences.daml
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
module OpenCapTable.TestConvertibleConversionRightReferences where

import Fairmint.OpenCapTable.OCF.ConvertibleIssuance
import Fairmint.OpenCapTable.Types.Conversion
import Fairmint.OpenCapTable.Types.Monetary
import qualified Fairmint.OpenCapTable.CapTable as CT
import OpenCapTable.Setup
import OpenCapTable.TestHelpers
import Daml.Script

convertibleConversionTriggerTo : Optional Text -> OcfConvertibleConversionTrigger
convertibleConversionTriggerTo stockClassId = OcfConvertibleConversionTrigger with
conversion_right = OcfConvertibleConversionRight with
conversion_mechanism = OcfConvMechSAFE (OcfSAFEConversionMechanism with
capitalization_definition = None
capitalization_definition_rules = None
conversion_discount = Some 0.2
conversion_mfn = False
conversion_timing = None
conversion_valuation_cap = None
exit_multiple = None)
converts_to_future_round = None
converts_to_stock_class_id = stockClassId
type_ = "CONVERTIBLE_CONVERSION_RIGHT"
end_date = None
nickname = None
start_date = None
trigger_condition = None
trigger_date = None
trigger_description = None
trigger_id = "TRIGGER-1"
type_ = OcfTriggerTypeTypeUnspecified

convertibleIssuanceWithConversionTarget : Text -> Text -> Optional Text -> ConvertibleIssuanceOcfData
convertibleIssuanceWithConversionTarget issuanceId securityId stockClassId = ConvertibleIssuanceOcfData with
id = issuanceId
date = defaultTestDate
security_id = securityId
custom_id = "CN-" <> issuanceId
stakeholder_id = defaultStakeholderId
board_approval_date = None
stockholder_approval_date = None
consideration_text = None
security_law_exemptions = []
investment_amount = OcfMonetary with amount = 100_000.0, currency = "USD"
convertible_type = OcfConvertibleSafe
conversion_triggers = [convertibleConversionTriggerTo stockClassId]
pro_rata = None
seniority = 1
comments = []

testConvertibleConversionRightTargetCreatedInSameBatchSucceeds = script do
TestOcp{issuer, cap_table} <- setupTestOcp
capTableWithStakeholder <- addDefaultStakeholder issuer cap_table

_ <- submit issuer do
exerciseCmd capTableWithStakeholder CT.UpdateCapTable with
creates =
[ CT.OcfCreateStockClass (defaultStockClass "SC_CONVERTIBLE_TARGET")
, CT.OcfCreateConvertibleIssuance (convertibleIssuanceWithConversionTarget "TX_CONVERTIBLE_TARGET_REF" "CONV-TARGET-REF" (Some "SC_CONVERTIBLE_TARGET"))
]
edits = []
deletes = []
pure ()

testConvertibleConversionRightMissingTargetFails = script do
TestOcp{issuer, cap_table} <- setupTestOcp
capTableWithStakeholder <- addDefaultStakeholder issuer cap_table

submitMustFail issuer do
exerciseCmd capTableWithStakeholder CT.UpdateCapTable with
creates = [CT.OcfCreateConvertibleIssuance (convertibleIssuanceWithConversionTarget "TX_CONVERTIBLE_MISSING_TARGET" "CONV-MISSING-TARGET" (Some "SC_MISSING_CONVERTIBLE_TARGET"))]
edits = []
deletes = []

testConvertibleConversionRightEditMissingTargetFails = script do
TestOcp{issuer, cap_table} <- setupTestOcp
capTableWithStakeholder <- addDefaultStakeholder issuer cap_table
result <- submit issuer do
exerciseCmd capTableWithStakeholder CT.UpdateCapTable with
creates = [CT.OcfCreateConvertibleIssuance (convertibleIssuanceWithConversionTarget "TX_CONVERTIBLE_EDIT_TARGET" "CONV-EDIT-TARGET" None)]
edits = []
deletes = []

submitMustFail issuer do
exerciseCmd result.updatedCapTableCid CT.UpdateCapTable with
creates = []
edits = [CT.OcfEditConvertibleIssuance (convertibleIssuanceWithConversionTarget "TX_CONVERTIBLE_EDIT_TARGET" "CONV-EDIT-TARGET" (Some "SC_MISSING_CONVERTIBLE_EDIT_TARGET"))]
deletes = []
Comment on lines +76 to +89

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider adding a positive edit-success test.

Only the failure path for editing a conversion target is covered (testConvertibleConversionRightEditMissingTargetFails). There's no test confirming that editing a convertible issuance's converts_to_stock_class_id to a valid existing stock class succeeds, which is the complementary happy-path for the edit validation wired into processEdit.

🧪 Example addition
testConvertibleConversionRightEditValidTargetSucceeds = script do
  TestOcp{issuer, cap_table} <- setupTestOcp
  capTableWithStakeholder <- addDefaultStakeholder issuer cap_table
  result <- submit issuer do
    exerciseCmd capTableWithStakeholder CT.UpdateCapTable with
      creates =
        [ CT.OcfCreateStockClass (defaultStockClass "SC_CONVERTIBLE_EDIT_VALID_TARGET")
        , CT.OcfCreateConvertibleIssuance (convertibleIssuanceWithConversionTarget "TX_CONVERTIBLE_EDIT_VALID" "CONV-EDIT-VALID" None)
        ]
      edits = []
      deletes = []

  _ <- submit issuer do
    exerciseCmd result.updatedCapTableCid CT.UpdateCapTable with
      creates = []
      edits = [CT.OcfEditConvertibleIssuance (convertibleIssuanceWithConversionTarget "TX_CONVERTIBLE_EDIT_VALID" "CONV-EDIT-VALID" (Some "SC_CONVERTIBLE_EDIT_VALID_TARGET"))]
      deletes = []
  pure ()
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Test/daml/OpenCapTable/TestConvertibleConversionRightReferences.daml` around
lines 76 - 89, Add a happy-path test alongside
testConvertibleConversionRightEditMissingTargetFails to verify processEdit
accepts a valid conversion target. In
TestConvertibleConversionRightReferences.daml, create a stock class and a
convertible issuance with convertibleIssuanceWithConversionTarget, then submit
an OcfEditConvertibleIssuance that sets converts_to_stock_class_id to the
existing stock class and assert the update succeeds. Use the existing helper
names (testConvertibleConversionRightEditMissingTargetFails, processEdit,
convertibleIssuanceWithConversionTarget) to keep the new test aligned with the
current validation coverage.


testConvertibleConversionRightTargetDeleteCannotLeaveDanglingReference = script do
TestOcp{issuer, cap_table} <- setupTestOcp
capTableWithStakeholder <- addDefaultStakeholder issuer cap_table
result <- submit issuer do
exerciseCmd capTableWithStakeholder CT.UpdateCapTable with
creates =
[ CT.OcfCreateStockClass (defaultStockClass "SC_CONVERTIBLE_DELETE_TARGET")
, CT.OcfCreateConvertibleIssuance (convertibleIssuanceWithConversionTarget "TX_CONVERTIBLE_DANGLING_TARGET" "CONV-DANGLING-TARGET" (Some "SC_CONVERTIBLE_DELETE_TARGET"))
]
edits = []
deletes = []

submitMustFail issuer do
exerciseCmd result.updatedCapTableCid CT.UpdateCapTable with
creates = []
edits = []
deletes = [CT.OcfDeleteStockClass "SC_CONVERTIBLE_DELETE_TARGET"]
74 changes: 73 additions & 1 deletion Test/daml/OpenCapTable/TestDocument.daml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,18 @@ module OpenCapTable.TestDocument where
import Fairmint.OpenCapTable.OCF.Document
import qualified Fairmint.OpenCapTable.CapTable as CT
import OpenCapTable.Setup
import OpenCapTable.TestHelpers
import Daml.Script

documentData : Text -> [OcfObjectReference] -> DocumentOcfData
documentData documentId relatedObjects = DocumentOcfData with
id = documentId
path = Some ("/docs/" <> documentId <> ".pdf")
uri = None
md5 = "0123456789abcdef0123456789abcdef"
related_objects = relatedObjects
comments = []

testCreateDocument = script do
TestOcp{system_operator, issuer, ctx, cap_table} <- setupTestOcp
-- Add document to CapTable via batch
Expand Down Expand Up @@ -52,7 +62,7 @@ testCreateDocumentWithOptionalsSome = script do
path = None
uri = Some "https://cdn.example.com/docs/acme/charter.pdf"
md5 = "0123456789abcdef0123456789abcdef"
related_objects = [ OcfObjectReference with object_type = OcfObjIssuer, object_id = "ISS_FOR_DOC" ]
related_objects = [ OcfObjectReference with object_type = OcfObjIssuer, object_id = "ISSUER_1" ]
comments = ["External link"]]
edits = []
deletes = []
Expand Down Expand Up @@ -85,3 +95,65 @@ testEditDocument = script do
comments = ["Updated version"]]
deletes = []
pure ()

testDocumentRelatedIssuerReferenceMustExist = script do
TestOcp{issuer, cap_table} <- setupTestOcp

submitMustFail issuer do
exerciseCmd cap_table CT.UpdateCapTable with
creates = [CT.OcfCreateDocument (documentData "DOC_BAD_ISSUER_REF" [OcfObjectReference with object_type = OcfObjIssuer, object_id = "ISSUER_MISSING"])]
edits = []
deletes = []

testDocumentRelatedObjectCreatedInSameBatchSucceeds = script do
TestOcp{issuer, cap_table} <- setupTestOcp

_ <- submit issuer do
exerciseCmd cap_table CT.UpdateCapTable with
creates =
[ CT.OcfCreateDocument (documentData "DOC_STOCK_CLASS_REF" [OcfObjectReference with object_type = OcfObjStockClass, object_id = "SC_DOC_REF"])
, CT.OcfCreateStockClass (defaultStockClass "SC_DOC_REF")
]
edits = []
deletes = []
pure ()

testDocumentPlanSecurityAliasReferencesEquityCompensationIssuance = script do
TestOcp{issuer, cap_table} <- setupTestOcp
(capTableWithStakeholder, stakeholderId) <- setupStakeholderWithId issuer cap_table "SH_DOC_PLAN_SECURITY" "Plan Security Holder"
capTableWithIssuance <- addEquityCompensationIssuance issuer capTableWithStakeholder "EC_DOC_PLAN_SECURITY" "SEC_DOC_PLAN_SECURITY" stakeholderId

_ <- submit issuer do
exerciseCmd capTableWithIssuance CT.UpdateCapTable with
creates =
[ CT.OcfCreateDocument
(documentData
"DOC_PLAN_SECURITY_REF"
[OcfObjectReference with object_type = OcfObjTxPlanSecurityIssuance, object_id = "EC_DOC_PLAN_SECURITY"])
]
edits = []
deletes = []
pure ()

testDocumentEditMissingRelatedObjectFails = script do
TestOcp{issuer, cap_table} <- setupTestOcp
result <- submit issuer do
exerciseCmd cap_table CT.UpdateCapTable with
creates = [CT.OcfCreateDocument (documentData "DOC_EDIT_REF" [])]
edits = []
deletes = []

submitMustFail issuer do
exerciseCmd result.updatedCapTableCid CT.UpdateCapTable with
creates = []
edits = [CT.OcfEditDocument (documentData "DOC_EDIT_REF" [OcfObjectReference with object_type = OcfObjStockClass, object_id = "SC_MISSING_FOR_DOC"])]
deletes = []

testDocumentUnsupportedRelatedObjectTypeFails = script do
TestOcp{issuer, cap_table} <- setupTestOcp

submitMustFail issuer do
exerciseCmd cap_table CT.UpdateCapTable with
creates = [CT.OcfCreateDocument (documentData "DOC_UNSUPPORTED_REF" [OcfObjectReference with object_type = OcfObjFinancing, object_id = "FINANCING_1"])]
edits = []
deletes = []
4 changes: 2 additions & 2 deletions Test/daml/OpenCapTable/TestEquityCompensationAcceptance.daml
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ createEquityCompensationIssuance issuer capTableCid =
stockholder_approval_date = None
consideration_text = Some "Services rendered"
security_law_exemptions = []
stock_plan_id = Some "SP_2024"
stock_class_id = Some "SC_COMMON"
stock_plan_id = None
stock_class_id = None
compensation_type = OcfCompensationTypeOptionISO
quantity = 10000.0
exercise_price = Some (OcfMonetary with amount = 0.50, currency = "USD")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ createEquityCompensationIssuance issuer capTableCid securityId quantity =
stockholder_approval_date = None
consideration_text = None
security_law_exemptions = []
stock_plan_id = Some "PLAN-2020"
stock_class_id = Some "COMMON"
stock_plan_id = None
stock_class_id = None
compensation_type = OcfCompensationTypeOptionNSO
quantity = quantity
exercise_price = Some (OcfMonetary with amount = 0.10, currency = "USD")
Expand Down
Loading
Loading