Skip to content

feat: add Amount class for type-safe monetary operations - #62

Merged
Gaubee merged 1 commit into
mainfrom
feat/amount-type
Dec 22, 2025
Merged

Gaubee merged 1 commit into
mainfrom
feat/amount-type

Conversation

@Gaubee

@Gaubee Gaubee commented Dec 22, 2025

Copy link
Copy Markdown
Contributor

问题

BigInt(asset.amount) 在 asset.amount 包含小数时抛出错误:

SyntaxError: Cannot convert 102531.02649070 to a BigInt

根本原因:没有清晰区分 raw(最小单位)和 formatted(带小数)值。

解决方案

添加 Amount 类,封装金额操作:

设计原则

  1. 不可变 - 所有操作返回新实例
  2. 类型安全 - 通过静态工厂方法创建,防止混淆
  3. 自文档化 - 方法名清晰表达意图
  4. 智能解析 - Amount.parse() 自动判断 raw/formatted

API

// 工厂方法
Amount.fromRaw('1000000000000000000', 18)      // 从原始值
Amount.fromFormatted('1.5', 18)                // 从用户输入
Amount.parse(asset.amount, asset.decimals)     // 智能解析
amountFromAsset(asset)                         // 从 AssetInfo

// 比较
amount.gt(other)   // >
amount.lt(other)   // <
amount.eq(other)   // ==
amount.gte(other)  // >=
amount.lte(other)  // <=

// 运算
amount.add(other)
amount.sub(other)
amount.mul(factor)
amount.div(divisor)

// 转换
amount.toRawString()   // '1000000000000000000'
amount.toFormatted()   // '1.5'
amount.toNumber()      // 1.5 (可能丢精度)
amount.toString()      // '1.5 ETH' (带符号)

变更

  • src/types/amount.ts - Amount 类实现
  • src/types/amount.test.ts - 35 个测试用例
  • src/hooks/use-send.logic.ts - 使用 Amount 类修复 BUG

长期收益

新开发者只需使用 Amount 类,无需关心底层的 raw/formatted 区别,从根本上避免此类 BUG。

Problem:
- BigInt(asset.amount) throws when amount contains decimals
- No clear distinction between raw (smallest unit) and formatted values
- Easy to make mistakes when handling monetary values

Solution:
- Add Amount class with immutable design
- Factory methods: fromRaw(), fromFormatted(), parse() (auto-detect)
- Comparison: gt(), lt(), eq(), gte(), lte()
- Arithmetic: add(), sub(), mul(), div()
- Conversion: toRawString(), toFormatted(), toNumber()
- Helper: amountFromAsset() for smart parsing

Usage:
```ts
// From chain data (raw)
const balance = Amount.fromRaw('1000000000000000000', 18)

// From user input (formatted)
const input = Amount.fromFormatted('1.5', 18)

// Auto-detect (handles both)
const amount = Amount.parse(asset.amount, asset.decimals)

// Compare and operate
if (input.gt(balance)) throw new Error('Insufficient balance')
const remaining = balance.sub(input)
```

Fixes SendPage BigInt error with '102531.02649070'
@Gaubee
Gaubee merged commit 2e0820b into main Dec 22, 2025
3 checks passed
@Gaubee Gaubee mentioned this pull request Dec 22, 2025
1 of 10 tasks
@Gaubee
Gaubee deleted the feat/amount-type branch January 4, 2026 07:22
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.

1 participant