Browse Source

验证钱包地址

master
vee 4 years ago
parent
commit
a8e82f401e
  1. 4723
      package-lock.json
  2. 2
      package.json
  3. 29
      pages/menu/sendToken/addAddress/index.vue
  4. 63
      pages/menu/sendToken/addAddress2/index.vue
  5. 30
      pages/menu/sendToken/transfer/index.vue
  6. 2
      pages/menu/token/btc/index.css
  7. 53
      pages/menu/token/btc/index.vue
  8. 99
      utils/TokenUtil.js
  9. 87
      utils/WalletUtil.js
  10. 1
      utils/locales/en.js
  11. 1
      utils/locales/zh-F.js
  12. 1
      utils/locales/zh.js

4723
package-lock.json

File diff suppressed because it is too large

2
package.json

@ -21,10 +21,12 @@
"ethereumjs-tx": "^1.3.7",
"ethers": "^5.5.1",
"js-md5": "^0.7.3",
"js-sha256": "^0.9.0",
"node": "^17.1.0",
"tki-qrcode": "^0.1.6",
"tronweb": "^3.2.6",
"vue-clipboard2": "^0.3.3",
"wallet-address-validator": "^0.2.4",
"web3": "^1.3.4"
}
}

29
pages/menu/sendToken/addAddress/index.vue

