feat(finance): add USDT address lookup
This commit is contained in:
parent
2eb18502a2
commit
ee900d0127
@ -4571,6 +4571,28 @@
|
||||
"x-permissions": ["finance-order:coin-seller-recharge:grant"]
|
||||
}
|
||||
},
|
||||
"/admin/finance/usdt-addresses/{app_code}": {
|
||||
"get": {
|
||||
"operationId": "getFinanceUSDTAddresses",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "app_code",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"$ref": "#/components/responses/FinanceUSDTAddressesResponse"
|
||||
}
|
||||
},
|
||||
"x-permission": "finance-order:coin-seller-recharge:view",
|
||||
"x-permissions": ["finance-order:coin-seller-recharge:view"]
|
||||
}
|
||||
},
|
||||
"/admin/finance/coin-seller-recharge-exchange-rates/{app_code}": {
|
||||
"get": {
|
||||
"operationId": "getFinanceCoinSellerRechargeExchangeRate",
|
||||
@ -8745,6 +8767,16 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"FinanceUSDTAddressesResponse": {
|
||||
"description": "OK",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ApiResponseFinanceUSDTAddresses"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"FinanceCoinSellerRechargeReceiptVerificationResponse": {
|
||||
"description": "OK",
|
||||
"content": {
|
||||
@ -10972,6 +11004,21 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"ApiResponseFinanceUSDTAddresses": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/Envelope"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/components/schemas/FinanceUSDTAddresses"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"ApiResponseFinanceCoinSellerRechargeReceiptVerification": {
|
||||
"allOf": [
|
||||
{
|
||||
@ -13400,6 +13447,38 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"FinanceUSDTAddress": {
|
||||
"type": "object",
|
||||
"required": ["chain", "address", "updatedAtMs"],
|
||||
"properties": {
|
||||
"chain": {
|
||||
"type": "string",
|
||||
"enum": ["TRON", "BSC"]
|
||||
},
|
||||
"address": {
|
||||
"type": "string"
|
||||
},
|
||||
"updatedAtMs": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
}
|
||||
},
|
||||
"FinanceUSDTAddresses": {
|
||||
"type": "object",
|
||||
"required": ["appCode", "items"],
|
||||
"properties": {
|
||||
"appCode": {
|
||||
"type": "string"
|
||||
},
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/FinanceUSDTAddress"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"FinanceCoinSellerRechargeExchangeRateInput": {
|
||||
"type": "object",
|
||||
"required": ["tiers", "whitelist"],
|
||||
|
||||
@ -10,6 +10,7 @@ import {
|
||||
fetchFinanceSession,
|
||||
grantFinanceCoinSellerRechargeOrder,
|
||||
getFinanceCoinSellerRechargeExchangeRate,
|
||||
getFinanceUSDTAddresses,
|
||||
listFinanceCoinSellerRechargeOrders,
|
||||
listFinanceRechargeDetails,
|
||||
listFinanceRechargeRegions,
|
||||
@ -514,6 +515,8 @@ export function FinanceApp() {
|
||||
[],
|
||||
);
|
||||
|
||||
const loadUSDTAddresses = useCallback((appCode) => getFinanceUSDTAddresses(appCode), []);
|
||||
|
||||
const saveCoinSellerRechargeExchangeRate = useCallback(
|
||||
async (appCode, payload) => {
|
||||
const saved = await replaceFinanceCoinSellerRechargeExchangeRate(appCode, cleanPayload(payload));
|
||||
@ -727,6 +730,7 @@ export function FinanceApp() {
|
||||
orders={coinSellerRechargeOrdersState.data}
|
||||
onCreate={submitCoinSellerRechargeOrder}
|
||||
onLoadExchangeRate={loadCoinSellerRechargeExchangeRate}
|
||||
onLoadUSDTAddresses={loadUSDTAddresses}
|
||||
onFiltersChange={updateCoinSellerRechargeOrderFilters}
|
||||
onGrant={grantCoinSellerRechargeOrder}
|
||||
onReload={loadCoinSellerRechargeOrders}
|
||||
|
||||
@ -26,6 +26,7 @@ vi.mock("./api.js", () => ({
|
||||
fetchFinanceSession: vi.fn(),
|
||||
grantFinanceCoinSellerRechargeOrder: vi.fn(),
|
||||
getFinanceCoinSellerRechargeExchangeRate: vi.fn(),
|
||||
getFinanceUSDTAddresses: vi.fn(),
|
||||
listFinanceCoinSellerRechargeOrders: vi.fn(),
|
||||
listFinanceRechargeDetails: vi.fn(),
|
||||
listFinanceRechargeRegions: vi.fn(),
|
||||
|
||||
@ -105,6 +105,23 @@ export async function getFinanceCoinSellerRechargeExchangeRate(appCode) {
|
||||
});
|
||||
}
|
||||
|
||||
export async function getFinanceUSDTAddresses(appCode) {
|
||||
const endpoint = API_ENDPOINTS.getFinanceUSDTAddresses;
|
||||
const data = await apiRequest(apiEndpointPath(API_OPERATIONS.getFinanceUSDTAddresses, { app_code: appCode }), {
|
||||
method: endpoint.method
|
||||
});
|
||||
return {
|
||||
appCode: stringValue(data?.appCode ?? appCode),
|
||||
items: listItems(data?.items)
|
||||
.map((item) => ({
|
||||
address: stringValue(item?.address),
|
||||
chain: stringValue(item?.chain).toUpperCase(),
|
||||
updatedAtMs: Number(item?.updatedAtMs || 0)
|
||||
}))
|
||||
.filter((item) => item.address && item.chain)
|
||||
};
|
||||
}
|
||||
|
||||
export async function replaceFinanceCoinSellerRechargeExchangeRate(appCode, payload) {
|
||||
const endpoint = API_ENDPOINTS.replaceFinanceCoinSellerRechargeExchangeRate;
|
||||
return apiRequest(apiEndpointPath(API_OPERATIONS.replaceFinanceCoinSellerRechargeExchangeRate, { app_code: appCode }), {
|
||||
|
||||
@ -6,6 +6,7 @@ import {
|
||||
fetchFinanceOptions,
|
||||
fetchFinanceSession,
|
||||
getFinanceCoinSellerRechargeExchangeRate,
|
||||
getFinanceUSDTAddresses,
|
||||
grantFinanceCoinSellerRechargeOrder,
|
||||
listFinanceCoinSellerRechargeOrders,
|
||||
listFinanceRechargeDetails,
|
||||
@ -174,6 +175,33 @@ test("finance coin seller quote and exchange rate APIs use generated endpoint pa
|
||||
expect(calls[2][1]?.method).toBe("PUT");
|
||||
});
|
||||
|
||||
test("finance USDT address API uses the selected app path and normalizes SQL rows", async () => {
|
||||
vi.stubGlobal(
|
||||
"fetch",
|
||||
vi.fn(async () =>
|
||||
new Response(
|
||||
JSON.stringify({
|
||||
code: 0,
|
||||
data: {
|
||||
appCode: "aslan",
|
||||
items: [{ address: "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", chain: "TRON", updatedAtMs: 123 }]
|
||||
}
|
||||
})
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
const result = await getFinanceUSDTAddresses("aslan");
|
||||
|
||||
const [url, init] = vi.mocked(fetch).mock.calls[0];
|
||||
expect(String(url)).toContain("/api/v1/admin/finance/usdt-addresses/aslan");
|
||||
expect(init?.method).toBe("GET");
|
||||
expect(result).toEqual({
|
||||
appCode: "aslan",
|
||||
items: [{ address: "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", chain: "TRON", updatedAtMs: 123 }]
|
||||
});
|
||||
});
|
||||
|
||||
test("finance recharge details query every app with app header and merge by recharge time", async () => {
|
||||
vi.stubGlobal(
|
||||
"fetch",
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import AddOutlined from "@mui/icons-material/AddOutlined";
|
||||
import AccountBalanceWalletOutlined from "@mui/icons-material/AccountBalanceWalletOutlined";
|
||||
import FactCheckOutlined from "@mui/icons-material/FactCheckOutlined";
|
||||
import PaidOutlined from "@mui/icons-material/PaidOutlined";
|
||||
import RefreshOutlined from "@mui/icons-material/RefreshOutlined";
|
||||
@ -33,6 +34,7 @@ import {
|
||||
import { FinanceCoinSellerRechargeCreateDialog } from "./FinanceCoinSellerRechargeCreateDialog.jsx";
|
||||
import { FinanceCoinSellerExchangeRateDialog } from "./FinanceCoinSellerExchangeRateDialog.jsx";
|
||||
import { FinanceCoinSellerGrantDialog } from "./FinanceCoinSellerGrantDialog.jsx";
|
||||
import { FinanceUSDTAddressDialog } from "./FinanceUSDTAddressDialog.jsx";
|
||||
|
||||
export function FinanceCoinSellerRechargeOrderList({
|
||||
actionLoading,
|
||||
@ -46,6 +48,7 @@ export function FinanceCoinSellerRechargeOrderList({
|
||||
loading,
|
||||
onCreate,
|
||||
onLoadExchangeRate,
|
||||
onLoadUSDTAddresses,
|
||||
onFiltersChange,
|
||||
onGrant,
|
||||
onReload,
|
||||
@ -62,6 +65,7 @@ export function FinanceCoinSellerRechargeOrderList({
|
||||
const [quoteError, setQuoteError] = useState("");
|
||||
const [quoteLoading, setQuoteLoading] = useState(false);
|
||||
const [rateConfigOpen, setRateConfigOpen] = useState(false);
|
||||
const [usdtAddressOpen, setUSDTAddressOpen] = useState(false);
|
||||
const [receiptVerification, setReceiptVerification] = useState(null);
|
||||
const [receiptLoading, setReceiptLoading] = useState(false);
|
||||
const [grantTarget, setGrantTarget] = useState(null);
|
||||
@ -281,6 +285,13 @@ export function FinanceCoinSellerRechargeOrderList({
|
||||
<Button startIcon={<RefreshOutlined fontSize="small" />} variant="outlined" onClick={onReload}>
|
||||
刷新
|
||||
</Button>
|
||||
<Button
|
||||
startIcon={<AccountBalanceWalletOutlined fontSize="small" />}
|
||||
variant="outlined"
|
||||
onClick={() => setUSDTAddressOpen(true)}
|
||||
>
|
||||
USDT 收款地址
|
||||
</Button>
|
||||
{canConfigureExchangeRate ? (
|
||||
<Button startIcon={<SettingsOutlined fontSize="small" />} variant="outlined" onClick={() => setRateConfigOpen(true)}>
|
||||
金币汇率配置
|
||||
@ -495,6 +506,13 @@ export function FinanceCoinSellerRechargeOrderList({
|
||||
onLoad={onLoadExchangeRate}
|
||||
onSave={onSaveExchangeRate}
|
||||
/>
|
||||
<FinanceUSDTAddressDialog
|
||||
apps={apps}
|
||||
initialAppCode={filters.appCode}
|
||||
open={usdtAddressOpen}
|
||||
onClose={() => setUSDTAddressOpen(false)}
|
||||
onLoad={onLoadUSDTAddresses}
|
||||
/>
|
||||
<FinanceCoinSellerGrantDialog
|
||||
loading={Boolean(grantTarget && actionLoading === `grant:${grantTarget.id}`)}
|
||||
order={grantTarget}
|
||||
|
||||
@ -274,6 +274,7 @@ function baseProps(overrides = {}) {
|
||||
loading: false,
|
||||
onCreate: vi.fn(),
|
||||
onLoadExchangeRate: vi.fn(async () => ({ appCode: "lalu", tiers: [], whitelist: [] })),
|
||||
onLoadUSDTAddresses: vi.fn(async () => ({ appCode: "lalu", items: [] })),
|
||||
onFiltersChange: vi.fn(),
|
||||
onGrant: vi.fn(),
|
||||
onReload: vi.fn(),
|
||||
|
||||
144
finance/src/components/FinanceUSDTAddressDialog.jsx
Normal file
144
finance/src/components/FinanceUSDTAddressDialog.jsx
Normal file
@ -0,0 +1,144 @@
|
||||
import ContentCopyOutlined from "@mui/icons-material/ContentCopyOutlined";
|
||||
import Alert from "@mui/material/Alert";
|
||||
import Button from "@mui/material/Button";
|
||||
import Dialog from "@mui/material/Dialog";
|
||||
import DialogActions from "@mui/material/DialogActions";
|
||||
import DialogContent from "@mui/material/DialogContent";
|
||||
import DialogTitle from "@mui/material/DialogTitle";
|
||||
import LinearProgress from "@mui/material/LinearProgress";
|
||||
import MenuItem from "@mui/material/MenuItem";
|
||||
import TextField from "@mui/material/TextField";
|
||||
import { useEffect, useState } from "react";
|
||||
import { AppIdentity } from "@/shared/ui/AppIdentity.jsx";
|
||||
import { formatTime } from "../format.js";
|
||||
|
||||
const EMPTY_DATA = { appCode: "", items: [] };
|
||||
|
||||
export function FinanceUSDTAddressDialog({ apps, initialAppCode, open, onClose, onLoad }) {
|
||||
const [appCode, setAppCode] = useState("");
|
||||
const [data, setData] = useState(EMPTY_DATA);
|
||||
const [error, setError] = useState("");
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [copiedChain, setCopiedChain] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
if (!open) {
|
||||
return;
|
||||
}
|
||||
setAppCode(initialAppCode || apps[0]?.appCode || "");
|
||||
setCopiedChain("");
|
||||
setError("");
|
||||
}, [apps, initialAppCode, open]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!open || !appCode) {
|
||||
setData(EMPTY_DATA);
|
||||
return undefined;
|
||||
}
|
||||
// App 切换会并发触发新请求;旧请求完成后必须被 active 门禁丢弃,不能把上一账套地址覆盖到当前选择。
|
||||
let active = true;
|
||||
setLoading(true);
|
||||
setError("");
|
||||
setCopiedChain("");
|
||||
onLoad(appCode)
|
||||
.then((result) => {
|
||||
if (active) {
|
||||
setData({ appCode, items: result?.items || [] });
|
||||
}
|
||||
})
|
||||
.catch((loadError) => {
|
||||
if (active) {
|
||||
setData({ appCode, items: [] });
|
||||
setError(loadError.message || "加载 USDT 收款地址失败");
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
if (active) {
|
||||
setLoading(false);
|
||||
}
|
||||
});
|
||||
return () => {
|
||||
active = false;
|
||||
};
|
||||
}, [appCode, onLoad, open]);
|
||||
|
||||
const copyAddress = async (item) => {
|
||||
try {
|
||||
if (!navigator.clipboard?.writeText) {
|
||||
throw new Error("clipboard unavailable");
|
||||
}
|
||||
// 复制值直接使用 API 返回的完整地址,不经过缩写或格式化,避免运营粘贴后链上校验失败。
|
||||
await navigator.clipboard.writeText(item.address);
|
||||
setCopiedChain(item.chain);
|
||||
setError("");
|
||||
} catch {
|
||||
setCopiedChain("");
|
||||
setError("复制失败,请手动选择地址复制");
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog fullWidth maxWidth="sm" open={open} onClose={loading ? undefined : onClose}>
|
||||
<DialogTitle>USDT 收款地址</DialogTitle>
|
||||
<DialogContent className="finance-usdt-address-dialog">
|
||||
{error ? <Alert severity="error">{error}</Alert> : null}
|
||||
<TextField
|
||||
disabled={loading || !apps.length}
|
||||
label="APP"
|
||||
select
|
||||
value={appCode}
|
||||
onChange={(event) => setAppCode(event.target.value)}
|
||||
>
|
||||
{apps.map((app) => (
|
||||
<MenuItem key={app.appCode} value={app.appCode}>
|
||||
<AppIdentity app={app} size="small" />
|
||||
</MenuItem>
|
||||
))}
|
||||
</TextField>
|
||||
{loading ? <LinearProgress aria-label="加载 USDT 收款地址" /> : null}
|
||||
{!loading && data.items.length ? (
|
||||
<div className="finance-usdt-address-list">
|
||||
{data.items.map((item) => (
|
||||
<section className="finance-usdt-address-item" key={item.chain}>
|
||||
<div className="finance-usdt-address-item__meta">
|
||||
<strong>{chainLabel(item.chain)}</strong>
|
||||
<small>{item.updatedAtMs ? `更新于 ${formatTime(item.updatedAtMs)}` : ""}</small>
|
||||
</div>
|
||||
<div className="finance-usdt-address-item__value">
|
||||
<code>{item.address}</code>
|
||||
<Button
|
||||
aria-label={`复制 ${item.chain} 地址`}
|
||||
size="small"
|
||||
startIcon={<ContentCopyOutlined fontSize="small" />}
|
||||
variant="outlined"
|
||||
onClick={() => copyAddress(item)}
|
||||
>
|
||||
{copiedChain === item.chain ? "已复制" : "复制"}
|
||||
</Button>
|
||||
</div>
|
||||
</section>
|
||||
))}
|
||||
</div>
|
||||
) : null}
|
||||
{!loading && appCode && !data.items.length && !error ? (
|
||||
<div className="finance-usdt-address-empty">当前 APP 未配置 USDT 收款地址</div>
|
||||
) : null}
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button disabled={loading} variant="outlined" onClick={onClose}>
|
||||
关闭
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
function chainLabel(chain) {
|
||||
if (chain === "TRON") {
|
||||
return "TRON · TRC20";
|
||||
}
|
||||
if (chain === "BSC") {
|
||||
return "BSC · BEP20";
|
||||
}
|
||||
return chain;
|
||||
}
|
||||
43
finance/src/components/FinanceUSDTAddressDialog.test.jsx
Normal file
43
finance/src/components/FinanceUSDTAddressDialog.test.jsx
Normal file
@ -0,0 +1,43 @@
|
||||
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
|
||||
import { afterEach, expect, test, vi } from "vitest";
|
||||
import { FinanceUSDTAddressDialog } from "./FinanceUSDTAddressDialog.jsx";
|
||||
|
||||
afterEach(() => {
|
||||
vi.unstubAllGlobals();
|
||||
});
|
||||
|
||||
test("loads the selected app USDT address and copies the exact SQL value", async () => {
|
||||
const writeText = vi.fn(async () => undefined);
|
||||
vi.stubGlobal("navigator", { clipboard: { writeText } });
|
||||
const onLoad = vi.fn(async (appCode) => ({
|
||||
appCode,
|
||||
items: [
|
||||
{
|
||||
address: "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
|
||||
chain: "TRON",
|
||||
updatedAtMs: 1760000000000,
|
||||
},
|
||||
],
|
||||
}));
|
||||
|
||||
render(
|
||||
<FinanceUSDTAddressDialog
|
||||
apps={[
|
||||
{ appCode: "lalu", appName: "Lalu" },
|
||||
{ appCode: "aslan", appName: "Aslan" },
|
||||
]}
|
||||
initialAppCode="aslan"
|
||||
open
|
||||
onClose={vi.fn()}
|
||||
onLoad={onLoad}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(await screen.findByText("TRON · TRC20")).toBeInTheDocument();
|
||||
expect(screen.getByText("TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t")).toBeInTheDocument();
|
||||
expect(onLoad).toHaveBeenCalledWith("aslan");
|
||||
|
||||
fireEvent.click(screen.getByRole("button", { name: "复制 TRON 地址" }));
|
||||
await waitFor(() => expect(writeText).toHaveBeenCalledWith("TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t"));
|
||||
expect(screen.getByRole("button", { name: "复制 TRON 地址" })).toHaveTextContent("已复制");
|
||||
});
|
||||
@ -1850,6 +1850,59 @@ a {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.finance-usdt-address-dialog {
|
||||
display: grid;
|
||||
gap: var(--space-4);
|
||||
padding-top: var(--space-2) !important;
|
||||
}
|
||||
|
||||
.finance-usdt-address-list {
|
||||
display: grid;
|
||||
gap: var(--space-3);
|
||||
}
|
||||
|
||||
.finance-usdt-address-item {
|
||||
display: grid;
|
||||
gap: var(--space-2);
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding-bottom: var(--space-3);
|
||||
}
|
||||
|
||||
.finance-usdt-address-item:last-child {
|
||||
border-bottom: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.finance-usdt-address-item__meta,
|
||||
.finance-usdt-address-item__value {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: var(--space-3);
|
||||
}
|
||||
|
||||
.finance-usdt-address-item__meta small {
|
||||
color: var(--text-tertiary);
|
||||
}
|
||||
|
||||
.finance-usdt-address-item__value code {
|
||||
min-width: 0;
|
||||
overflow-wrap: anywhere;
|
||||
color: var(--text-primary);
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.finance-usdt-address-item__value .MuiButton-root {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.finance-usdt-address-empty {
|
||||
color: var(--text-secondary);
|
||||
padding: var(--space-5) 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.finance-fchip {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
|
||||
@ -137,6 +137,7 @@ export const API_OPERATIONS = {
|
||||
getCumulativeRechargeRewardConfig: "getCumulativeRechargeRewardConfig",
|
||||
getFinanceCoinSellerRechargeExchangeRate: "getFinanceCoinSellerRechargeExchangeRate",
|
||||
getFinanceScope: "getFinanceScope",
|
||||
getFinanceUSDTAddresses: "getFinanceUSDTAddresses",
|
||||
getFirstRechargeRewardConfig: "getFirstRechargeRewardConfig",
|
||||
getHumanRoomRobotConfig: "getHumanRoomRobotConfig",
|
||||
getInviteActivityRewardConfig: "getInviteActivityRewardConfig",
|
||||
@ -1267,6 +1268,13 @@ export const API_ENDPOINTS: Record<ApiOperationId, ApiEndpoint> = {
|
||||
permission: "finance:view",
|
||||
permissions: ["finance:view"]
|
||||
},
|
||||
getFinanceUSDTAddresses: {
|
||||
method: "GET",
|
||||
operationId: API_OPERATIONS.getFinanceUSDTAddresses,
|
||||
path: "/v1/admin/finance/usdt-addresses/{app_code}",
|
||||
permission: "finance-order:coin-seller-recharge:view",
|
||||
permissions: ["finance-order:coin-seller-recharge:view"]
|
||||
},
|
||||
getFirstRechargeRewardConfig: {
|
||||
method: "GET",
|
||||
operationId: API_OPERATIONS.getFirstRechargeRewardConfig,
|
||||
|
||||
53
src/shared/api/generated/schema.d.ts
vendored
53
src/shared/api/generated/schema.d.ts
vendored
@ -2588,6 +2588,22 @@ export interface paths {
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/admin/finance/usdt-addresses/{app_code}": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get: operations["getFinanceUSDTAddresses"];
|
||||
put?: never;
|
||||
post?: never;
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/admin/finance/coin-seller-recharge-exchange-rates/{app_code}": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
@ -5424,6 +5440,9 @@ export interface components {
|
||||
ApiResponseFinanceCoinSellerRechargeExchangeRate: components["schemas"]["Envelope"] & {
|
||||
data?: components["schemas"]["FinanceCoinSellerRechargeExchangeRate"];
|
||||
};
|
||||
ApiResponseFinanceUSDTAddresses: components["schemas"]["Envelope"] & {
|
||||
data?: components["schemas"]["FinanceUSDTAddresses"];
|
||||
};
|
||||
ApiResponseFinanceCoinSellerRechargeReceiptVerification: components["schemas"]["Envelope"] & {
|
||||
data?: components["schemas"]["FinanceCoinSellerRechargeReceiptVerification"];
|
||||
};
|
||||
@ -6200,6 +6219,17 @@ export interface components {
|
||||
whitelist: components["schemas"]["FinanceCoinSellerRechargeExchangeRateWhitelist"][];
|
||||
updatedAtMs: number;
|
||||
};
|
||||
FinanceUSDTAddress: {
|
||||
/** @enum {string} */
|
||||
chain: "TRON" | "BSC";
|
||||
address: string;
|
||||
/** Format: int64 */
|
||||
updatedAtMs: number;
|
||||
};
|
||||
FinanceUSDTAddresses: {
|
||||
appCode: string;
|
||||
items: components["schemas"]["FinanceUSDTAddress"][];
|
||||
};
|
||||
FinanceCoinSellerRechargeExchangeRateInput: {
|
||||
tiers: {
|
||||
minUsdAmount: number;
|
||||
@ -7056,6 +7086,15 @@ export interface components {
|
||||
};
|
||||
};
|
||||
/** @description OK */
|
||||
FinanceUSDTAddressesResponse: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["ApiResponseFinanceUSDTAddresses"];
|
||||
};
|
||||
};
|
||||
/** @description OK */
|
||||
FinanceCoinSellerRechargeReceiptVerificationResponse: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
@ -10780,6 +10819,20 @@ export interface operations {
|
||||
200: components["responses"]["FinanceCoinSellerRechargeOrderResponse"];
|
||||
};
|
||||
};
|
||||
getFinanceUSDTAddresses: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
app_code: string;
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
200: components["responses"]["FinanceUSDTAddressesResponse"];
|
||||
};
|
||||
};
|
||||
getFinanceCoinSellerRechargeExchangeRate: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user