Skip to content

purchase notify update for negative values#9

Open
kaushalya4s5s7 wants to merge 3 commits into
Dead_Bytes/sync_minor_patchesfrom
KC/Borrow-update
Open

purchase notify update for negative values#9
kaushalya4s5s7 wants to merge 3 commits into
Dead_Bytes/sync_minor_patchesfrom
KC/Borrow-update

Conversation

@kaushalya4s5s7

Copy link
Copy Markdown
Collaborator

No description provided.

Copilot AI review requested due to automatic review settings January 11, 2026 10:37

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This pull request adds support for negative amounts in purchase notifications to track token deposits (balance decreases) to the contract. The changes allow the system to record both positive purchases and negative deposits in the same Purchase schema.

Changes:

  • Modified the DTO validation to accept negative number strings using a regex pattern
  • Added a 'type' field to the Purchase schema metadata to distinguish between 'PURCHASE' and 'DEPOSIT' records
  • Implemented deposit handling logic that bypasses on-chain validation and converts amounts to wei

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 10 comments.

File Description
packages/backend/src/modules/marketplace/dto/notify-purchase.dto.ts Updated validation to allow negative amounts using regex pattern instead of IsNumberString
packages/backend/src/database/schemas/purchase.schema.ts Added optional 'type' field to metadata to track PURCHASE vs DEPOSIT transactions
packages/backend/src/modules/marketplace/services/purchase-tracker.service.ts Implemented deposit handling with negative amounts, added early return path for deposits that skips on-chain validation

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +60 to +100
if (isDeposit) {
// Handle token deposit to contract (balance decrease)
this.logger.log(`Processing token deposit (balance decrease): ${dto.amount}`);

// Convert amount to wei (if not already in wei)
const amountWithoutSign = dto.amount.substring(1); // Remove negative sign
const depositAmountInWei = (BigInt(amountWithoutSign) * BigInt(10 ** 18)).toString();
const blockNumber = dto.blockNumber ? parseInt(dto.blockNumber) : 0;

// Record as a negative purchase to track balance decrease
const purchase = await this.purchaseModel.create({
txHash: dto.txHash,
assetId: dto.assetId,
investorWallet: investorWallet.toLowerCase(), // Store as negative in wei
tokenAddress: asset.token?.address || '',
amount: '-' + depositAmountInWei,
price: '0', // No price for deposits
totalPayment: '0', // No payment for deposits
blockNumber: blockNumber,
blockTimestamp: new Date(),
status: 'CONFIRMED',
metadata: {
assetName: `${asset.metadata?.invoiceNumber} - ${asset.metadata?.buyerName}`,
industry: asset.metadata?.industry,
riskTier: asset.metadata?.riskTier,
type: 'DEPOSIT', // Mark as deposit
},
});

this.logger.log(`Token deposit recorded: ${purchase._id}, amount in wei: -${depositAmountInWei}`);

return {
success: true,
purchaseId: purchase._id,
assetId: dto.assetId,
amount: '-' + depositAmountInWei,
totalPayment: '0',
tokenAddress: asset.token?.address,
type: 'DEPOSIT',
};
}

Copilot AI Jan 11, 2026

Copy link

Choose a reason for hiding this comment

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

The deposit functionality is not covered by any tests. Since this introduces a new critical code path that bypasses transaction validation and manipulates portfolio balances, comprehensive test coverage is essential to prevent regressions and ensure the deposit logic works correctly with both positive and negative amounts.

Copilot uses AI. Check for mistakes.
Comment on lines +58 to +65
const isDeposit = dto.amount.startsWith('-');

