1244 lines
31 KiB
JavaScript
1244 lines
31 KiB
JavaScript
import serviceConfig from "../config/service";
|
||
import request from "../utils/request";
|
||
|
||
function createError(message, raw) {
|
||
return {
|
||
message: message || "接口请求失败",
|
||
raw: raw,
|
||
};
|
||
}
|
||
|
||
function toNumber(value) {
|
||
const number = Number(value || 0);
|
||
return Number.isFinite(number) ? number : 0;
|
||
}
|
||
|
||
function toFixedNumber(value, digits) {
|
||
return toNumber(value).toFixed(digits);
|
||
}
|
||
|
||
function formatHomeNumber(value, digits) {
|
||
const number = toNumber(value);
|
||
|
||
if (digits > 0) {
|
||
const fixed = number.toFixed(digits);
|
||
const parts = fixed.split(".");
|
||
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||
return parts.join(".");
|
||
}
|
||
|
||
return Math.round(number)
|
||
.toString()
|
||
.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||
}
|
||
|
||
function isSuccessPayload(payload) {
|
||
if (!payload || typeof payload !== "object") {
|
||
return false;
|
||
}
|
||
|
||
const statusCode =
|
||
payload.code !== undefined ? Number(payload.code) : Number(payload.status);
|
||
|
||
return statusCode === 200;
|
||
}
|
||
|
||
function unwrapPayload(payload, fallbackMessage) {
|
||
if (isSuccessPayload(payload)) {
|
||
return payload.data;
|
||
}
|
||
|
||
if (payload && typeof payload === "object") {
|
||
throw createError(
|
||
payload.msg || payload.message || fallbackMessage || "接口请求失败",
|
||
payload,
|
||
);
|
||
}
|
||
|
||
throw createError(fallbackMessage || "接口返回异常", payload);
|
||
}
|
||
|
||
async function fetchPayload(options, fallbackMessage) {
|
||
try {
|
||
const payload = await request(options);
|
||
return unwrapPayload(payload, fallbackMessage);
|
||
} catch (error) {
|
||
if (error && error.message) {
|
||
throw error;
|
||
}
|
||
|
||
throw createError(fallbackMessage || "接口请求失败", error);
|
||
}
|
||
}
|
||
|
||
function createRequestOptions(baseOptions, requestOptions) {
|
||
return Object.assign({}, baseOptions, requestOptions || {});
|
||
}
|
||
|
||
function normalizeTicker(data) {
|
||
const close = toNumber(data && (data.close || data.cnyPrice));
|
||
const lastDayClose = toNumber(data && data.lastDayClose);
|
||
const rawChange = data && data.change;
|
||
let change = typeof rawChange === "string" ? rawChange : "";
|
||
|
||
if (!change) {
|
||
if (close && lastDayClose) {
|
||
const percent = ((close - lastDayClose) / lastDayClose) * 100;
|
||
const prefix = percent >= 0 ? "+" : "";
|
||
change = prefix + percent.toFixed(2) + "%";
|
||
} else {
|
||
change = "0.00%";
|
||
}
|
||
}
|
||
|
||
return {
|
||
symbol: (data && data.symbol) || "BMT/CNY",
|
||
close: close,
|
||
cnyPrice:
|
||
(data && data.cnyPrice) || (close ? close.toFixed(2) : "0.00"),
|
||
lastDayClose: lastDayClose,
|
||
change: change,
|
||
};
|
||
}
|
||
|
||
function normalizeBalances(data) {
|
||
return {
|
||
points: toNumber(data && data.point),
|
||
power: toNumber(data && data.c_power),
|
||
bmt: toNumber(data && data.bmt_num),
|
||
withdrawableBmt: toNumber(data && data.bmt_num),
|
||
voucher: toNumber(data && data.coin),
|
||
coupon: toNumber(data && data.diamond_balance),
|
||
};
|
||
}
|
||
|
||
function buildHomeOverview(balanceData, tickerData) {
|
||
const balances = normalizeBalances(balanceData);
|
||
const ticker = normalizeTicker(tickerData);
|
||
|
||
return {
|
||
title: "数字资产",
|
||
ticker: ticker,
|
||
topStats: [
|
||
{
|
||
key: "wallet-bmt",
|
||
title: "可提取BMT",
|
||
value: toFixedNumber(balances.withdrawableBmt, 2),
|
||
unit: "BMT",
|
||
accent: "gold",
|
||
},
|
||
{
|
||
key: "ticker",
|
||
title: "BMT实时价格",
|
||
value: toFixedNumber(ticker.close || ticker.cnyPrice, 3),
|
||
unit: "CNY/BMT",
|
||
accent: "green",
|
||
},
|
||
],
|
||
quickAssets: [
|
||
{
|
||
key: "points",
|
||
title: "积分",
|
||
value: formatHomeNumber(balances.points, 0),
|
||
accent: "gold",
|
||
},
|
||
{
|
||
key: "voucher",
|
||
title: "抵用券",
|
||
value: formatHomeNumber(balances.voucher, 2),
|
||
accent: "rose",
|
||
},
|
||
{
|
||
key: "coupon",
|
||
title: "消费券",
|
||
value: formatHomeNumber(balances.coupon, 0),
|
||
accent: "teal",
|
||
},
|
||
{
|
||
key: "power",
|
||
title: "算力",
|
||
value: formatHomeNumber(balances.power, 0),
|
||
accent: "violet",
|
||
},
|
||
],
|
||
features: [
|
||
{
|
||
key: "bmt-exchange",
|
||
title: "BMT兑换",
|
||
desc: "积分与算力兑换 BMT",
|
||
accent: "mint",
|
||
},
|
||
{
|
||
key: "power-exchange",
|
||
title: "算力兑换",
|
||
desc: "抵用券与消费券兑换算力",
|
||
accent: "amber",
|
||
},
|
||
{
|
||
key: "transfer",
|
||
title: "转赠中心",
|
||
desc: "积分或算力转赠好友",
|
||
accent: "indigo",
|
||
},
|
||
{
|
||
key: "withdraw",
|
||
title: "BMT提取",
|
||
desc: "钱包中的 BMT 可提取到交易所进行交易",
|
||
accent: "pink",
|
||
},
|
||
{
|
||
key: "points-convert",
|
||
title: "积分转换",
|
||
desc: "释放中的积分转换为可用积分",
|
||
accent: "pink",
|
||
},
|
||
],
|
||
notice:
|
||
"数字资产是您在平台上的虚拟资产,请谨慎管理;BMT可在交易所中进行交易。",
|
||
};
|
||
}
|
||
|
||
function buildTransferTips(feePercent) {
|
||
const percentText = toNumber(feePercent) || 10;
|
||
|
||
return {
|
||
points: [
|
||
"只能转赠100的整数倍",
|
||
"凌晨0点-凌晨01点系统维护不可赠送",
|
||
"转赠系统会扣除" + percentText + "%的手续费",
|
||
],
|
||
power: [
|
||
"只能转赠1的整数倍",
|
||
"转赠系统会扣除" + percentText + "%的手续费",
|
||
],
|
||
};
|
||
}
|
||
|
||
function buildWalletList(address) {
|
||
const normalizedAddress = String(address || "").trim();
|
||
|
||
if (!normalizedAddress) {
|
||
return [];
|
||
}
|
||
|
||
return [
|
||
{
|
||
id: "default-wallet",
|
||
name: serviceConfig.WALLET_NAME,
|
||
address: normalizedAddress,
|
||
isDefault: true,
|
||
},
|
||
];
|
||
}
|
||
|
||
function buildWalletPayload(address) {
|
||
return {
|
||
wallets: buildWalletList(address),
|
||
instructions: [
|
||
"点击交易所 App 底部“资产”进入钱包页",
|
||
"搜索或输入大写字母 BMT",
|
||
"点击“充币 / 充值”进入收款地址页面",
|
||
"复制钱包地址后回填到当前页面",
|
||
],
|
||
};
|
||
}
|
||
|
||
function pickFirstValue(source, keys) {
|
||
const target = source && typeof source === "object" ? source : {};
|
||
|
||
for (let index = 0; index < keys.length; index += 1) {
|
||
const key = keys[index];
|
||
const value = target[key];
|
||
|
||
if (
|
||
value !== undefined &&
|
||
value !== null &&
|
||
!(typeof value === "string" && value.trim() === "")
|
||
) {
|
||
return value;
|
||
}
|
||
}
|
||
|
||
return "";
|
||
}
|
||
|
||
function normalizeListData(data) {
|
||
if (Array.isArray(data)) {
|
||
return data;
|
||
}
|
||
|
||
if (data && Array.isArray(data.list)) {
|
||
return data.list;
|
||
}
|
||
|
||
return [];
|
||
}
|
||
|
||
function formatTransferRecordNumber(value) {
|
||
const number = toNumber(value);
|
||
return formatHomeNumber(number, Number.isInteger(number) ? 0 : 2);
|
||
}
|
||
|
||
function formatLedgerRecordNumber(value) {
|
||
return formatTransferRecordNumber(Math.abs(toNumber(value)));
|
||
}
|
||
|
||
function resolveRecordDirection(item, amountValue, positiveLabel, negativeLabel) {
|
||
const rawDirection = pickFirstValue(item, [
|
||
"io_type",
|
||
"in_out",
|
||
"direction",
|
||
"income_type",
|
||
"is_add",
|
||
"flow_type",
|
||
]);
|
||
|
||
if (rawDirection !== "") {
|
||
const directionText = String(rawDirection).toLowerCase();
|
||
|
||
if (
|
||
directionText === "1" ||
|
||
directionText === "in" ||
|
||
directionText === "income" ||
|
||
directionText === "add" ||
|
||
directionText === "+"
|
||
) {
|
||
return positiveLabel;
|
||
}
|
||
|
||
if (
|
||
directionText === "0" ||
|
||
directionText === "-1" ||
|
||
directionText === "out" ||
|
||
directionText === "expense" ||
|
||
directionText === "sub" ||
|
||
directionText === "-"
|
||
) {
|
||
return negativeLabel;
|
||
}
|
||
}
|
||
|
||
return toNumber(amountValue) >= 0 ? positiveLabel : negativeLabel;
|
||
}
|
||
|
||
function buildDirectionPresentation(direction) {
|
||
return {
|
||
income:
|
||
direction === "收入" ||
|
||
direction === "转入" ||
|
||
direction === "获得" ||
|
||
direction === "到账",
|
||
actionSymbol:
|
||
direction === "收入" ||
|
||
direction === "转入" ||
|
||
direction === "获得" ||
|
||
direction === "到账"
|
||
? "+"
|
||
: "-",
|
||
};
|
||
}
|
||
|
||
function buildRecordId(item, fallbackPrefix) {
|
||
return String(
|
||
pickFirstValue(item, [
|
||
"order_sn",
|
||
"trade_no",
|
||
"bill_no",
|
||
"sn",
|
||
"id",
|
||
"log_id",
|
||
"uid",
|
||
]) || fallbackPrefix + "-" + Math.random(),
|
||
);
|
||
}
|
||
|
||
function mapWalletFlowRecords(list, meta) {
|
||
return normalizeListData(list).map(function (item) {
|
||
const amountValue = pickFirstValue(item, [
|
||
"number",
|
||
"num",
|
||
"amount",
|
||
"change_num",
|
||
"value",
|
||
"money",
|
||
"bmt_num",
|
||
"power_num",
|
||
"point_num",
|
||
]);
|
||
const direction = resolveRecordDirection(item, amountValue, "收入", "支出");
|
||
const directionPresentation = buildDirectionPresentation(direction);
|
||
const orderSn = String(
|
||
pickFirstValue(item, ["order_sn", "trade_no", "bill_no", "sn"]) || "",
|
||
);
|
||
const noteText = String(
|
||
pickFirstValue(item, [
|
||
"remark",
|
||
"desc",
|
||
"memo",
|
||
"note",
|
||
"type_name",
|
||
"status_text",
|
||
]) || "",
|
||
);
|
||
const balanceValue = pickFirstValue(item, [
|
||
"balance",
|
||
"after_balance",
|
||
"surplus",
|
||
"remain",
|
||
"wallet_balance",
|
||
"usable_balance",
|
||
]);
|
||
const title =
|
||
pickFirstValue(item, ["title", "name", "type_name"]) ||
|
||
meta.title ||
|
||
meta.unit + "记录";
|
||
|
||
return {
|
||
id: buildRecordId(item, meta.key || "flow"),
|
||
title: title,
|
||
subtitle: orderSn ? "单号 " + orderSn : noteText || direction,
|
||
time: pickFirstValue(item, [
|
||
"add_time",
|
||
"create_time",
|
||
"created_at",
|
||
"time",
|
||
"update_time",
|
||
]),
|
||
amount:
|
||
directionPresentation.actionSymbol +
|
||
formatLedgerRecordNumber(amountValue),
|
||
balance:
|
||
balanceValue !== ""
|
||
? "结余 " + formatTransferRecordNumber(balanceValue) + " " + meta.unit
|
||
: "",
|
||
balanceLabel:
|
||
balanceValue !== ""
|
||
? "剩余" + meta.unit + ":" + formatTransferRecordNumber(balanceValue)
|
||
: "当前" + meta.unit + "流水",
|
||
assetLabel: meta.unit,
|
||
feeText: noteText || (orderSn ? "单号 " + orderSn : meta.subtitle),
|
||
directionLabel: direction,
|
||
actionSymbol: directionPresentation.actionSymbol,
|
||
orderSn: orderSn,
|
||
tag: directionPresentation.income ? "收" : "支",
|
||
tone: directionPresentation.income ? "success" : "danger",
|
||
cardTone: directionPresentation.income ? "success" : "danger",
|
||
};
|
||
});
|
||
}
|
||
|
||
function buildRedeemConsumeText(item, meta) {
|
||
const fragments = [];
|
||
|
||
if (meta.type === 0) {
|
||
const voucherValue = pickFirstValue(item, [
|
||
"voucher_num",
|
||
"coin",
|
||
"deduct_coin",
|
||
"use_coin",
|
||
]);
|
||
const couponValue = pickFirstValue(item, [
|
||
"coupon_num",
|
||
"diamond",
|
||
"deduct_diamond",
|
||
"use_diamond",
|
||
]);
|
||
|
||
if (voucherValue !== "") {
|
||
fragments.push("抵用券 " + formatTransferRecordNumber(voucherValue));
|
||
}
|
||
|
||
if (couponValue !== "") {
|
||
fragments.push("消费券 " + formatTransferRecordNumber(couponValue));
|
||
}
|
||
} else {
|
||
const pointValue = pickFirstValue(item, [
|
||
"point",
|
||
"points",
|
||
"point_num",
|
||
"use_point",
|
||
"integral",
|
||
]);
|
||
const powerValue = pickFirstValue(item, [
|
||
"power",
|
||
"power_num",
|
||
"c_power",
|
||
"use_power",
|
||
]);
|
||
|
||
if (pointValue !== "") {
|
||
fragments.push("积分 " + formatTransferRecordNumber(pointValue));
|
||
}
|
||
|
||
if (powerValue !== "") {
|
||
fragments.push("算力 " + formatTransferRecordNumber(powerValue));
|
||
}
|
||
}
|
||
|
||
if (fragments.length) {
|
||
return "消耗" + fragments.join(" / ");
|
||
}
|
||
|
||
return String(
|
||
pickFirstValue(item, ["remark", "desc", "memo", "note", "status_text"]) ||
|
||
meta.subtitle ||
|
||
"",
|
||
);
|
||
}
|
||
|
||
function mapRedeemRecords(list, meta) {
|
||
return normalizeListData(list).map(function (item) {
|
||
const primaryValue = pickFirstValue(item, meta.amountKeys);
|
||
const orderSn = String(
|
||
pickFirstValue(item, ["order_sn", "trade_no", "bill_no", "sn"]) || "",
|
||
);
|
||
const balanceValue = pickFirstValue(item, [
|
||
"balance",
|
||
"after_balance",
|
||
"surplus",
|
||
"remain",
|
||
]);
|
||
const noteText = buildRedeemConsumeText(item, meta);
|
||
|
||
return {
|
||
id: buildRecordId(item, meta.key || "redeem"),
|
||
title:
|
||
pickFirstValue(item, ["title", "name", "type_name"]) ||
|
||
meta.title ||
|
||
"兑换记录",
|
||
subtitle: orderSn ? "单号 " + orderSn : noteText,
|
||
time: pickFirstValue(item, [
|
||
"add_time",
|
||
"create_time",
|
||
"created_at",
|
||
"time",
|
||
"update_time",
|
||
]),
|
||
amount: "+" + formatLedgerRecordNumber(primaryValue),
|
||
balance:
|
||
balanceValue !== ""
|
||
? "结余 " + formatTransferRecordNumber(balanceValue) + " " + meta.unit
|
||
: "",
|
||
balanceLabel:
|
||
balanceValue !== ""
|
||
? "剩余" + meta.unit + ":" + formatTransferRecordNumber(balanceValue)
|
||
: "本次到账" + meta.unit,
|
||
assetLabel: meta.unit,
|
||
feeText: noteText,
|
||
directionLabel: "兑换",
|
||
actionSymbol: "+",
|
||
orderSn: orderSn,
|
||
tag: "兑",
|
||
tone: "success",
|
||
cardTone: "success",
|
||
};
|
||
});
|
||
}
|
||
|
||
function getTransferRecordUnit(item) {
|
||
return Number(item && item.type) === 0 ? "算力" : "积分";
|
||
}
|
||
|
||
function getTransferRecordTone(item) {
|
||
return Number(item && item.io_type) === 1 ? "success" : "danger";
|
||
}
|
||
|
||
function getTransferRecordTag(item) {
|
||
return Number(item && item.io_type) === 1 ? "收" : "赠";
|
||
}
|
||
|
||
function getTransferRecordDirection(item) {
|
||
return Number(item && item.io_type) === 1 ? "转入" : "转出";
|
||
}
|
||
|
||
function getTransferRecordTitle(item) {
|
||
const unit = getTransferRecordUnit(item);
|
||
return Number(item && item.io_type) === 1 ? unit + "获赠" : unit + "转赠";
|
||
}
|
||
|
||
function getTransferRecordSymbol(item) {
|
||
return Number(item && item.io_type) === 1 ? "+" : "-";
|
||
}
|
||
|
||
function getTransferRecordAmount(item) {
|
||
const numberText = formatTransferRecordNumber(item && item.num);
|
||
return getTransferRecordSymbol(item) + numberText;
|
||
}
|
||
|
||
function getTransferRecordFee(item) {
|
||
if (
|
||
item &&
|
||
item.fee !== undefined &&
|
||
item.fee !== null &&
|
||
String(item.fee).trim() !== ""
|
||
) {
|
||
return toNumber(item.fee);
|
||
}
|
||
|
||
return (toNumber(item && item.num) * toNumber(item && item.fee_percent)) / 100;
|
||
}
|
||
|
||
function getTransferRecordFeeText(item) {
|
||
const percent = toNumber(item && item.fee_percent);
|
||
const unit = getTransferRecordUnit(item);
|
||
const feeText = formatTransferRecordNumber(getTransferRecordFee(item));
|
||
|
||
if (percent > 0) {
|
||
return (
|
||
"手续费 " +
|
||
feeText +
|
||
" " +
|
||
unit +
|
||
" (" +
|
||
formatTransferRecordNumber(percent) +
|
||
"%)"
|
||
);
|
||
}
|
||
|
||
return "手续费 " + feeText + " " + unit;
|
||
}
|
||
|
||
function getTransferRecordBalance(item) {
|
||
const unit = getTransferRecordUnit(item);
|
||
return "结余 " + toFixedNumber(item && item.balance, 2) + " " + unit;
|
||
}
|
||
|
||
function getTransferRecordBalanceLabel(item) {
|
||
const unit = getTransferRecordUnit(item);
|
||
return "剩余" + unit + ":" + formatTransferRecordNumber(item && item.balance);
|
||
}
|
||
|
||
function mapTransferRecords(list) {
|
||
return (Array.isArray(list) ? list : []).map(function (item) {
|
||
return {
|
||
id: item.order_sn || item.id || String(Math.random()),
|
||
title: item.title || getTransferRecordTitle(item),
|
||
subtitle: item.order_sn ? "单号 " + item.order_sn : getTransferRecordDirection(item),
|
||
time: item.add_time || "",
|
||
amount: getTransferRecordAmount(item),
|
||
balance: getTransferRecordBalance(item),
|
||
balanceLabel: getTransferRecordBalanceLabel(item),
|
||
assetLabel: getTransferRecordUnit(item),
|
||
feeText: getTransferRecordFeeText(item),
|
||
directionLabel: getTransferRecordDirection(item),
|
||
actionSymbol: getTransferRecordSymbol(item),
|
||
orderSn: item.order_sn || "",
|
||
tag: getTransferRecordTag(item),
|
||
tone: getTransferRecordTone(item),
|
||
cardTone: getTransferRecordTone(item),
|
||
};
|
||
});
|
||
}
|
||
|
||
function mapPointsConvertRecords(list) {
|
||
return (Array.isArray(list) ? list : []).map(function (item) {
|
||
const numberText = toFixedNumber(item.number, 2);
|
||
const transferCoinText = toFixedNumber(item.transfer_coin_num, 0);
|
||
const releaseTotal =
|
||
item &&
|
||
item.userBillRelease &&
|
||
item.userBillRelease.total !== undefined &&
|
||
item.userBillRelease.total !== null
|
||
? String(item.userBillRelease.total)
|
||
: "";
|
||
|
||
return {
|
||
id: String(item.id || ""),
|
||
title: item.title || "积分记录",
|
||
subtitle: "可转数量 " + transferCoinText,
|
||
time: item.add_time || "",
|
||
amount: "+" + numberText,
|
||
balance: releaseTotal ? "释放总量 " + releaseTotal : "",
|
||
tag: "积",
|
||
tone: "success",
|
||
};
|
||
});
|
||
}
|
||
|
||
function buildDefaultLedger(type, balances) {
|
||
const map = {
|
||
power: {
|
||
title: "兑换记录",
|
||
subtitle: "算力兑换记录",
|
||
},
|
||
bmt: {
|
||
title: "兑换记录",
|
||
subtitle: "BMT兑换记录",
|
||
},
|
||
withdraw: {
|
||
title: "提取记录",
|
||
subtitle: "BMT提取流水",
|
||
},
|
||
coupon: {
|
||
title: "消费券",
|
||
subtitle: "当前消费券 " + toFixedNumber(balances.coupon, 2),
|
||
},
|
||
voucher: {
|
||
title: "抵用券记录",
|
||
subtitle: "可用抵用券 " + toFixedNumber(balances.voucher, 2),
|
||
},
|
||
};
|
||
|
||
return {
|
||
type: type,
|
||
title: map[type].title,
|
||
subtitle: map[type].subtitle,
|
||
records: [],
|
||
};
|
||
}
|
||
|
||
function normalizeTransferTarget(data, fallbackId) {
|
||
if (data && typeof data === "object" && !Array.isArray(data)) {
|
||
const id = String(data.uid || data.id || fallbackId || "").trim();
|
||
if (!id) {
|
||
throw createError("未查询到好友", data);
|
||
}
|
||
|
||
return {
|
||
id: id,
|
||
nickname:
|
||
data.nickname || data.nick_name || data.username || "用户" + id,
|
||
phone: data.mobile || data.phone || "ID已通过校验",
|
||
avatar: data.avatar || data.headimg || "",
|
||
};
|
||
}
|
||
|
||
if (data === true) {
|
||
const id = String(fallbackId || "").trim();
|
||
if (!id) {
|
||
throw createError("未查询到好友", data);
|
||
}
|
||
|
||
return {
|
||
id: id,
|
||
nickname: "用户" + id,
|
||
phone: "ID已通过校验",
|
||
avatar: "",
|
||
};
|
||
}
|
||
|
||
throw createError("未查询到好友", data);
|
||
}
|
||
|
||
function sumBy(list, key) {
|
||
return (Array.isArray(list) ? list : []).reduce(function (total, item) {
|
||
return total + toNumber(item && item[key]);
|
||
}, 0);
|
||
}
|
||
|
||
async function fetchPriceData(requestOptions) {
|
||
return fetchPayload(
|
||
createRequestOptions({
|
||
url: serviceConfig.ENDPOINTS.price,
|
||
}, requestOptions),
|
||
"实时价格加载失败",
|
||
);
|
||
}
|
||
|
||
async function fetchHomeBalanceData(requestOptions) {
|
||
return fetchPayload(
|
||
createRequestOptions({
|
||
url: serviceConfig.ENDPOINTS.homeBalance,
|
||
}, requestOptions),
|
||
"首页资产加载失败",
|
||
);
|
||
}
|
||
|
||
async function fetchBmtPowerRateData(requestOptions) {
|
||
return fetchPayload(
|
||
createRequestOptions({
|
||
url: serviceConfig.ENDPOINTS.bmtRedeemPowerRate,
|
||
}, requestOptions),
|
||
"兑换比例加载失败",
|
||
);
|
||
}
|
||
|
||
async function fetchTransferFeeData(requestOptions) {
|
||
return fetchPayload(
|
||
createRequestOptions({
|
||
url: serviceConfig.ENDPOINTS.transferFee,
|
||
}, requestOptions),
|
||
"手续费比例加载失败",
|
||
);
|
||
}
|
||
|
||
async function fetchWalletAddressData(requestOptions) {
|
||
return fetchPayload(
|
||
createRequestOptions({
|
||
url: serviceConfig.ENDPOINTS.walletDetail,
|
||
}, requestOptions),
|
||
"钱包加载失败",
|
||
);
|
||
}
|
||
|
||
async function fetchPointsConvertList(requestOptions) {
|
||
return fetchPayload(
|
||
createRequestOptions({
|
||
url: serviceConfig.ENDPOINTS.pointsConvertList,
|
||
data: {
|
||
interval: serviceConfig.POINTS_CONVERT_INTERVAL,
|
||
},
|
||
}, requestOptions),
|
||
"积分转换列表加载失败",
|
||
);
|
||
}
|
||
|
||
async function fetchTransferLedgerData(requestOptions) {
|
||
return fetchPayload(
|
||
createRequestOptions({
|
||
url: serviceConfig.ENDPOINTS.transferLedger,
|
||
}, requestOptions),
|
||
"转赠记录加载失败",
|
||
);
|
||
}
|
||
|
||
async function fetchWalletFlowListData(flowType, requestOptions) {
|
||
return fetchPayload(
|
||
createRequestOptions({
|
||
url: serviceConfig.ENDPOINTS.walletFlowList,
|
||
data: {
|
||
type: flowType,
|
||
},
|
||
}, requestOptions),
|
||
"资产流水加载失败",
|
||
);
|
||
}
|
||
|
||
async function fetchRedeemRecordListData(redeemType, requestOptions) {
|
||
return fetchPayload(
|
||
createRequestOptions({
|
||
url: serviceConfig.ENDPOINTS.redeemRecordList,
|
||
data: {
|
||
type: redeemType,
|
||
},
|
||
}, requestOptions),
|
||
"兑换记录加载失败",
|
||
);
|
||
}
|
||
|
||
export async function fetchAssetHome(requestOptions) {
|
||
const result = await Promise.all([
|
||
fetchPriceData(requestOptions),
|
||
fetchHomeBalanceData(requestOptions),
|
||
]);
|
||
return buildHomeOverview(result[1], result[0]);
|
||
}
|
||
|
||
export async function fetchPointsConvertDetail(requestOptions) {
|
||
const result = await Promise.all([
|
||
fetchHomeBalanceData(requestOptions),
|
||
fetchPointsConvertList(requestOptions),
|
||
]);
|
||
const balances = normalizeBalances(result[0]);
|
||
const pointList = Array.isArray(result[1] && result[1].list)
|
||
? result[1].list
|
||
: [];
|
||
|
||
return {
|
||
availablePoints: toFixedNumber(balances.points, 2),
|
||
pendingPoints: toFixedNumber(sumBy(pointList, "number"), 0),
|
||
ids: pointList
|
||
.map(function (item) {
|
||
return item && item.id;
|
||
})
|
||
.filter(Boolean),
|
||
tips: [
|
||
"释放中的积分,转换成可用积分后,方可兑换BMT;",
|
||
"凌晨0点-凌晨1点积分系统维护不可兑换。",
|
||
],
|
||
};
|
||
}
|
||
|
||
export async function submitAssetPointsConvert(payload, requestOptions) {
|
||
const ids = Array.isArray(payload && payload.ids) ? payload.ids : [];
|
||
|
||
if (!ids.length) {
|
||
throw createError("暂无可转换积分");
|
||
}
|
||
|
||
await fetchPayload(
|
||
createRequestOptions({
|
||
url: serviceConfig.ENDPOINTS.pointsConvertSubmit,
|
||
method: "POST",
|
||
data: {
|
||
ids: ids.join(","),
|
||
type: 1,
|
||
},
|
||
}, requestOptions),
|
||
"积分转换失败",
|
||
);
|
||
|
||
return {
|
||
success: true,
|
||
message: "转换成功",
|
||
};
|
||
}
|
||
|
||
export async function fetchTransferDetail(requestOptions) {
|
||
const result = await Promise.all([
|
||
fetchHomeBalanceData(requestOptions),
|
||
fetchTransferFeeData(requestOptions),
|
||
]);
|
||
const balances = normalizeBalances(result[0]);
|
||
const feePercent = toNumber(result[1] && result[1].r) || 10;
|
||
|
||
return {
|
||
balances: {
|
||
points: toFixedNumber(balances.points, 0),
|
||
power: toFixedNumber(balances.power, 0),
|
||
},
|
||
feePercent: feePercent,
|
||
tips: buildTransferTips(feePercent),
|
||
};
|
||
}
|
||
|
||
export async function searchTransferUser(uid, requestOptions) {
|
||
const keyword = String(uid || "").trim();
|
||
if (!keyword) {
|
||
throw createError("请输入被赠人ID");
|
||
}
|
||
|
||
const data = await fetchPayload(
|
||
createRequestOptions({
|
||
url: serviceConfig.ENDPOINTS.transferUser,
|
||
method: "POST",
|
||
data: {
|
||
uid: keyword,
|
||
},
|
||
}, requestOptions),
|
||
"查询好友失败",
|
||
);
|
||
|
||
return normalizeTransferTarget(data, keyword);
|
||
}
|
||
|
||
export async function submitAssetTransfer(payload, requestOptions) {
|
||
const transferType = payload && payload.type === "power" ? "power" : "points";
|
||
const targetId = String(payload && payload.targetId ? payload.targetId : "").trim();
|
||
const amount = toNumber(payload && payload.amount);
|
||
|
||
if (!targetId) {
|
||
throw createError("请选择被赠送人");
|
||
}
|
||
|
||
if (!amount) {
|
||
throw createError("请输入转赠数量");
|
||
}
|
||
|
||
const result = await Promise.all([
|
||
fetchTransferFeeData(requestOptions),
|
||
fetchPayload(
|
||
createRequestOptions({
|
||
url:
|
||
transferType === "power"
|
||
? serviceConfig.ENDPOINTS.transferPowerSubmit
|
||
: serviceConfig.ENDPOINTS.transferPointsSubmit,
|
||
method: "POST",
|
||
data: {
|
||
uid: targetId,
|
||
number: String(amount),
|
||
},
|
||
}, requestOptions),
|
||
"转赠失败",
|
||
),
|
||
]);
|
||
const feePercent = toNumber(result[0] && result[0].r) || 10;
|
||
const fee = (amount * feePercent) / 100;
|
||
const received = amount - fee;
|
||
|
||
return {
|
||
success: true,
|
||
fee: toFixedNumber(fee, 2),
|
||
received: toFixedNumber(received, 2),
|
||
};
|
||
}
|
||
|
||
export async function fetchPowerExchangeDetail(requestOptions) {
|
||
const result = await Promise.all([
|
||
fetchPriceData(requestOptions),
|
||
fetchHomeBalanceData(requestOptions),
|
||
]);
|
||
const ticker = normalizeTicker(result[0]);
|
||
const balances = normalizeBalances(result[1]);
|
||
|
||
return {
|
||
ticker: ticker,
|
||
balances: {
|
||
coupon: toFixedNumber(balances.coupon, 2),
|
||
voucher: toFixedNumber(balances.voucher, 2),
|
||
power: toFixedNumber(balances.power, 0),
|
||
},
|
||
tips: [
|
||
"算力 = 抵用券或消费券 ÷ BMT实时价格;",
|
||
"抵用券和消费券总数小于100券的不可兑换;",
|
||
"算力用于兑换BMT使用。",
|
||
],
|
||
};
|
||
}
|
||
|
||
export async function submitAssetPowerExchange(payload, requestOptions) {
|
||
const mode = payload && payload.mode === "coupon" ? "coupon" : "voucher";
|
||
const amount = toNumber(payload && payload.amount);
|
||
|
||
if (!amount) {
|
||
throw createError("请输入兑换数量");
|
||
}
|
||
|
||
await fetchPayload(
|
||
createRequestOptions({
|
||
url: serviceConfig.ENDPOINTS.powerExchangeSubmit,
|
||
method: "POST",
|
||
data: {
|
||
type: mode === "coupon" ? 1 : 0,
|
||
number: String(amount),
|
||
},
|
||
}, requestOptions),
|
||
"算力兑换失败",
|
||
);
|
||
|
||
return {
|
||
success: true,
|
||
};
|
||
}
|
||
|
||
export async function fetchBmtExchangeDetail(requestOptions) {
|
||
const result = await Promise.all([
|
||
fetchPriceData(requestOptions),
|
||
fetchHomeBalanceData(requestOptions),
|
||
fetchBmtPowerRateData(requestOptions),
|
||
]);
|
||
const ticker = normalizeTicker(result[0]);
|
||
const balances = normalizeBalances(result[1]);
|
||
const powerRate = toNumber(result[2]);
|
||
|
||
return {
|
||
ticker: ticker,
|
||
powerRate: powerRate,
|
||
balances: {
|
||
points: toFixedNumber(balances.points, 0),
|
||
power: toFixedNumber(balances.power, 2),
|
||
bmt: toFixedNumber(balances.bmt, 2),
|
||
voucher: toFixedNumber(balances.voucher, 2),
|
||
coupon: toFixedNumber(balances.coupon, 2),
|
||
},
|
||
tips: [
|
||
"BMT=输入的积分数量,提交时会同步校验所需算力。",
|
||
"兑换所需算力按后端返回比例实时计算。",
|
||
"只能兑换100的整数倍,小于100积分不可兑换。",
|
||
"凌晨0点至凌晨1点积分系统维护期间不可兑换。",
|
||
],
|
||
};
|
||
}
|
||
|
||
export async function submitAssetBmtExchange(payload, requestOptions) {
|
||
const amount = toNumber(payload && payload.amount);
|
||
|
||
if (!amount) {
|
||
throw createError("请输入积分数量");
|
||
}
|
||
|
||
await fetchPayload(
|
||
createRequestOptions({
|
||
url: serviceConfig.ENDPOINTS.bmtExchangeSubmit,
|
||
method: "POST",
|
||
data: {
|
||
number: String(amount),
|
||
},
|
||
}, requestOptions),
|
||
"BMT兑换失败",
|
||
);
|
||
|
||
return {
|
||
success: true,
|
||
};
|
||
}
|
||
|
||
export async function fetchWithdrawDetail(requestOptions) {
|
||
const result = await Promise.all([
|
||
fetchPriceData(requestOptions),
|
||
fetchHomeBalanceData(requestOptions),
|
||
fetchWalletAddressData(requestOptions),
|
||
]);
|
||
const ticker = normalizeTicker(result[0]);
|
||
const balances = normalizeBalances(result[1]);
|
||
const walletPayload = buildWalletPayload(result[2] && result[2].address);
|
||
|
||
return {
|
||
ticker: ticker,
|
||
withdrawableBmt: toFixedNumber(balances.withdrawableBmt, 2),
|
||
wallets: walletPayload.wallets,
|
||
defaultWallet: walletPayload.wallets[0] || null,
|
||
};
|
||
}
|
||
|
||
export async function submitAssetWithdraw(payload, requestOptions) {
|
||
const address = String(
|
||
payload && payload.address ? payload.address : "",
|
||
).trim();
|
||
const amount = toNumber(payload && payload.amount);
|
||
|
||
if (!address) {
|
||
throw createError("请先添加钱包地址");
|
||
}
|
||
|
||
if (!amount) {
|
||
throw createError("请输入提取数量");
|
||
}
|
||
|
||
await fetchPayload(
|
||
createRequestOptions({
|
||
url: serviceConfig.ENDPOINTS.withdrawSubmit,
|
||
method: "POST",
|
||
data: {
|
||
address: address,
|
||
number: String(amount),
|
||
},
|
||
}, requestOptions),
|
||
"提取失败",
|
||
);
|
||
|
||
return {
|
||
success: true,
|
||
};
|
||
}
|
||
|
||
export async function fetchLedgerDetail(type, requestOptions) {
|
||
if (type === "transfer") {
|
||
const data = await fetchTransferLedgerData(requestOptions);
|
||
return {
|
||
type: type,
|
||
title: "转赠记录",
|
||
subtitle: "积分与算力转赠流水",
|
||
records: mapTransferRecords(data && data.list),
|
||
};
|
||
}
|
||
|
||
if (type === "points") {
|
||
const data = await fetchWalletFlowListData(0, requestOptions);
|
||
return {
|
||
type: type,
|
||
title: "我的积分",
|
||
subtitle: "可用积分收支记录",
|
||
records: mapWalletFlowRecords(data, {
|
||
key: "points",
|
||
unit: "积分",
|
||
title: "积分记录",
|
||
subtitle: "可用积分流水",
|
||
}),
|
||
};
|
||
}
|
||
|
||
if (type === "power-flow") {
|
||
const data = await fetchWalletFlowListData(1, requestOptions);
|
||
return {
|
||
type: type,
|
||
title: "算力记录",
|
||
subtitle: "算力收支记录",
|
||
records: mapWalletFlowRecords(data, {
|
||
key: "power-flow",
|
||
unit: "算力",
|
||
title: "算力记录",
|
||
subtitle: "算力流水",
|
||
}),
|
||
};
|
||
}
|
||
|
||
if (type === "power") {
|
||
const data = await fetchRedeemRecordListData(0, requestOptions);
|
||
return {
|
||
type: type,
|
||
title: "兑换记录",
|
||
subtitle: "算力兑换记录",
|
||
records: mapRedeemRecords(data, {
|
||
key: "power",
|
||
type: 0,
|
||
unit: "算力",
|
||
title: "兑换算力",
|
||
subtitle: "算力兑换",
|
||
amountKeys: ["power", "power_num", "c_power", "redeem_power", "num", "number"],
|
||
}),
|
||
};
|
||
}
|
||
|
||
if (type === "bmt") {
|
||
const data = await fetchRedeemRecordListData(1, requestOptions);
|
||
return {
|
||
type: type,
|
||
title: "兑换记录",
|
||
subtitle: "BMT兑换记录",
|
||
records: mapRedeemRecords(data, {
|
||
key: "bmt",
|
||
type: 1,
|
||
unit: "BMT",
|
||
title: "兑换BMT",
|
||
subtitle: "BMT兑换",
|
||
amountKeys: ["bmt", "bmt_num", "redeem_bmt", "num", "number"],
|
||
}),
|
||
};
|
||
}
|
||
|
||
if (type === "withdraw") {
|
||
const data = await fetchWalletFlowListData(2, requestOptions);
|
||
return {
|
||
type: type,
|
||
title: "提取记录",
|
||
subtitle: "BMT收支记录",
|
||
records: mapWalletFlowRecords(data, {
|
||
key: "withdraw",
|
||
unit: "BMT",
|
||
title: "BMT记录",
|
||
subtitle: "BMT流水",
|
||
}),
|
||
};
|
||
}
|
||
|
||
const homeData = await fetchHomeBalanceData(requestOptions);
|
||
const balances = normalizeBalances(homeData);
|
||
return buildDefaultLedger(type, balances);
|
||
}
|
||
|
||
export async function fetchWalletDetail(requestOptions) {
|
||
const data = await fetchWalletAddressData(requestOptions);
|
||
return buildWalletPayload(data && data.address);
|
||
}
|
||
|
||
export async function saveAssetWallet(payload, requestOptions) {
|
||
const address = String(payload && payload.address ? payload.address : "").trim();
|
||
|
||
if (!address) {
|
||
throw createError("请输入钱包地址");
|
||
}
|
||
|
||
await fetchPayload(
|
||
createRequestOptions({
|
||
url: serviceConfig.ENDPOINTS.walletSave,
|
||
method: "POST",
|
||
data: {
|
||
address: address,
|
||
},
|
||
}, requestOptions),
|
||
"保存失败",
|
||
);
|
||
|
||
return {
|
||
success: true,
|
||
};
|
||
}
|
||
|
||
export async function deleteAssetWallet(id, requestOptions) {
|
||
await fetchPayload(
|
||
createRequestOptions({
|
||
url: serviceConfig.ENDPOINTS.walletSave,
|
||
method: "POST",
|
||
data: {
|
||
address: "",
|
||
},
|
||
}, requestOptions),
|
||
"删除失败",
|
||
);
|
||
|
||
return {
|
||
success: true,
|
||
};
|
||
}
|