检查的顺序
提现窗口是一个表单,包含地址、金额,有时还有网络、标签,有时还有验证码。这样的表单在每个交易所和每个钱包里都存在,看起来都差不多,这就掩盖了一个事实:在按钮被启用之前,很多决定其实已经做好了。这个表单短到可以完整读完,所以下面就是它具体做了什么。
| 检查项 | 什么算通过 | 失败时你会看到什么 |
|---|---|---|
| 是否是大于零的数字? | 任何正数金额 | 金额错误提示,按钮保持禁用 |
| 你有这么多吗? | 金额 ≤ 你在该币种下的余额(从该币种的最小单位换算而来) | “余额不足” |
| 是否足够发送? | 金额 ≥ 该币种的最低提现额 | 最低金额,连同币种符号,会显示在提示信息里 |
最低金额和手续费是按币种和网络分别计算的,两者都会打印在表单下方的警告文字里,在你输入任何内容之前就能看到。
已核实(源码级)component/common/popup/wallet/withdraw.tsx:金额校验器会拒绝非正数值(amountError),然后用 Big(balance) ÷ 10^precision 与输入的值比较(notEnoughBalance),接着用 selectCoin.minWithdrawView 与之比较(minWithdraw,其中 {min} 和 {symbol} 会被替换)。警告区块渲染 withdrawWarn,使用 {symbol}、{min: selectCoin.minWithdrawView} 和 {fee: selectCoin.feeView}。store/CoinStore.ts:minWithdrawView 和 feeView 将存储的 minWithdraw 和 fee 除以 10^precision。
网络、标签和验证码
这三个字段只有在该币种需要时才会出现,而且每一个的存在都是因为曾经有人因此损失过资金。网络选择器出现在那些存在于多条链上的币种中:一个稳定币可能以 ERC-20 代币、TRC-20 代币或其他若干种网络形式转账,而如果你在接收钱包不监听的网络上发送转账,那就不是转账,而是损失。当你选择一个网络时,请求会带上该网络的基础币种,这样服务器就能确切知道你请求的是哪条链。关于网络的这篇文章讲的是这个问题的另一半。
标签字段出现在那些地址代表交易所或共享钱包而非个人的币种中,此时目标标签或备注用于在其内部识别你。只发送到地址而不带标签,资金会到达正确的“大楼”,却没有“房间号”。该窗口会将标签作为独立字段发送,且仅对这些币种如此。
如果你为账户开启了一次性验证码,验证码输入框就会出现。这个窗口只接受恰好六位数字,并将验证码包含在请求中,服务器会在做任何其他操作之前先检查它。这是列表中唯一能保护你免受
ENGINE-VERIFIEDwithdraw.tsx:请求体为 { coinId, amount: Big(amount) × 10^precision 转为字符串, address };当 isNetworkCoin && selectedNetwork 时添加 baseCoinId;当六位数字输入完成时(onTypeOtp: code.length === 6)添加 otpCode;当 selectCoin.type === ECoinType.TAG 且该字段非空时添加 tag。请求为 api.post('/wallet/withdraw', body);非成功状态码会被抛出并显示,成功则显示 requestWithdrawDone 并关闭窗口。
它无法检查的部分
以上每一项检查都是关于金额、路径和发送方的。没有一项是关于目的地的,因为也无法做到。地址是一个字符串,要么格式正确要么不正确,而一个属于陌生人的格式正确的地址,和一个属于你的格式正确的地址是没有区别的。网站能看到字符串能被解析,却看不出它属于谁。
- 网站会检查金额、余额、最低限额、网络、标签和验证码。这些是它的职责,其中任何一项失败都会在请求离开浏览器之前将其拦下。
- 你需要检查地址。从发放地址的地方复制它,不仅要看首尾,也要读中间的字符,并且把历史记录中任何最近的小额转账都当作需要更仔细核实的理由,而不是走捷径的借口。
- 手续费是网络的手续费,会提前显示出来。它会在你输入之前就打印在最低限额旁边,手续费相关文章解释了它为何会变动。
- 点击按钮之后,由链决定。提交的提现请求先由钱包服务处理,然后由网络确认;什么是确认一文讲述了等待过程。
本文描述的是代码库中出现的客户端提现组件;钱包服务会在服务器端进行自己的检查,并且是决定提现是否发送的最终权威。限额、手续费和最低限额是按币种设定的,可能会变化;窗口会显示当前的数值。
常见问题
为什么提现按钮一直是禁用状态?
因为其中一项检查未通过:金额不是正数、超过了你的余额、低于该币种的最低限额,或者缺少必填字段,例如网络、标签或六位验证码。金额下方的提示信息会说明具体原因。
我在哪里能看到最低限额和手续费?
在表单下方的提示文字中,针对你所选择的币种和网络显示。两者都以该币种的最小单位存储,并转换为常规单位显示。
为什么有些币种会有网络选择器?
因为这些币种存在于不止一条链上。请求会携带你所选网络对应的基础币种,以确保转账走的是你的接收钱包所监听的那条链。
标签字段是什么?
是针对那些地址标识共享钱包的币种所设的目的地标签或备注。它只针对这些币种作为独立字段发送;如果没有它,资金会到达该地址,但不会到达你手中。
窗口会检查地址吗?
只检查它是否已填写。它无法判断这是谁的地址,这就是为什么你应该从发放地址的地方复制它,并且不只是看首尾字符,而要多读一些。
来源与参考
- Betkyo 客户端源码:component/common/popup/wallet/withdraw.tsx(验证、请求体、OTP 和标签处理),store/CoinStore.ts(minWithdrawView、feeView)