@ -191,6 +191,16 @@
if (this.value == 'BTC') {
if(!this.$Token.validateBtc(this.bigAddress))
{
uni.showToast({
title: this.$t('index').addressFormatError,
icon: 'none',
duration: 1500
})
return
}
console.log(uni.getStorageSync('BTCAddressInfo'), 777)
if (uni.getStorageSync('BTCAddressInfo').length > 0) {
let btc = new Object;
@ -247,6 +257,16 @@
if (this.value == 'ETH') {
console.log(this.bigAddress,this.$Token.validateEth(this.bigAddress))
if(!this.$Token.validateEth(this.bigAddress))
{
uni.showToast({
title: this.$t('index').addressFormatError,
icon: 'none',
duration: 1500
})
return
}
console.log(uni.getStorageSync('ETHAddressInfo'), 777)
if (uni.getStorageSync('ETHAddressInfo').length > 0) {
let eth = new Object;
@ -306,6 +326,15 @@
}
if (this.value == 'TRX') {
if(!this.$Token.validateTrx(this.bigAddress))
{
uni.showToast({
title: this.$t('index').addressFormatError,
icon: 'none',
duration: 1500
})
return
}
console.log(uni.getStorageSync('TRXAddressInfo'), 777)
if (uni.getStorageSync('TRXAddressInfo').length > 0) {
let trx = new Object;

63
pages/menu/sendToken/addAddress2/index.vue

@ -202,6 +202,15 @@
if (this.info.coinList[0].name2 == 'TRX') {
this.$walletUtil.updateAddress(this.info.coinList[0].name2, this.value);
if (this.value == 'ETH') {
if(!this.$Token.validateEth(this.bigAddress))
{
uni.showToast({
title: this.$t('index').addressFormatError,
icon: 'none',
duration: 1500
})
return
}
this.gai = uni.getStorageSync('ETHAddressInfo')
this.gai2 = uni.getStorageSync('TRXAddressInfo')
var index = uni.getStorageSync('editIndex')
@ -296,6 +305,15 @@
if (this.info.coinList[0].name2 == 'ETH') {
if (this.value == 'TRX') {
if(!this.$Token.validateTrx(this.bigAddress))
{
uni.showToast({
title: this.$t('index').addressFormatError,
icon: 'none',
duration: 1500
})
return
}
this.gai = uni.getStorageSync('TRXAddressInfo')
this.gai2 = uni.getStorageSync('ETHAddressInfo')
var index = uni.getStorageSync('editIndex')
@ -329,6 +347,15 @@
})
}
if (this.value == 'ETH') {
if(!this.$Token.validateEth(this.bigAddress))
{
uni.showToast({
title: this.$t('index').addressFormatError,
icon: 'none',
duration: 1500
})
return
}
this.gai = uni.getStorageSync('ETHAddressInfo')
var index = uni.getStorageSync('editIndex')
let eth = new Object;
@ -354,6 +381,15 @@
}
if (this.value == 'BTC') {
if(!this.$Token.validateBtc(this.bigAddress))
{
uni.showToast({
title: this.$t('index').addressFormatError,
icon: 'none',
duration: 1500
})
return
}
this.gai = uni.getStorageSync('BTCAddressInfo')
this.gai2 = uni.getStorageSync('ETHAddressInfo')
var index = uni.getStorageSync('editIndex')
@ -391,6 +427,15 @@
if (this.info.coinList[0].name2 == 'BTC') {
if (this.value == 'TRX') {
if(!this.$Token.validateTrx(this.bigAddress))
{
uni.showToast({
title: this.$t('index').addressFormatError,
icon: 'none',
duration: 1500
})
return
}
this.gai = uni.getStorageSync('TRXAddressInfo')
this.gai2 = uni.getStorageSync('BTCAddressInfo')
@ -426,6 +471,15 @@
})
}
if (this.value == 'BTC') {
if(!this.$Token.validateBtc(this.bigAddress))
{
uni.showToast({
title: this.$t('index').addressFormatError,
icon: 'none',
duration: 1500
})
return
}
this.gai = uni.getStorageSync('BTCAddressInfo')
var index = uni.getStorageSync('editIndex')
let btc = new Object;
@ -451,6 +505,15 @@
}
if (this.value == 'ETH') {
if(!this.$Token.validateEth(this.bigAddress))
{
uni.showToast({
title: this.$t('index').addressFormatError,
icon: 'none',
duration: 1500
})
return
}
this.gai = uni.getStorageSync('ETHAddressInfo')
this.gai2 = uni.getStorageSync('BTCAddressInfo')
var index = uni.getStorageSync('editIndex')

30
pages/menu/sendToken/transfer/index.vue

@ -305,7 +305,7 @@
}, 1000)
} else {
console.log(err, 'cuowu')
that.showFinger = false;
that.showBottom = true;
uni.showToast({
@ -441,6 +441,15 @@
let that = this
if (this.coin.type === 'ETH') {
if(!this.$Token.validateEth(this.transInfoPass.toAddress))
{
uni.showToast({
title: this.$t('index').addressFormatError,
icon: 'none',
duration: 1500
})
return
}
this.$EthUtil.getGas().then((res) => {
console.log(res, 'ETH')
this.$EthUtil.getGas().then((res) => {
@ -451,6 +460,15 @@
})
} else if (this.coin.type === 'TRX') {
if(!this.$Token.validateTrx(this.transInfoPass.toAddress))
{
uni.showToast({
title: this.$t('index').addressFormatError,
icon: 'none',
duration: 1500
})
return
}
this.$TronUtil.getTransaction(this.transInfoPass.fromAddress,
this.transInfoPass.toAddress, this.transInfoPass.amount, this.transInfoPass.remark, this
.transInfoPass.contractAddress)
@ -477,6 +495,16 @@
})
})
}else if(this.coin.type === 'BTC'){
if(!this.$Token.validateBtc(this.transInfoPass.toAddress))
{
uni.showToast({
title: this.$t('index').addressFormatError,
icon: 'none',
duration: 1500
})
return
}
}
},

2
pages/menu/token/btc/index.css

@ -196,7 +196,7 @@
.main .money_con {
margin-top: 32rpx;
background-image: linear-gradient(to right, #6441CF, #877BFE);
height: 320rpx;
height: 354rpx;
padding: 40rpx 36rpx;
position: relative;
border-radius: 24rpx;

53
pages/menu/token/btc/index.vue

@ -16,9 +16,10 @@
{{coin.balance}} {{coin.name}}
</view>
<text class="text2">
{{currency=='USD'?'$ '+(!coin.balancePrice?0.00:coin.balancePrice):'¥ '+(!coin.balanceCnyPrice?0.00:coin.balanceCnyPrice)}}
{{currency=='USD'?'$ '+(!coin.balancePrice?0.00:coin.balancePrice):'¥ '+(!coin.balanceCnyPrice?0.00:coin.balanceCnyPrice)}}
</text>
</text>
</text>
<image src="../../../../static/tongyonh/ethereum.png" mode="aspectFit" class="img1"
v-if="coin.type=='ETH'&&!coin.contractAddress"></image>
@ -54,8 +55,9 @@
</u-tabs>
<u-empty :text="teee" mode="list" v-if="showInfo"></u-empty>
<scroll-view v-if="!showInfo":scroll-y="true" style="max-height: 880rpx;" @scrolltolower="scrollToPage" lower-threshold="50">
<view class="item1" v-for="(item,index) in trxs" @click="goDetail(item,index)">
<scroll-view v-if="!showInfo" :scroll-y="true" style="max-height: 880rpx;"
@scrolltolower="scrollToPage" lower-threshold="50">
<view class="item1" v-for="(item,index) in trxs" @click="goDetail(item,index)">
<view class="lef_con">
<image src="../../../../static/tongyonh/arrow-up-left.png" mode="aspectFit" class="img1"
v-if="item.type=='in'"></image>
@ -84,7 +86,7 @@
</image>
</view>
</view>
</scroll-view>
</scroll-view>
</view>
</view>
@ -113,12 +115,12 @@
export default {
data() {
return {
teee:this.$t('index').Nocontent,
teee: this.$t('index').Nocontent,
// address
trxs: [],
coin: {},
currency:'USD',
isNoData:false,
currency: 'USD',
isNoData: false,
showInfo: false,
list: [{
name: this.$t('index').All,
@ -172,7 +174,7 @@
})
},
goDetail(item, index) {
console.log(this.trxs[index],444444)
console.log(this.trxs[index], 444444)
uni.setStorageSync('transDetail', this.trxs[index])
uni.navigateTo({
url: '/pages/menu/transction/detail/index'
@ -191,9 +193,9 @@
}
this.current = index;
this.pageNum = 1;
this.trxs=[];
this.trxs = [];
this.getWalletInfo();
this.isNoData=false;
this.isNoData = false;
},
// onReachBottom() {
// if(!this.isNoData){
@ -204,30 +206,33 @@
// },
// scrollview onReachBottom
scrollToPage(){
if(!this.isNoData){
console.log(445454545)
this.pageNum=this.pageNum+1;
scrollToPage() {
if (!this.isNoData) {
console.log(445454545)
this.pageNum = this.pageNum + 1;
this.getWalletInfo();
}
},
async getWalletInfo() {
let params = {
address: this.coin.address,
chainName: this.coin.type,
contract: this.coin.contractAddress,
type: this.coin.tokenType,
pageNum: this.pageNum,
pageSize: this.pageSize
}
console.log(params)
if (this.type === 'send') {
params.fromAddress = this.coin.address;
} else if (this.type === 'receive') {
params.toAddress = this.coin.address
}
const response = await this.$api.getChainDataList(params)
if (response.data.rows.length == 0 ) {
this.isNoData=true;
if(this.pageNum == 1){
if (response.data.rows.length == 0) {
this.isNoData = true;
if (this.pageNum == 1) {
this.showInfo = true;
}
@ -235,18 +240,20 @@
this.showInfo = false;
}
this.trxs=this.trxs.concat(response.data.rows);
console.log(this.trxs,787878)
this.trxs = this.trxs.concat(response.data.rows);
console.log(this.trxs, 787878)
}
},
onLoad() {
this.coin = uni.getStorageSync('coin');
this.change(0);
let currency=uni.getStorageSync('currency');
if(currency){
this.currency=currency;
let currency = uni.getStorageSync('currency');
if (currency) {
this.currency = currency;
}
var a=this.$Token.validateTrx('TWgEuYRuXgwfDbcfzZsteu5w5dq1nFR35w');
console.log(a,123465)
}
};

99
utils/TokenUtil.js

@ -5,7 +5,8 @@ const util = require('ethereumjs-util')
const ethers = require('ethers')
const bitcoin = require('bitcoinjs-lib')
let Tx = require('ethereumjs-tx');
const WAValidator = require('wallet-address-validator');
const sha256= require('js-sha256').sha256;
@ -175,30 +176,82 @@ let token = {
}
return wallrtInfo;
},
validateBtc: function(address) {
let valid = WAValidator.validate(address, 'BTC');
console.log(valid, 'BTC')
return valid;
},
validateEth: function(address) {
let valid = WAValidator.validate(address, 'ETH');
console.log(valid, 'eth')
return valid;
},
validateTrx: function(base58Str) {
if (typeof(base58Str) !== 'string')
return false;
// creatingWallets: function() {
// let mnemonic = this.generateMnemonic();
// let eth = this.generateEth(mnemonic);
// let tron = this.generateTron(mnemonic);
// let btc = this.generateBtc(mnemonic);
// // let privateKey = this.getPrivateKey(mnemonic);
// return {
// 'eth': eth,
// 'tron': tron,
// 'btc': btc,
// 'mnemonic': mnemonic,
// // 'privateKey': privateKey
// };
// },
creatingWallets: function() {
let mnemonic = this.generateMnemonic();
// let privateKey = this.getPrivateKey(mnemonic);
return {
if (base58Str.length !== 34)
return false;
'mnemonic': mnemonic,
// 'privateKey': privateKey
};
let address = this.decode58(base58Str);
if (address.length !== 25)
return false;
if (address[0] !== 0x41)
return false;
// const checkSum = address.slice(21);
// address = address.slice(0, 21);
// const hash0 = sha256.sha256(address);
// const hash1 = sha256.sha256(hash0);
// const checkSum1 = hash1.slice(0, 4);
// console.log(hash1)
// console.log(address,1111)
// console.log(checkSum1)
// console.log(checkSum)
// if (checkSum[0] == checkSum1[0] && checkSum[1] == checkSum1[1] && checkSum[2] ==
// checkSum1[2] && checkSum[3] == checkSum1[3]
// ) {
return true
// }
// return false;
},
decode58: function (string) {
var ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
var ALPHABET_MAP = {};
var BASE = 58;
for (var i = 0; i < ALPHABET.length; i++) {
ALPHABET_MAP[ALPHABET.charAt(i)] = i;
}
if (string.length === 0) return [];
var i,
j,
bytes = [0];
for (i = 0; i < string.length; i++) {
var c = string[i];
// c是不是ALPHABET_MAP的key
if (!(c in ALPHABET_MAP)) throw new Error('Non-base58 character');
for (j = 0; j < bytes.length; j++) bytes[j] *= BASE;
bytes[0] += ALPHABET_MAP[c];
var carry = 0;
for (j = 0; j < bytes.length; ++j) {
bytes[j] += carry;
carry = bytes[j] >> 8;
// 0xff --> 11111111
bytes[j] &= 0xff;
}
while (carry) {
bytes.push(carry & 0xff);
carry >>= 8;
}
}
// deal with leading zeros
for (i = 0; string[i] === '1' && i < string.length - 1; i++) bytes.push(0);
return bytes.reverse();
}
}
export default token

87
utils/WalletUtil.js

@ -67,7 +67,7 @@ let WalletUtil = {
walletInfo.BTC[0].privateKey = btc.privateKey;
walletInfo.BTC[0].address = btc.address;
walletInfo.BTC[0].ellipsisAddress = walletInfo.BTC[0].address.substring(0, 6) + '...' + walletInfo.BTC[
0].address.substring(walletInfo.BTC[0].address.length-6,
0].address.substring(walletInfo.BTC[0].address.length - 6,
walletInfo.BTC[0].address.length)
let eth = TokenUtil.generateEth(mnemonic)
walletInfo.ETH[0].password = password;
@ -88,14 +88,14 @@ let WalletUtil = {
updateWalletName: function(type, address, name) {
let walletInfo = uni.getStorageSync('walletInfo');
let walletList = walletInfo[type];
let wallet =uni.getStorageSync('wallet');
let wallet = uni.getStorageSync('wallet');
for (var k = 0, length = walletList.length; k < length; k++) {
if (walletList[k].address === address) {
walletList[k].name = name
if(wallet.address==walletList[k].address){
wallet.name=name
uni.setStorageSync('wallet',wallet);
}
if (wallet.address == walletList[k].address) {
wallet.name = name
uni.setStorageSync('wallet', wallet);
}
break;
}
}
@ -164,7 +164,7 @@ let WalletUtil = {
wallet.password = password;
wallet.privateKey = walletdec.privateKey;
wallet.address = walletdec.address;
wallet.ellipsisAddress = wallet.address.substring(0, 6) + '...' + wallet.address.substring(
wallet.ellipsisAddress = wallet.address.substring(0, 6) + '...' + wallet.address.substring(
wallet.address.length - 6,
wallet.address.length);
walletInfo[type].push(wallet);
@ -181,7 +181,8 @@ let WalletUtil = {
walletList = walletInfo[type]
for (var k = 0, length = walletList.length; k < length; k++) {
let address = walletList[k].address;
walletList[k].ellipsisAddress = address.substring(0, 6) + '...' + address.substring(address.length - 6,
walletList[k].ellipsisAddress = address.substring(0, 6) + '...' + address.substring(address
.length - 6,
address.length)
}
} else {
@ -207,7 +208,8 @@ let WalletUtil = {
console.log()
for (var k = 0, length = walletList.length; k < length; k++) {
if (walletList[k].address == address) {
walletList[k].ellipsisAddress = address.substring(0, 6) + '...' + address.substring(address.length - 6,
walletList[k].ellipsisAddress = address.substring(0, 6) + '...' + address.substring(address
.length - 6,
address.length)
uni.setStorageSync('wallet', walletList[k]);
break;
@ -225,7 +227,7 @@ let WalletUtil = {
params.coinName = 'USDT';
const usdtU = await api.getCoinRate(params);
wallet.totalBalancePrice = 0
wallet.totalBalanceCnyPrice=0
wallet.totalBalanceCnyPrice = 0
console.log(usdtU, 8888)
switch (wallet.type) {
case 'BTC':
@ -233,17 +235,20 @@ let WalletUtil = {
wallet.balance = await BtcUtil.getBalance(wallet.address)
break;
case 'ETH':
console.log("进来ETH",wallet.balance )
console.log("进来ETH", wallet.balance)
wallet.balance = await EthUtil.getBalance(wallet.address);
wallet.balance=wallet.balance>0?wallet.balance.toFixed(6):wallet.balance
console.log("进来ETH",wallet.balance )
wallet.balance = wallet.balance > 0 ? wallet.balance.toFixed(6) : wallet.balance
console.log("进来ETH", wallet.balance)
for (let i = 1; i < wallet.coinList.length; i++) {
wallet.coinList[i].balance = await EthUtil.getTokenBalance(wallet.address, wallet.coinList[i].contractAddress);
console.log("进来ETH",wallet.coinList[i].balance)
wallet.coinList[i].balance = await EthUtil.getTokenBalance(wallet.address, wallet.coinList[
i].contractAddress);
console.log("进来ETH", wallet.coinList[i].balance)
}
wallet.totalBalancePrice = wallet.coinList[1].balancePrice?wallet.coinList[1].balancePrice:0;
wallet.totalBalanceCnyPrice=wallet.coinList[1].balanceCnyPrice?wallet.coinList[1].balanceCnyPrice:0;
wallet.totalBalancePrice = wallet.coinList[1].balancePrice ? wallet.coinList[1].balancePrice :
0;
wallet.totalBalanceCnyPrice = wallet.coinList[1].balanceCnyPrice ? wallet.coinList[1]
.balanceCnyPrice : 0;
wallet.coinList[1].balancePrice = (wallet
.coinList[1].balance * usdtU.data.priceInUsd).toFixed(2);
wallet.coinList[1].balanceCnyPrice = (wallet
@ -255,56 +260,58 @@ let WalletUtil = {
params.address = wallet.address;
params.chainName = wallet.type;
const tronCoin = await api.getBalance(params);
var newList=[];
var newList = [];
newList.push(wallet.coinList[0])
newList.push(wallet.coinList[1])
newList[0].tokenType = "trc10"
newList[0].contractAddress='_';
for (let i = 1; i < tronCoin.data.length; i++) {
if (tronCoin.data[i].tokenAbbr === 'USDT') {
newList[1].balance = (Number(tronCoin.data[i].balance) / Math.pow(10, tronCoin
.data[i].tokenDecimal));
newList[1].tokenType = "trc20"
newList[1].balanceCnyPrice = (newList[1].balance * usdtU.data.priceCny).toFixed(2);
newList[1].balancePrice = (newList[1].balance * usdtU.data.priceInUsd).toFixed(2);
wallet.totalBalancePrice = newList[1].balancePrice
wallet.totalBalanceCnyPrice=newList[1].balanceCnyPrice
wallet.totalBalanceCnyPrice = newList[1].balanceCnyPrice
} else {
console.log(Number(tronCoin.data[i].balance) / Math.pow(10, tronCoin.data[i]
.tokenDecimal))
var coin = {
name: tronCoin.data[i].tokenAbbr,
xname: tronCoin.data[i].tokenName,
balance: (Number(tronCoin.data[i].balance) / Math.pow(10, tronCoin.data[i]
.tokenDecimal)),
icon: tronCoin.data[i].tokenLogo,
name: tronCoin.data[i].tokenAbbr,
xname: tronCoin.data[i].tokenName,
balance: (Number(tronCoin.data[i].balance) / Math.pow(10, tronCoin.data[i]
.tokenDecimal)),
icon: tronCoin.data[i].tokenLogo,
contractAddress: tronCoin.data[i].tokenId,
tokenType: tronCoin.data[i].tokenType
}
}
if (tronCoin.data[i].tokenType === 'trc20') {
coin.contractAddress = tronCoin.data[i].tokenId
} else {
coin.contractAddress = tronCoin.data[i].owner_address
}
newList.push(coin)
newList.push(coin)
}
}
wallet.coinList=newList;
wallet.coinList = newList;
break;
}
wallet.ellipsisAddress=wallet.address.substring(0, 6) + '...' + wallet.address.substring(
wallet.address.length - 6,
wallet.address.length);
wallet.ellipsisAddress = wallet.address.substring(0, 6) + '...' + wallet.address.substring(
wallet.address.length - 6,
wallet.address.length);
wallet.balancePrice = (wallet.balance * mainCoinP.data.priceInUsd).toFixed(2);
wallet.balanceCnyPrice = (wallet.balance * mainCoinP.data.priceCny).toFixed(2);
wallet.totalBalancePrice=(Number(wallet.totalBalancePrice)+Number(wallet.balancePrice)).toFixed(2);
wallet.totalBalanceCnyPrice=(Number(wallet.totalBalanceCnyPrice)+Number(wallet.balanceCnyPrice)).toFixed(2);
console.log("wallet.balancePrice",Number(wallet.totalBalancePrice))
console.log("wallet.balanceCnyPrice",wallet.totalBalancePrice)
wallet.totalBalancePrice = (Number(wallet.totalBalancePrice) + Number(wallet.balancePrice)).toFixed(2);
wallet.totalBalanceCnyPrice = (Number(wallet.totalBalanceCnyPrice) + Number(wallet.balanceCnyPrice))
.toFixed(2);
console.log("wallet.balancePrice", Number(wallet.totalBalancePrice))
console.log("wallet.balanceCnyPrice", wallet.totalBalancePrice)
wallet.coinList[0].balance = wallet.balance
wallet.coinList[0].balancePrice = wallet.balancePrice
wallet.coinList[0].balanceCnyPrice = wallet.balanceCnyPrice
uni.setStorageSync('wallet',wallet);
uni.setStorageSync('wallet', wallet);
const walletInfo = uni.getStorageSync('walletInfo');
for (var k = 0, length = walletInfo[wallet.type].length; k < length; k++) {
if (walletInfo[wallet.type][k].address === wallet.address) {

1
utils/locales/en.js

@ -169,6 +169,7 @@ export default {
fingerprintidentification: 'This device does not support fingerprint identification',
notequipped: 'This device is not equipped with a password lock screen and cannot use fingerprint identification',
oninthesetting: 'There is no fingerprint entered in this device. Please turn it on in the setting',
addressFormatError:'Address format error',
// Add Token
AddToken: 'Add Token',
Hotassets: 'Hot assets',

1
utils/locales/zh-F.js

@ -168,6 +168,7 @@ export default {
fingerprintidentification: '此設備不支持指紋識別',
notequipped: '此設備未配備密碼鎖定荧幕,無法使用指紋識別',
oninthesetting: '此設備中沒有輸入指紋。 請在設定中打開它',
addressFormatError:'地址格式錯誤',
// Add Token
AddToken: '添加代幣',
Hotassets: '熱門資產',

1
utils/locales/zh.js

@ -166,6 +166,7 @@ export default {
fingerprintidentification: '此设备不支持指纹识别',
notequipped: '此设备未配备密码锁定屏幕,无法使用指纹识别',
oninthesetting: '此设备中没有输入指纹。请在设置中打开它',
addressFormatError:'地址格式错误',
// Add Token
AddToken: '添加代币',
Hotassets: '热门资产',

Loading…
Cancel
Save