if (isDeposit) {
// Handle token deposit to contract (balance decrease)
this.logger.log(`Processing token deposit (balance decrease): ${dto.amount}`);

// Convert amount to wei (if not already in wei)
const amountWithoutSign = dto.amount.substring(1); // Remove negative sign

Copilot AI Jan 11, 2026

Copy link

Choose a reason for hiding this comment

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

Using startsWith('-') to detect deposits is fragile and could fail if the amount string has leading whitespace or uses a different representation. Consider using a more robust approach such as checking if the first non-whitespace character is '-' using trim(), or better yet, adding an explicit field in the DTO to indicate the transaction type.

Suggested change
const isDeposit = dto.amount.startsWith('-');
if (isDeposit) {
// Handle token deposit to contract (balance decrease)
this.logger.log(`Processing token deposit (balance decrease): ${dto.amount}`);
// Convert amount to wei (if not already in wei)
const amountWithoutSign = dto.amount.substring(1); // Remove negative sign
const normalizedAmount = dto.amount.trim();
const isDeposit = normalizedAmount.startsWith('-');
if (isDeposit) {
// Handle token deposit to contract (balance decrease)
this.logger.log(`Processing token deposit (balance decrease): ${dto.amount}`);
// Convert amount to wei (if not already in wei)
const amountWithoutSign = normalizedAmount.substring(1); // Remove negative sign

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@kaushalya4s5s7 this works but yes robustness is well appriciated dont think of a specific case u can solve while solving , think how many cases this code can pass, nothing can pass everycase but the more we support the more better

// Convert amount to wei (if not already in wei)
const amountWithoutSign = dto.amount.substring(1); // Remove negative sign
const depositAmountInWei = (BigInt(amountWithoutSign) * BigInt(10 ** 18)).toString();
const blockNumber = dto.blockNumber ? parseInt(dto.blockNumber) : 0;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Very right thing to do is to fetch the tx details just in case , use optional between frontend provided and blockchain provided

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@kaushalya4s5s7 please have a review

price: '0', // No price for deposits
totalPayment: '0', // No payment for deposits
blockNumber: blockNumber,
blockTimestamp: new Date(),

Copilot AI Jan 11, 2026

Copy link

Choose a reason for hiding this comment

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

For deposits, blockTimestamp is set to "new Date()" (current time) instead of the actual transaction timestamp. This is inconsistent with how purchases handle timestamps (line 123 uses the actual block timestamp). This inconsistency could cause issues with chronological ordering of transactions and inaccurate historical data analysis.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

again same thing if data can be fetched and presented then why not

Comment on lines +91 to +100
return {
success: true,
purchaseId: purchase._id,
assetId: dto.assetId,
amount: '-' + depositAmountInWei,
totalPayment: '0',
tokenAddress: asset.token?.address,
type: 'DEPOSIT',
};
}

Copilot AI Jan 11, 2026

Copy link

Choose a reason for hiding this comment

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

Unlike regular purchases which send a user notification (lines 167-181), deposits do not trigger any notification to the user. This inconsistency could leave users unaware of important balance changes in their portfolio, especially for negative deposits which decrease their holdings.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

exactly @kaushalya4s5s7 Deposit shall send a notif that asset from ur portfolio has been deposited it will give them a sense of assurance Use whats integrated best.

Comment on lines +60 to +100
if (isDeposit) {
// Handle token deposit to contract (balance decrease)
this.logger.log(`Processing token deposit (balance decrease): ${dto.amount}`);

// Convert amount to wei (if not already in wei)
const amountWithoutSign = dto.amount.substring(1); // Remove negative sign
const depositAmountInWei = (BigInt(amountWithoutSign) * BigInt(10 ** 18)).toString();
const blockNumber = dto.blockNumber ? parseInt(dto.blockNumber) : 0;

// Record as a negative purchase to track balance decrease
const purchase = await this.purchaseModel.create({
txHash: dto.txHash,
assetId: dto.assetId,
investorWallet: investorWallet.toLowerCase(), // Store as negative in wei
tokenAddress: asset.token?.address || '',
amount: '-' + depositAmountInWei,
price: '0', // No price for deposits
totalPayment: '0', // No payment for deposits
blockNumber: blockNumber,
blockTimestamp: new Date(),
status: 'CONFIRMED',
metadata: {
assetName: `${asset.metadata?.invoiceNumber} - ${asset.metadata?.buyerName}`,
industry: asset.metadata?.industry,
riskTier: asset.metadata?.riskTier,
type: 'DEPOSIT', // Mark as deposit
},
});

this.logger.log(`Token deposit recorded: ${purchase._id}, amount in wei: -${depositAmountInWei}`);

return {
success: true,
purchaseId: purchase._id,
assetId: dto.assetId,
amount: '-' + depositAmountInWei,
totalPayment: '0',
tokenAddress: asset.token?.address,
type: 'DEPOSIT',
};
}

Copilot AI Jan 11, 2026

Copy link

Choose a reason for hiding this comment

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

This change introduces negative amounts into the Purchase records, but other parts of the codebase that query and sum purchase.amount values are not updated to handle this. Specifically, asset-lifecycle.service.ts (lines 1128, 1132, 1278, 1299) and bid-tracker.service.ts (lines 557-564) sum purchase amounts without filtering out deposits. This will cause incorrect calculations for tokensSold and listing.sold. All queries that aggregate purchase amounts must be updated to either exclude deposits (filter by metadata.type != 'DEPOSIT') or handle negative values appropriately in the business logic.

Copilot uses AI. Check for mistakes.
Comment on lines +60 to +100
if (isDeposit) {
// Handle token deposit to contract (balance decrease)
this.logger.log(`Processing token deposit (balance decrease): ${dto.amount}`);

// Convert amount to wei (if not already in wei)
const amountWithoutSign = dto.amount.substring(1); // Remove negative sign
const depositAmountInWei = (BigInt(amountWithoutSign) * BigInt(10 ** 18)).toString();
const blockNumber = dto.blockNumber ? parseInt(dto.blockNumber) : 0;

// Record as a negative purchase to track balance decrease
const purchase = await this.purchaseModel.create({
txHash: dto.txHash,
assetId: dto.assetId,
investorWallet: investorWallet.toLowerCase(), // Store as negative in wei
tokenAddress: asset.token?.address || '',
amount: '-' + depositAmountInWei,
price: '0', // No price for deposits
totalPayment: '0', // No payment for deposits
blockNumber: blockNumber,
blockTimestamp: new Date(),
status: 'CONFIRMED',
metadata: {
assetName: `${asset.metadata?.invoiceNumber} - ${asset.metadata?.buyerName}`,
industry: asset.metadata?.industry,
riskTier: asset.metadata?.riskTier,
type: 'DEPOSIT', // Mark as deposit
},
});

this.logger.log(`Token deposit recorded: ${purchase._id}, amount in wei: -${depositAmountInWei}`);

return {
success: true,
purchaseId: purchase._id,
assetId: dto.assetId,
amount: '-' + depositAmountInWei,
totalPayment: '0',
tokenAddress: asset.token?.address,
type: 'DEPOSIT',
};
}

Copilot AI Jan 11, 2026

Copy link

Choose a reason for hiding this comment

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

The deposit flow bypasses on-chain transaction validation entirely. Unlike purchases which use validatePurchaseTransaction() to verify the transaction on-chain, deposits are recorded without any blockchain verification. This creates a security vulnerability where malicious actors could submit fake deposit transactions without actual on-chain events, potentially manipulating portfolio balances.

Copilot uses AI. Check for mistakes.
Comment on lines +73 to +75
investorWallet: investorWallet.toLowerCase(), // Store as negative in wei
tokenAddress: asset.token?.address || '',
amount: '-' + depositAmountInWei,

Copilot AI Jan 11, 2026

Copy link

Choose a reason for hiding this comment

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

The comment "Store as negative in wei" is placed next to the investorWallet field but appears to be intended for the amount field on line 75. This misleading comment could confuse future developers about what should be stored as negative.

Suggested change
investorWallet: investorWallet.toLowerCase(), // Store as negative in wei
tokenAddress: asset.token?.address || '',
amount: '-' + depositAmountInWei,
investorWallet: investorWallet.toLowerCase(),
tokenAddress: asset.token?.address || '',
amount: '-' + depositAmountInWei, // Store as negative in wei

Copilot uses AI. Check for mistakes.
// Convert amount to wei (if not already in wei)
const amountWithoutSign = dto.amount.substring(1); // Remove negative sign
const depositAmountInWei = (BigInt(amountWithoutSign) * BigInt(10 ** 18)).toString();
const blockNumber = dto.blockNumber ? parseInt(dto.blockNumber) : 0;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Very right thing to do is to fetch the tx details just in case , use optional between frontend provided and blockchain provided

@TheOpenAssets TheOpenAssets deleted a comment from Copilot AI Jan 11, 2026
@TheOpenAssets TheOpenAssets deleted a comment from Copilot AI Jan 11, 2026
@TheOpenAssets TheOpenAssets deleted a comment from Copilot AI Jan 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants