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') {
|
if (p.token === 'ETH') {
|
||||||
// Native ETH transfer
|
// Native ETH transfer
|
||||||
const weiAmount = BigInt(Math.round(parseFloat(effectiveAmount) * 1e18));
|
const weiAmount = this.parseTokenAmount(effectiveAmount, 18);
|
||||||
txHash = await signer.sendTransaction({
|
txHash = await signer.sendTransaction({
|
||||||
from: this.walletAccount,
|
from: this.walletAccount,
|
||||||
to: p.recipientAddress,
|
to: p.recipientAddress,
|
||||||
|
|
@ -229,7 +229,7 @@ class FolkPaymentPage extends HTMLElement {
|
||||||
if (!usdcAddress) throw new Error('USDC not supported on this chain');
|
if (!usdcAddress) throw new Error('USDC not supported on this chain');
|
||||||
|
|
||||||
const decimals = p.token === 'USDC' ? 6 : 18;
|
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
|
// transfer(address to, uint256 amount) — selector: 0xa9059cbb
|
||||||
const recipient = p.recipientAddress.slice(2).toLowerCase().padStart(64, '0');
|
const recipient = p.recipientAddress.slice(2).toLowerCase().padStart(64, '0');
|
||||||
|
|
@ -303,7 +303,7 @@ class FolkPaymentPage extends HTMLElement {
|
||||||
txHash = await client.sendTransaction({
|
txHash = await client.sendTransaction({
|
||||||
account,
|
account,
|
||||||
to: p.recipientAddress as `0x${string}`,
|
to: p.recipientAddress as `0x${string}`,
|
||||||
value: BigInt(Math.round(parseFloat(effectiveAmount) * 1e18)),
|
value: this.parseTokenAmount(effectiveAmount, 18),
|
||||||
chain,
|
chain,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -312,7 +312,7 @@ class FolkPaymentPage extends HTMLElement {
|
||||||
if (!usdcAddress) throw new Error('USDC not supported on this chain');
|
if (!usdcAddress) throw new Error('USDC not supported on this chain');
|
||||||
|
|
||||||
const decimals = p.token === 'USDC' ? 6 : 18;
|
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 recipient = p.recipientAddress.slice(2).toLowerCase().padStart(64, '0');
|
||||||
const amountHex = rawAmount.toString(16).padStart(64, '0');
|
const amountHex = rawAmount.toString(16).padStart(64, '0');
|
||||||
|
|
@ -347,6 +347,18 @@ class FolkPaymentPage extends HTMLElement {
|
||||||
return this.customAmount || '0';
|
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 ──
|
// ── Status update ──
|
||||||
|
|
||||||
private async updatePaymentStatus(status: string, method: string, txHash?: string | null, transakOrderId?: string | null) {
|
private async updatePaymentStatus(status: string, method: string, txHash?: string | null, transakOrderId?: string | null) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue