fix: cumulative fund claims — deposits accumulate until claimed
Instead of expiring old claims, new deposits add to the existing pending claim's fiat_amount and extend the expiry. The claim email shows the updated total. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
6c807afeb0
commit
f662881170
|
|
@ -1271,6 +1271,18 @@ export async function acceptFundClaim(token: string, userId: string): Promise<St
|
||||||
return rowToFundClaim(rows[0]);
|
return rowToFundClaim(rows[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function accumulateFundClaim(claimId: string, additionalAmount: string, expiresAt: number): Promise<StoredFundClaim | null> {
|
||||||
|
const rows = await sql`
|
||||||
|
UPDATE fund_claims
|
||||||
|
SET fiat_amount = (COALESCE(fiat_amount::numeric, 0) + ${additionalAmount}::numeric)::text,
|
||||||
|
expires_at = ${new Date(expiresAt)}
|
||||||
|
WHERE id = ${claimId} AND status IN ('pending', 'resent')
|
||||||
|
RETURNING *
|
||||||
|
`;
|
||||||
|
if (rows.length === 0) return null;
|
||||||
|
return rowToFundClaim(rows[0]);
|
||||||
|
}
|
||||||
|
|
||||||
export async function expireFundClaim(claimId: string): Promise<void> {
|
export async function expireFundClaim(claimId: string): Promise<void> {
|
||||||
await sql`UPDATE fund_claims SET status = 'expired', email = NULL WHERE id = ${claimId} AND status IN ('pending', 'resent')`;
|
await sql`UPDATE fund_claims SET status = 'expired', email = NULL WHERE id = ${claimId} AND status IN ('pending', 'resent')`;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ import {
|
||||||
getFundClaimByToken,
|
getFundClaimByToken,
|
||||||
getFundClaimsByEmailHash,
|
getFundClaimsByEmailHash,
|
||||||
acceptFundClaim,
|
acceptFundClaim,
|
||||||
expireFundClaim,
|
accumulateFundClaim,
|
||||||
cleanExpiredFundClaims,
|
cleanExpiredFundClaims,
|
||||||
sql,
|
sql,
|
||||||
} from './db.js';
|
} from './db.js';
|
||||||
|
|
@ -2926,17 +2926,30 @@ app.post('/api/internal/fund-claims', async (c) => {
|
||||||
return c.json({ error: 'email and walletAddress are required' }, 400);
|
return c.json({ error: 'email and walletAddress are required' }, 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
const id = crypto.randomUUID();
|
|
||||||
const token = generateToken();
|
|
||||||
const emailHashed = await hashEmail(email);
|
const emailHashed = await hashEmail(email);
|
||||||
const expiresAt = Date.now() + 7 * 24 * 60 * 60 * 1000; // 7 days
|
const expiresAt = Date.now() + 7 * 24 * 60 * 60 * 1000; // 7 days
|
||||||
|
|
||||||
// Expire any existing pending claims for this email (one active claim per user)
|
// Check for existing pending claim — accumulate deposits
|
||||||
const existingClaims = await getFundClaimsByEmailHash(emailHashed);
|
const existingClaims = await getFundClaimsByEmailHash(emailHashed);
|
||||||
for (const ec of existingClaims) {
|
if (existingClaims.length > 0 && fiatAmount) {
|
||||||
await expireFundClaim(ec.id);
|
const existing = existingClaims[0];
|
||||||
|
const updated = await accumulateFundClaim(existing.id, fiatAmount, expiresAt);
|
||||||
|
|
||||||
|
let sent = false;
|
||||||
|
try {
|
||||||
|
const totalAmount = updated?.fiatAmount || fiatAmount;
|
||||||
|
sent = await sendClaimEmail(email, existing.token, totalAmount, fiatCurrency || 'USD');
|
||||||
|
} catch (err) {
|
||||||
|
console.error('EncryptID: Failed to send claim email:', err);
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.json({ claimId: existing.id, accumulated: true, sent });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// No existing claim — create new
|
||||||
|
const id = crypto.randomUUID();
|
||||||
|
const token = generateToken();
|
||||||
|
|
||||||
const claim = await createFundClaim({
|
const claim = await createFundClaim({
|
||||||
id,
|
id,
|
||||||
token,
|
token,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue