fix(rcart): fix floating-point precision in wallet payment amounts
Replace parseFloat * 10^decimals with string-based decimal parsing to avoid precision loss for 18-decimal tokens (ETH). Affects both MetaMask and EncryptID payment paths. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
f5ac038803
commit
8345648d61
|
|
@ -216,7 +216,7 @@ class FolkPaymentPage extends HTMLElement {
|
|||
|
||||
if (p.token === 'ETH') {
|
||||
// Native ETH transfer
|
||||
const weiAmount = BigInt(Math.round(parseFloat(effectiveAmount) * 1e18));
|
||||
const weiAmount = this.parseTokenAmount(effectiveAmount, 18);
|
||||
txHash = await signer.sendTransaction({
|
||||
from: this.walletAccount,
|
||||
to: p.recipientAddress,
|
||||
|
|
@ -229,7 +229,7 @@ class FolkPaymentPage extends HTMLElement {
|
|||
if (!usdcAddress) throw new Error('USDC not supported on this chain');
|
||||
|
||||
const decimals = p.token === 'USDC' ? 6 : 18;
|
||||
const rawAmount = BigInt(Math.round(parseFloat(effectiveAmount) * (10 ** decimals)));
|
||||
const rawAmount = this.parseTokenAmount(effectiveAmount, decimals);
|
||||
|
||||
// transfer(address to, uint256 amount) — selector: 0xa9059cbb
|
||||
const recipient = p.recipientAddress.slice(2).toLowerCase().padStart(64, '0');
|
||||
|
|
@ -303,7 +303,7 @@ class FolkPaymentPage extends HTMLElement {
|
|||
txHash = await client.sendTransaction({
|
||||
account,
|
||||
to: p.recipientAddress as `0x${string}`,
|
||||
value: BigInt(Math.round(parseFloat(effectiveAmount) * 1e18)),
|
||||
value: this.parseTokenAmount(effectiveAmount, 18),
|
||||
chain,
|
||||
});
|
||||
} else {
|
||||
|
|
@ -312,7 +312,7 @@ class FolkPaymentPage extends HTMLElement {
|
|||
if (!usdcAddress) throw new Error('USDC not supported on this chain');
|
||||
|
||||
const decimals = p.token === 'USDC' ? 6 : 18;
|
||||
const rawAmount = BigInt(Math.round(parseFloat(effectiveAmount) * (10 ** decimals)));
|
||||
const rawAmount = this.parseTokenAmount(effectiveAmount, decimals);
|
||||
|
||||
const recipient = p.recipientAddress.slice(2).toLowerCase().padStart(64, '0');
|
||||
const amountHex = rawAmount.toString(16).padStart(64, '0');
|
||||
|
|
@ -347,6 +347,18 @@ class FolkPaymentPage extends HTMLElement {
|
|||
return this.customAmount || '0';
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a decimal amount string into a BigInt with the given decimals.
|
||||
* Avoids floating-point precision loss for 18-decimal tokens.
|
||||
* e.g. parseTokenAmount("1.5", 18) → 1500000000000000000n
|
||||
*/
|
||||
private parseTokenAmount(amount: string, decimals: number): bigint {
|
||||
const parts = amount.split('.');
|
||||
const whole = parts[0] || '0';
|
||||
let frac = (parts[1] || '').slice(0, decimals).padEnd(decimals, '0');
|
||||
return BigInt(whole) * BigInt(10 ** decimals) + BigInt(frac);
|
||||
}
|
||||
|
||||
// ── Status update ──
|
||||
|
||||
private async updatePaymentStatus(status: string, method: string, txHash?: string | null, transakOrderId?: string | null) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue