diff --git a/package.json b/package.json index e9c3e811..5cbf5c43 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,7 @@ "prettier": "^2.7.1", "solhint": "^3.4.1", "typescript": "~5.8.2", - "ts-jest": "^29.4.6", + "ts-jest": "^29.4.0", "uuid": "^9.0.0" }, "main": "jest.config.js", diff --git a/src/db/objects/Factory.js b/src/db/objects/Factory.js index ea080390..8d45c026 100644 --- a/src/db/objects/Factory.js +++ b/src/db/objects/Factory.js @@ -6,6 +6,12 @@ export const FACTORY_VERSION = { LEGACY: "LEGACY", }; +const CHAIN_ID = { + BASE_MAINNET: "8453", + BASE_SEPOLIA: "84532", + ANVIL: "31337", +}; + const FactorySchema = new mongoose.Schema( { _id: { type: String, default: () => uuid() }, @@ -15,21 +21,13 @@ const FactorySchema = new mongoose.Schema( chain_id: { type: String, required: true, - enum: [ - "8453", // Base mainnet - "84532", // Base Sepolia - "31337", // anvil - ], + enum: Object.values(CHAIN_ID), }, version: { type: String, required: true, enum: Object.values(FACTORY_VERSION), }, - notes: { - type: String, - default: "", - }, }, { timestamps: true } ); diff --git a/src/db/objects/HistoricalTransaction.js b/src/db/objects/HistoricalTransaction.js deleted file mode 100644 index ebf7a66d..00000000 --- a/src/db/objects/HistoricalTransaction.js +++ /dev/null @@ -1,43 +0,0 @@ -import mongoose from "mongoose"; - -const HistoricalTransactionSchema = new mongoose.Schema( - { - transaction: { - type: String, - refPath: "transactionType", // This will use the value of transactionType as the model name for population - }, - transactionType: { - type: String, - enum: [ - "StockIssuance", - "StockTransfer", - "StockCancellation", - "StockRetraction", - "StockReissuance", - "StockRepurchase", - "StockAcceptance", - "IssuerAuthorizedSharesAdjustment", - "StockClassAuthorizedSharesAdjustment", - "StockPlanPoolAdjustment", - "EquityCompensationIssuance", - "EquityCompensationExercise", - "ConvertibleIssuance", - "WarrantIssuance", - ], // List of possible models - required: true, - }, - hash: { - type: String, - required: true, - }, - issuer: { - type: String, - ref: "Issuer", - }, - }, - { timestamps: true } -); - -const HistoricalTransaction = mongoose.model("HistoricalTransaction", HistoricalTransactionSchema); - -export default HistoricalTransaction; diff --git a/src/db/operations/create.js b/src/db/operations/create.js index fc1bbfce..f300c50c 100644 --- a/src/db/operations/create.js +++ b/src/db/operations/create.js @@ -1,5 +1,4 @@ import Factory from "../objects/Factory.js"; -import HistoricalTransaction from "../objects/HistoricalTransaction.js"; import Issuer from "../objects/Issuer.js"; import Stakeholder from "../objects/Stakeholder.js"; import StockClass from "../objects/StockClass.js"; @@ -18,6 +17,7 @@ import EquityCompensationExercise from "../objects/transactions/exercise/EquityC import StockPlanPoolAdjustment from "../objects/transactions/adjustment/StockPlanPoolAdjustment.js"; import StockClassAuthorizedSharesAdjustment from "../objects/transactions/adjustment/StockClassAuthorizedSharesAdjustment.js"; import IssuerAuthorizedSharesAdjustment from "../objects/transactions/adjustment/IssuerAuthorizedSharesAdjustment.js"; +import StockCancellation from "../objects/transactions/cancellation/StockCancellation.js"; export const createIssuer = (issuerData) => { return save(new Issuer(issuerData)); @@ -47,10 +47,6 @@ export const createVestingTerms = (vestingTermsData) => { return save(new VestingTerms(vestingTermsData)); }; -export const createHistoricalTransaction = (transactionHistoryData) => { - return save(new HistoricalTransaction(transactionHistoryData)); -}; - export const createStockIssuance = (stockIssuanceData) => { return save(new StockIssuance(stockIssuanceData)); }; @@ -83,6 +79,10 @@ export const createEquityCompensationExercise = (exerciseData) => { return save(new EquityCompensationExercise(exerciseData)); }; +export const createStockCancellation = (stockCancellationData) => { + return save(new StockCancellation(stockCancellationData)); +}; + export const createStockPlanPoolAdjustment = (stockPlanPoolAdjustmentData) => { return save(new StockPlanPoolAdjustment(stockPlanPoolAdjustmentData)); }; diff --git a/src/db/operations/read.js b/src/db/operations/read.js index fe3141f2..6bef405e 100644 --- a/src/db/operations/read.js +++ b/src/db/operations/read.js @@ -1,5 +1,4 @@ import Factory from "../objects/Factory.js"; -import HistoricalTransaction from "../objects/HistoricalTransaction.js"; import Issuer from "../objects/Issuer.js"; import Stakeholder from "../objects/Stakeholder.js"; import StockClass from "../objects/StockClass.js"; @@ -47,16 +46,6 @@ export const readVestingTermsById = async (id) => { return await findById(VestingTerms, id); }; -export const readHistoricalTransactionById = async (txId) => { - return await findOne(HistoricalTransaction, { transaction: txId }); -}; - -// READ Multiple -export const readHistoricalTransactionByIssuerId = async (issuerId) => { - return await find(HistoricalTransaction, { issuer: issuerId }).populate("transaction"); -}; - -// COUNT export const countIssuers = async () => { return await countDocuments(Issuer); }; diff --git a/src/routes/export.js b/src/routes/export.js index d782414e..cc07258d 100644 --- a/src/routes/export.js +++ b/src/routes/export.js @@ -6,7 +6,6 @@ import StockLegendTemplate from "../db/objects/StockLegendTemplate"; import StockPlan from "../db/objects/StockPlan"; import Valuation from "../db/objects/Valuation"; import VestingTerm from "../db/objects/VestingTerms"; -import HistoricalTransaction from "../db/objects/HistoricalTransaction"; import { find } from "../db/operations/atomic"; const exportCaptable = Router(); @@ -26,7 +25,6 @@ exportCaptable.get("/ocf", async (req, res) => { const stockLegendTemplates = await find(StockLegendTemplate, { issuer: issuerId }); const valuations = await find(Valuation, { issuer: issuerId }); const vestingTerms = await find(VestingTerm, { issuer: issuerId }); - const historicalTransactions = await find(HistoricalTransaction, { issuer: issuerId }); res.status(200).json({ issuer, @@ -36,7 +34,6 @@ exportCaptable.get("/ocf", async (req, res) => { stockLegendTemplates, valuations, vestingTerms, - historicalTransactions, }); } catch (error) { console.error("Error fetching data:", error); diff --git a/src/routes/issuer.js b/src/routes/issuer.js index 8f2de78e..af334f79 100644 --- a/src/routes/issuer.js +++ b/src/routes/issuer.js @@ -62,17 +62,17 @@ issuer.post("/create", async (req, res) => { const issuerIdBytes16 = convertUUIDToBytes16(incomingIssuerToValidate.id); console.log("💾 | Issuer id in bytes16 ", issuerIdBytes16); - const { address, deployHash } = await deployCapTable(issuerIdBytes16, incomingIssuerToValidate.initial_shares_authorized, Number(chain_id)); + const { address, deployHash } = await deployCapTable(issuerIdBytes16, incomingIssuerToValidate.initial_shares_authorized, chain_id); const incomingIssuerForDB = { ...incomingIssuerToValidate, deployed_to: address, tx_hash: deployHash, - chain_id: Number(chain_id), + chain_id, }; const issuer = await createIssuer(incomingIssuerForDB); - addAddressesToWatch(Number(chain_id), address); + addAddressesToWatch(chain_id, address); console.log("✅ | Issuer created offchain:", issuer); diff --git a/src/routes/stakeholder/base.js b/src/routes/stakeholder/base.js index 00cf9b85..6a643b2b 100644 --- a/src/routes/stakeholder/base.js +++ b/src/routes/stakeholder/base.js @@ -11,6 +11,7 @@ import stakeholderSchema from "../../../ocf/schema/objects/Stakeholder.schema.js import { createStakeholder } from "../../db/operations/create.js"; import { readIssuerById, readStakeholderById, getAllStakeholdersByIssuerId } from "../../db/operations/read.js"; import validateInputAgainstOCF from "../../utils/validateInputAgainstSchema.js"; +import Stakeholder from "../../db/objects/Stakeholder.js"; const router = Router(); @@ -111,11 +112,12 @@ router.post("/create", async (req, res) => { const stakeholder = await createStakeholder(incomingStakeholderForDB); // Save onchain - await convertAndReflectStakeholderOnchain(contract, incomingStakeholderForDB.id); + const receipt = await convertAndReflectStakeholderOnchain(contract, incomingStakeholderForDB.id); + await Stakeholder.findByIdAndUpdate(stakeholder._id, { tx_hash: receipt.hash }); console.log("✅ | Stakeholder created offchain:", stakeholder); - res.status(200).send({ stakeholder }); + res.status(200).send({ stakeholder: { ...stakeholder.toObject(), tx_hash: receipt.hash } }); } catch (error) { console.error(error); res.status(500).send(`${error}`); diff --git a/src/routes/stockClass.js b/src/routes/stockClass.js index 65a6996f..eb35f318 100644 --- a/src/routes/stockClass.js +++ b/src/routes/stockClass.js @@ -5,6 +5,7 @@ import { convertAndReflectStockClassOnchain, getStockClassById, getTotalNumberOf import { createStockClass } from "../db/operations/create.js"; import { readIssuerById, readStockClassById } from "../db/operations/read.js"; import validateInputAgainstOCF from "../utils/validateInputAgainstSchema.js"; +import StockClass from "../db/objects/StockClass"; const stockClass = Router(); @@ -67,11 +68,12 @@ stockClass.post("/create", async (req, res) => { const stockClass = await createStockClass(incomingStockClassForDB); // Save Onchain - await convertAndReflectStockClassOnchain(contract, incomingStockClassForDB); + const receipt = await convertAndReflectStockClassOnchain(contract, incomingStockClassForDB); + await StockClass.findByIdAndUpdate(stockClass._id, { tx_hash: receipt.hash }); console.log("✅ | Stock Class created offchain:", stockClass); - res.status(200).send({ stockClass }); + res.status(200).send({ stockClass: { ...stockClass.toObject(), tx_hash: receipt.hash } }); } catch (error) { console.error(error); res.status(500).send(`${error}`); diff --git a/src/routes/transactions/base.js b/src/routes/transactions/base.js index 8bba894f..ec439ae0 100644 --- a/src/routes/transactions/base.js +++ b/src/routes/transactions/base.js @@ -37,6 +37,7 @@ import { createStockIssuance, createStockClassAuthorizedSharesAdjustment, createIssuerAuthorizedSharesAdjustment, + createStockCancellation, } from "../../db/operations/create.js"; import { @@ -54,6 +55,14 @@ import validateInputAgainstOCF from "../../utils/validateInputAgainstSchema.js"; import get from "lodash/get"; import { convertAndCreateEquityCompensationExerciseOnchain } from "../../controllers/transactions/exerciseController"; import { adjustStockPlanPoolOnchain } from "../../controllers/stockPlanController"; +import StockIssuance from "../../db/objects/transactions/issuance/StockIssuance.js"; +import ConvertibleIssuance from "../../db/objects/transactions/issuance/ConvertibleIssuance.js"; +import EquityCompensationIssuance from "../../db/objects/transactions/issuance/EquityCompensationIssuance.js"; +import WarrantIssuance from "../../db/objects/transactions/issuance/WarrantIssuance.js"; +import StockClassAuthorizedSharesAdjustment from "../../db/objects/transactions/adjustment/StockClassAuthorizedSharesAdjustment.js"; +import StockPlanPoolAdjustment from "../../db/objects/transactions/adjustment/StockPlanPoolAdjustment.js"; +import { EquityCompensationExercise } from "../../db/objects/transactions/exercise"; +import { StockCancellation } from "../../db/objects/transactions/cancellation"; const transactions = Router(); @@ -82,7 +91,7 @@ transactions.post("/issuance/stock", async (req, res) => { const stockIssuance = await createStockIssuance({ ...incomingStockIssuance, issuer: issuerId }); - await convertAndCreateIssuanceStockOnchain(contract, { + const receipt = await convertAndCreateIssuanceStockOnchain(contract, { security_id: incomingStockIssuance.security_id, stock_class_id: incomingStockIssuance.stock_class_id, stakeholder_id: incomingStockIssuance.stakeholder_id, @@ -93,7 +102,10 @@ transactions.post("/issuance/stock", async (req, res) => { id: incomingStockIssuance.id, }); - res.status(200).send({ stockIssuance }); + // Update the stock issuance with tx_hash + await StockIssuance.findByIdAndUpdate(stockIssuance._id, { tx_hash: receipt.hash }); + + res.status(200).send({ stockIssuance: { ...stockIssuance.toObject(), tx_hash: receipt.hash } }); } catch (error) { console.error(error); res.status(500).send(`${error}`); @@ -110,8 +122,6 @@ transactions.post("/transfer/stock", async (req, res) => { // @dev: Transfer Validation is not possible through schema because it validates that the transfer has occurred,at this stage it has not yet. await convertAndCreateTransferStockOnchain(contract, data); - // TODO: store historical transaction - res.status(200).send("success"); } catch (error) { console.error(error); @@ -126,8 +136,6 @@ transactions.post("/cancel/stock", async (req, res) => { try { await readIssuerById(issuerId); - const { stakeholderId, stockClassId } = data; - console.log({ data }); const incomingStockCancellation = { id: uuid(), security_id: uuid(), @@ -135,20 +143,17 @@ transactions.post("/cancel/stock", async (req, res) => { object_type: "TX_STOCK_CANCELLATION", ...data, }; - delete incomingStockCancellation.stakeholderId; - delete incomingStockCancellation.stockClassId; // NOTE: schema validation does not include stakeholder, stockClassId, however these properties are needed on to be passed on chain await validateInputAgainstOCF(incomingStockCancellation, stockCancellationSchema); - await convertAndCreateCancellationStockOnchain(contract, { - ...incomingStockCancellation, - stakeholderId, - stockClassId, - }); + const stockCancellation = await createStockCancellation({ ...incomingStockCancellation, issuer: issuerId }); - res.status(200).send({ stockCancellation: incomingStockCancellation }); + const receipt = await convertAndCreateCancellationStockOnchain(contract, stockCancellation); + + await StockCancellation.findByIdAndUpdate(stockCancellation._id, { tx_hash: receipt.hash }); + res.status(200).send({ stockCancellation: { ...stockCancellation.toObject(), tx_hash: receipt.hash } }); } catch (error) { console.error(`error: ${error.stack}`); res.status(500).send(`${error}`); @@ -299,14 +304,14 @@ transactions.post("/adjust/issuer/authorized-shares", async (req, res) => { }; await validateInputAgainstOCF(issuerAuthorizedSharesAdj, issuerAuthorizedSharesAdjustmentSchema); - // TODO: store tranaction on db + historical transactions + const createdIssuerAdjustment = await createIssuerAuthorizedSharesAdjustment({ ...issuerAuthorizedSharesAdj, issuer: issuerId, }); const receipt = await convertAndAdjustIssuerAuthorizedSharesOnChain(contract, createdIssuerAdjustment); - res.status(200).send({ ...issuerAuthorizedSharesAdj, txhash: receipt.hash }); + res.status(200).send({ ...createdIssuerAdjustment.toObject(), txhash: receipt.hash }); } catch (error) { console.error(error); res.status(500).send(`${error}`); @@ -344,7 +349,10 @@ transactions.post("/adjust/stock-class/authorized-shares", async (req, res) => { const receipt = await convertAndAdjustStockClassAuthorizedSharesOnchain(contract, createdStockClassAdjustment); - res.status(200).send({ stockClassAdjustment: { ...stockClassAuthorizedSharesAdjustment, txhash: receipt.hash } }); + // Update the stock class adjustment with tx_hash + await StockClassAuthorizedSharesAdjustment.findByIdAndUpdate(createdStockClassAdjustment._id, { tx_hash: receipt.hash }); + + res.status(200).send({ stockClassAdjustment: { ...createdStockClassAdjustment.toObject(), tx_hash: receipt.hash } }); } catch (error) { console.error(`error: ${error.stack}`); res.status(500).send(`${error}`); @@ -375,14 +383,17 @@ transactions.post("/adjust/stock-plan-pool", async (req, res) => { return res.status(404).send({ error: "Stock plan not found on OCP" }); } - await createStockPlanPoolAdjustment({ + const createdStockPlanAdjustment = await createStockPlanPoolAdjustment({ ...stockPlanPoolAdjustment, issuer: issuerId, }); const receipt = await adjustStockPlanPoolOnchain(contract, stockPlanPoolAdjustment); - res.status(200).send({ stockPlanAdjustment: { ...stockPlanPoolAdjustment, txhash: receipt.hash } }); + // Update the stock plan pool adjustment with tx_hash + await StockPlanPoolAdjustment.findByIdAndUpdate(createdStockPlanAdjustment._id, { tx_hash: receipt.hash }); + + res.status(200).send({ stockPlanAdjustment: { ...createdStockPlanAdjustment.toObject(), tx_hash: receipt.hash } }); } catch (error) { console.error(`error: ${error.stack}`); res.status(500).send(`${error}`); @@ -404,13 +415,10 @@ transactions.post("/issuance/equity-compensation", async (req, res) => { object_type: "TX_EQUITY_COMPENSATION_ISSUANCE", ...data, }; - // Enforce data.stock_class_id and data.stock_plan_id are present + // Enforce data.stock_class_id is present if (!get(incomingEquityCompensationIssuance, "stock_class_id")) { return res.status(400).send({ error: "Stock class id is required" }); } - if (!get(incomingEquityCompensationIssuance, "stock_plan_id")) { - return res.status(400).send({ error: "Stock plan id is required" }); - } await validateInputAgainstOCF(incomingEquityCompensationIssuance, equityCompensationIssuanceSchema); @@ -436,24 +444,12 @@ transactions.post("/issuance/equity-compensation", async (req, res) => { // Save offchain const createdIssuance = await createEquityCompensationIssuance({ ...incomingEquityCompensationIssuance, issuer: issuerId }); - // Save onchain - await convertAndCreateIssuanceEquityCompensationOnchain(contract, { - security_id: incomingEquityCompensationIssuance.security_id, - stakeholder_id: incomingEquityCompensationIssuance.stakeholder_id, - stock_class_id: incomingEquityCompensationIssuance.stock_class_id, - stock_plan_id: incomingEquityCompensationIssuance.stock_plan_id, - quantity: incomingEquityCompensationIssuance.quantity, - compensation_type: incomingEquityCompensationIssuance.compensation_type, - exercise_price: incomingEquityCompensationIssuance.exercise_price, - base_price: incomingEquityCompensationIssuance.base_price, - expiration_date: incomingEquityCompensationIssuance.expiration_date, - custom_id: incomingEquityCompensationIssuance.custom_id || "", - id: incomingEquityCompensationIssuance.id, - }); + const receipt = await convertAndCreateIssuanceEquityCompensationOnchain(contract, createdIssuance); - // TODO: Store Historical Transactions + // Update the equity compensation issuance with tx_hash + await EquityCompensationIssuance.findByIdAndUpdate(createdIssuance._id, { tx_hash: receipt.hash }); - res.status(200).send({ equityCompensationIssuance: createdIssuance }); + res.status(200).send({ equityCompensationIssuance: { ...createdIssuance, tx_hash: receipt.hash } }); } catch (error) { console.error(error); res.status(500).send(`${error}`); @@ -494,16 +490,12 @@ transactions.post("/exercise/equity-compensation", async (req, res) => { const createdExercise = await createEquityCompensationExercise({ ...incomingEquityCompensationExercise, issuer: issuerId }); // Save onchain - await convertAndCreateEquityCompensationExerciseOnchain(contract, { - equity_comp_security_id: incomingEquityCompensationExercise.security_id, - resulting_stock_security_id: incomingEquityCompensationExercise.resulting_security_ids[0], - quantity: incomingEquityCompensationExercise.quantity, - id: incomingEquityCompensationExercise.id, - }); + const receipt = await convertAndCreateEquityCompensationExerciseOnchain(contract, incomingEquityCompensationExercise); - // TODO: Store Historical Transactions + // Update the equity compensation exercise with tx_hash + await EquityCompensationExercise.findByIdAndUpdate(createdExercise._id, { tx_hash: receipt.hash }); - res.status(200).send({ equityCompensationExercise: createdExercise }); + res.status(200).send({ equityCompensationExercise: { ...createdExercise.toObject(), tx_hash: receipt.hash } }); } catch (error) { console.error(error); res.status(500).send(`${error}`); @@ -526,10 +518,9 @@ transactions.post("/issuance/convertible", async (req, res) => { ...data, }; - console.log("incomingConvertibleIssuance", incomingConvertibleIssuance); await validateInputAgainstOCF(incomingConvertibleIssuance, convertibleIssuanceSchema); - // Check if convertible exists - updated to use securityId + // Check if convertible exists - TODO use id instead of securityId const convertibleExists = await readConvertibleIssuanceBySecurityId(incomingConvertibleIssuance.security_id); if (convertibleExists && convertibleExists._id) { return res.status(200).send({ @@ -538,15 +529,14 @@ transactions.post("/issuance/convertible", async (req, res) => { }); } - // save to DB - const createdIssuance = await createConvertibleIssuance({ ...incomingConvertibleIssuance, issuer: issuerId }); + const convertibleIssuance = await createConvertibleIssuance({ ...incomingConvertibleIssuance, issuer: issuerId }); - // Create convertible onchain - await convertAndCreateIssuanceConvertibleOnchain(contract, createdIssuance); + const receipt = await convertAndCreateIssuanceConvertibleOnchain(contract, convertibleIssuance); - // TODO: Store Historical Transactions + // Update the convertible issuance with tx_hash + await ConvertibleIssuance.findByIdAndUpdate(convertibleIssuance._id, { tx_hash: receipt.hash }); - res.status(200).send({ convertibleIssuance: createdIssuance }); + res.status(200).send({ convertibleIssuance: { ...convertibleIssuance.toObject(), tx_hash: receipt.hash } }); } catch (error) { console.error(error); res.status(500).send(`${error}`); @@ -581,22 +571,14 @@ transactions.post("/issuance/warrant", async (req, res) => { }); } - // Save Offchain - const createdIssuance = await createWarrantIssuance({ ...incomingWarrantIssuance, issuer: issuerId }); - - // Save Onchain - await convertAndCreateIssuanceWarrantOnchain(contract, { - security_id: incomingWarrantIssuance.security_id, - stakeholder_id: incomingWarrantIssuance.stakeholder_id, - quantity: incomingWarrantIssuance.quantity, - purchase_price: incomingWarrantIssuance.purchase_price, - custom_id: incomingWarrantIssuance.custom_id || "", - id: incomingWarrantIssuance.id, - }); + const warrantIssuance = await createWarrantIssuance({ ...incomingWarrantIssuance, issuer: issuerId }); + + const receipt = await convertAndCreateIssuanceWarrantOnchain(contract, warrantIssuance); - // TODO: Store Historical Transactions + // Update the warrant issuance with tx_hash + await WarrantIssuance.findByIdAndUpdate(warrantIssuance._id, { tx_hash: receipt.hash }); - res.status(200).send({ warrantIssuance: createdIssuance }); + res.status(200).send({ warrantIssuance: { ...warrantIssuance.toObject(), tx_hash: receipt.hash } }); } catch (error) { console.error(error); res.status(500).send(`${error}`); diff --git a/src/scripts/migrate.js b/src/scripts/migrate.js index b3c40cc5..05b7a858 100644 --- a/src/scripts/migrate.js +++ b/src/scripts/migrate.js @@ -1,13 +1,11 @@ import { Contract } from "ethers"; -import Factory from "../db/objects/Factory.js"; import { readIssuerById, getAllStateMachineObjectsById, readAllIssuers } from "../db/operations/read.js"; import { updateIssuerById } from "../db/operations/update.js"; -import { facetsABI } from "../utils/errorDecoder.js"; import deployCapTable, { getWallet } from "../chain-operations/deployCapTable.js"; import { convertUUIDToBytes16 } from "../utils/convertUUID.js"; import { convertAndReflectStockClassOnchain } from "../controllers/stockClassController.js"; import { convertAndReflectStakeholderOnchain } from "../controllers/stakeholderController.js"; -import { adjustStockPlanPoolOnchain, createStockPlanOnchain } from "../controllers/stockPlanController.js"; +import { createStockPlanOnchain, adjustStockPlanPoolOnchain } from "../controllers/stockPlanController.js"; import { convertAndAdjustIssuerAuthorizedSharesOnChain } from "../controllers/issuerController.js"; import { convertAndAdjustStockClassAuthorizedSharesOnchain } from "../controllers/stockClassController.js"; import { @@ -24,14 +22,16 @@ import fs from "fs"; import path from "path"; import chalk from "chalk"; import readline from "readline"; -import { addAddressesToWatch, removeAllListeners } from "../utils/websocket.ts"; +import { addAddressesToWatch, reamoveAllListeners } from "../utils/websocket.ts"; import { validateIssuerForMigration } from "./validate.js"; +import { facetsABI } from "../utils/errorDecoder.js"; import { convertAndCreateCancellationStockOnchain } from "../controllers/transactions/cancellationController.js"; // Load environment variables dotenv.config(); -const ISSUERS_TO_SKIP = ["96887358-568d-44f8-b6d0-73c4f38558f6", "d5cffdf6-790c-477b-bce9-67831e5d834e", "15f5ac1e-2311-4716-abe8-3b943bca8d49"]; +const ISSUERS_TO_SKIP = []; +const ISSUERS_TO_MIGRATE = []; const rl = readline.createInterface({ input: process.stdin, @@ -154,7 +154,7 @@ async function migrateIssuer(issuerId, gasTracker = { gasUsed: BigInt(0), transa console.log({ issuerId, address: migrationLog.address, chainId: issuer.chain_id }); const contract = new Contract(migrationLog.address, facetsABI, await getWallet(issuer.chain_id)); - addAddressesToWatch(Number(issuer.chain_id), migrationLog.address); + addAddressesToWatch(issuer.chain_id, migrationLog.address); // 5. Deploy Stock Classes console.log("\nDeploying Stock Classes..."); @@ -400,43 +400,24 @@ async function migrateIssuer(issuerId, gasTracker = { gasUsed: BigInt(0), transa const MAX_RETRIES = 3; // Maximum number of retry attempts async function main() { - // Environment confirmation - console.log(chalk.blue.bold("\nCurrent Environment Configuration:")); - console.log(chalk.blue(`NODE_ENV: ${chalk.yellow(process.env.NODE_ENV || "not set")}`)); - console.log(chalk.blue(`USE_ENV_FILE: ${chalk.yellow(process.env.USE_ENV_FILE || "not set")}`)); - console.log(chalk.blue(`FACTORY_ADDRESS: ${chalk.yellow(process.env.FACTORY_ADDRESS || "not set")}`)); - - const envConfirmation = await askQuestion(`\nPlease confirm these environment settings are correct (y/n): `); - - if (envConfirmation.toLowerCase() !== "y") { - console.log(chalk.yellow("\nMigration aborted. Please set the correct environment variables and try again.")); - return; - } - const gasReport = createGasReport(); try { await connectDB(); - const FACTORY_ADDRESS = process.env.FACTORY_ADDRESS; - const factory = await Factory.findOne({ factory_address: FACTORY_ADDRESS }); - if (!factory) { - throw new Error("Factory not found"); - } - const skipIssuers = []; - const issuers = (await readAllIssuers()).filter((i) => !i?.factory).filter((i) => !skipIssuers.includes(i.legal_name)); - // .filter((i) => { - // // Check both database and log file status - // const logFile = path.join(process.cwd(), "migrations", `${i.legal_name}.log.json`); - // if (fs.existsSync(logFile)) { - // const log = JSON.parse(fs.readFileSync(logFile, "utf8")); - // return !i.migrated && !log.migrated; - // } - - // return !i.migrated; - // }); - issuers.forEach((i) => { - console.log(`${i.legal_name} - ${i.id}: Factory? ${!!i?.factory}`); - }); + + const issuers = (await readAllIssuers()) + .filter((i) => ISSUERS_TO_MIGRATE.includes(i._id)) + .filter((i) => { + // Check both database and log file status + const logFile = path.join(process.cwd(), "migrations", `${i.legal_name}.log.json`); + if (fs.existsSync(logFile)) { + const log = JSON.parse(fs.readFileSync(logFile, "utf8")); + return !i.migrated && !log.migrated; + } + + return !i.migrated; + }); + console.log(chalk.blue.bold(`Found ${issuers.length} issuers to migrate.\n`)); const initialAnswer = await askQuestion( @@ -533,7 +514,7 @@ async function main() { } finally { rl.close(); await mongoose.disconnect(); - await removeAllListeners(); + await reamoveAllListeners(); console.log(chalk.gray("\nExiting migration process...")); } } @@ -542,52 +523,32 @@ async function main() { // Allow script to be run from command line with a specific issuer ID or run all if (process.argv[2]) { const issuerId = process.argv[2]; - - // Environment confirmation - console.log(chalk.blue.bold("\nCurrent Environment Configuration:")); - console.log(chalk.blue(`NODE_ENV: ${chalk.yellow(process.env.NODE_ENV || "not set")}`)); - console.log(chalk.blue(`USE_ENV_FILE: ${chalk.yellow(process.env.USE_ENV_FILE || "not set")}`)); - - const rl = readline.createInterface({ - input: process.stdin, - output: process.stdout, - }); - - rl.question(chalk.cyan("\nPlease confirm these environment settings are correct (y/n): "), (answer) => { - if (answer.toLowerCase() !== "y") { - console.log(chalk.yellow("\nMigration aborted. Please set the correct environment variables and try again.")); - rl.close(); + migrateIssuer(issuerId) + .then((result) => { + if (result.success) { + console.log(chalk.green("Single issuer migration completed successfully")); + const reportPath = saveGasReport({ + totalGasUsed: result.gasTracker.gasUsed, + issuers: [ + { + name: result.issuerName, + gasUsed: result.gasTracker.gasUsed, + transactionCount: result.gasTracker.transactionCount, + }, + ], + startTime: new Date().toISOString(), + endTime: new Date().toISOString(), + }); + console.log(chalk.blue(`Gas report saved to: ${reportPath}`)); + } else { + throw result.error; + } process.exit(0); - } - rl.close(); - - migrateIssuer(issuerId) - .then((result) => { - if (result.success) { - console.log(chalk.green("Single issuer migration completed successfully")); - const reportPath = saveGasReport({ - totalGasUsed: result.gasTracker.gasUsed, - issuers: [ - { - name: result.issuerName, - gasUsed: result.gasTracker.gasUsed, - transactionCount: result.gasTracker.transactionCount, - }, - ], - startTime: new Date().toISOString(), - endTime: new Date().toISOString(), - }); - console.log(chalk.blue(`Gas report saved to: ${reportPath}`)); - } else { - throw result.error; - } - process.exit(0); - }) - .catch((error) => { - console.error(chalk.red("Migration failed:"), error); - process.exit(1); - }); - }); + }) + .catch((error) => { + console.error(chalk.red("Migration failed:"), error); + process.exit(1); + }); } else { // Run migration for all issuers main() diff --git a/src/tests/integration/utils.ts b/src/tests/integration/utils.ts index b877527c..bea21106 100644 --- a/src/tests/integration/utils.ts +++ b/src/tests/integration/utils.ts @@ -1,5 +1,4 @@ import { connectDB } from "../../db/config/mongoose"; -import HistoricalTransaction from "../../db/objects/HistoricalTransaction"; import Issuer from "../../db/objects/Issuer"; import Stakeholder from "../../db/objects/Stakeholder"; import StockClass from "../../db/objects/StockClass"; @@ -27,7 +26,6 @@ const deleteAll = async () => { await StockPlan.deleteMany({}); await Valuation.deleteMany({}); await VestingTerms.deleteMany({}); - await HistoricalTransaction.deleteMany({}); await deleteAllTransactions(); // Delete all transactions };