Commit 94f8e1e2 by haojie

1

parent 67d43f9a
......@@ -10,10 +10,20 @@
class InscriptionController extends Controller
{
// 根据钱包地址获取铭文列表
public function wallet(Request $request){
public function wallet(Request $request)
{
$address = $request->input('address');
$result = app(InscriptionService::class)->getWalletInscription($address);
return $this->success($result);
}
// 获取外部网站的市场铭文列表
public function outMarket(Request $request)
{
$tick = $request->input('tick');
$type = $request->input('type');
$result = app(InscriptionService::class)->getMarketInscription();
return $this->success($result);
}
}
<?php
namespace App\Http\Controllers\Web;
use App\Http\Controllers\Controller;
use Inertia\Inertia;
class TradeController extends Controller
{
public function index()
{
// 铭文交易页面
$title = '铭文交易';
return Inertia::render('Trade/index', [
'info' => [
'title' => $title,
],
]);
}
public function shelves()
{
// 铭文上架
$title = '铭文上架';
return Inertia::render('InscriptionShelves/index', [
'info' => [
'title' => $title,
],
]);
}
}
<?php
namespace App\Service;
use App\Service\RequestService;
use Illuminate\Support\Facades\Log;
class InscriptionService{
class InscriptionService
{
// 铭文请求地址
public const InscriptionDomain = 'https://eth-script-indexer-eca25c4cf43b.herokuapp.com';
public function getWalletInscription($address = ''){
if(!$address){
public function getWalletInscription($address = '')
{
if (!$address) {
return false;
}
$url =self::InscriptionDomain . "/api/ethscriptions/owned_by/$address";
$url = self::InscriptionDomain . "/api/ethscriptions/owned_by/$address";
return app(RequestService::class)->get($url);
}
}
\ No newline at end of file
/**
* 获取外部网站的市场铭文列表
*/
public function getOutMarketInscription()
{
}
}
<?php
namespace App\Service;
class TradeService
{
// 市场页面交易列表的筛选条件
}
......@@ -11,6 +11,7 @@
"@vitejs/plugin-vue-jsx": "^3.0.1",
"@vue/server-renderer": "^3.3.4",
"axios": "^1.1.2",
"ethers": "^5.7.2",
"laravel-vite-plugin": "^0.7.2",
"less": "^4.1.3",
"lodash": "^4.17.19",
......@@ -20,6 +21,7 @@
"vite": "^4.0.0",
"vite-plugin-compression": "^0.5.1",
"vite-svg-loader": "^4.0.0",
"vue": "^3.2.36"
"vue": "^3.2.36",
"vuex": "^4.0.2"
}
}
<template>
<Layout> 铭文市场 </Layout>
<Head :title="info.title" />
<Layout>
<Navbar title="ERC-20- Ethscription" content=""></Navbar>
<div class="inscription-market-content">
<div class="inscription-market-table-head">
<!-- input -->
<CustomInput
v-model="inputValue"
className="inscription-market-input"
:clear="true"
@search="onSearch"
>
</CustomInput>
<CustomGroupButton
:list="groupBtns"
parentHeight="36px"
childHeight="26px"
:bordered="false"
v-model="currentBtn"
@change="groupButtonChange"
></CustomGroupButton>
</div>
<div class="inscription-market-table">
<CustomTable
:data="tableList"
:columns="columns"
:loading="loading"
></CustomTable>
<div class="pagination-box">
<CustomPagination
:total="total"
:pageNum="pageNum"
:pageSize="pageSize"
@pageChange="pageChange"
></CustomPagination>
</div>
</div>
</div>
</Layout>
</template>
<script lang="ts" setup>
<script lang="tsx" setup>
import Layout from "@/layout/index.vue";
import { Head } from "@inertiajs/vue3";
import Navbar from "@/components/navbar.vue";
import CustomTable from "@/components/table.vue";
import CustomInput from "@/components/input/index.vue";
import { reactive, ref } from "vue";
import CustomGroupButton from "@/components/groupButton.vue";
import TipsSvg from "@/assets/svg/content/tips.svg";
import CustomTooltip from "@/components/tooltip.vue";
import CustomPagination from "@/components/pagination.vue";
import { getUserInscriptionList } from "@/utils/api/external";
import { showMessage, isDev, getMask, timeFormatSeconds } from "@/utils/tool";
import { test_wallet_list } from "@/constants/testData";
defineProps({ info: Object });
/**
* 按钮组的value
*/
const groupBtn_all = "all";
const groupBtn_cast = "cast";
const groupBtn_send = "send";
// 搜索框的值
const inputValue = ref("");
// 当前选中的按钮
const currentBtn = ref(groupBtn_all);
// 按钮组
const groupBtns = [
{
// all
label: "所有",
value: groupBtn_all,
},
{
// 两个地址相同的
label: "进行中",
value: groupBtn_cast,
},
{
// 两个地址不同的
label: "已完成",
value: groupBtn_send,
},
];
const pageNum = ref(1);
const pageSize = ref(10);
const total = ref(0);
const loading = ref(false);
// 接口返回的列表
const allTableList = reactive({
[groupBtn_all]: [],
[groupBtn_cast]: [],
[groupBtn_send]: [],
});
// 页面展示的列表
const tableList = ref([]);
// 上次搜索的地址
const oldAddress = ref("");
// 按钮组变化
const groupButtonChange = (value: string) => {
arrayPag(value);
};
// 打开hash链接
const openLink = (value) => {
if (!value) {
showMessage("没有hash");
return;
}
const url = "https://etherscan.io/tx/" + value;
window.open(url);
};
const columns = [
{
colKey: "name",
title: "名称",
align: "center",
className: "font700",
width: "10%",
},
{
colKey: "number",
title: "部署时间",
align: "center",
className: "font700",
width: "10%",
},
{
colKey: "creator",
title: "总供应量",
align: "center",
className: "public-style font700",
},
{
colKey: "current_owner",
title: "每分钟限制",
align: "center",
className: "public-style font700",
},
{
colKey: "creation_timestamp",
title: "持有者",
align: "center",
className: "public-style font700",
},
{
colKey: "content_uri",
title: "状态",
align: "center",
cell: (h, { col, row }) => (
<div>
<CustomTooltip content={row[col.colKey]}>
<span class="tip-span">查看</span>
</CustomTooltip>
</div>
),
},
{
colKey: "creation_timestamp",
title: "操作",
align: "center",
className: "public-style font700",
},
];
// 过滤出对应条件的列表
const getCurrentList = (list: any[]) => {
// 两个地址相同的
allTableList[groupBtn_cast] = list.filter(
(item: any) => item.current_owner === item.creator
);
// 两个地址不同的
allTableList[groupBtn_send] = list.filter(
(item: any) => item.current_owner !== item.creator
);
};
const listResult = (list: any[]) => {
// 分别过滤出对应的列表
list.forEach((item: any) => {
item.creator = getMask(item.creator);
item.current_owner = getMask(item.current_owner);
item.creation_timestamp = timeFormatSeconds(item.creation_timestamp);
// 过滤出名称和数量
const match = item.content_uri.match(/{.*}/);
if (match) {
const jsonStr = match[0];
const jsonObject = JSON.parse(jsonStr);
item.name = jsonObject.tick;
item.number = jsonObject.amt;
} else {
console.log("content_uri格式错误");
console.log(item.content_uri);
}
});
// 全部数据
allTableList[groupBtn_all] = list;
getCurrentList(list);
total.value = list.length;
//分页
arrayPag();
};
const getList = async () => {
try {
if (!inputValue.value) {
showMessage("未输入钱包地址");
return;
}
if (isDev()) {
// 本地环境
listResult(test_wallet_list);
} else {
loading.value = true;
const res: any = await getUserInscriptionList(inputValue.value);
if (res) {
oldAddress.value = inputValue.value;
let list = JSON.parse(res);
if (list.length) {
listResult(list);
}
}
loading.value = false;
}
} catch (e) {
console.log(e);
loading.value = false;
}
};
const arrayPag = (value?: string) => {
// 根据页数和分页大小、当前按钮--获取对应的数据
const start = (pageNum.value - 1) * pageSize.value;
tableList.value = allTableList[value ? value : currentBtn.value].slice(
start,
pageSize.value + start
);
// 改变total
total.value = allTableList[value ? value : currentBtn.value].length;
};
// 开始搜索
const onSearch = () => {
pageNum.value = 1;
getList();
};
// 页数变化
const pageChange = (value: number) => {
pageNum.value = value;
arrayPag();
};
</script>
<style lang="less"></style>
<style lang="less">
.inscription-market-content {
max-width: 1430px;
flex: 1;
border-radius: 8px;
background: white;
padding: 20px;
margin: 0 auto;
display: flex;
flex-direction: column;
.inscription-market-table-head {
display: flex;
justify-content: space-between;
.inscription-market-input {
width: 247px;
height: 40px;
}
}
.inscription-market-table {
margin-top: 20px;
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
.table-tip-label {
display: flex;
justify-content: center;
align-items: center;
.tip {
margin-left: 6px;
cursor: pointer;
display: flex;
align-items: center;
}
}
.tip-span {
font-weight: 700;
color: #0075ff;
}
.open-link {
cursor: pointer;
}
.pagination-box {
margin-top: 20px;
}
}
}
</style>
<template>
<t-dialog
class="custom-inscription-market-dialog"
v-model:visible="visible"
attach="body"
placement="center"
:closeBtn="false"
:footer="false"
@Close="OnClose"
>
<template #header> </template>
<template #body>
<div class="inscription-market-dialog-content">
<SuccessSvg></SuccessSvg>
<div class="label1">可铸造</div>
<div class="label2">该铭文ID未被铸造</div>
</div>
</template>
</t-dialog>
</template>
<script lang="ts" setup>
import { ref, watch } from "vue";
import SuccessSvg from "@/assets/svg/content/success.svg";
const props = withDefaults(
defineProps<{
modelValue: boolean;
delay?: number;
}>(),
{
delay: 2000,
}
);
const emit = defineEmits(["update:modelValue"]);
const visible = ref(props.modelValue);
watch(
() => props.modelValue,
(v) => {
visible.value = v;
if (v) {
closeDialog();
}
}
);
watch(
() => visible.value,
(v) => {
emit("update:modelValue", v);
}
);
const OnClose = () => {
//
};
const closeDialog = () => {
// 关闭弹窗
setTimeout(() => {
visible.value = false;
}, props.delay);
};
</script>
<style lang="less">
.custom-inscription-market-dialog {
.t-dialog {
width: 412px;
height: 264px;
border: 1px solid #b1b1b1;
}
.t-dialog__body {
padding: 0;
}
.inscription-market-dialog-content {
height: 180px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-evenly;
color: #000000;
.label1,
.label2 {
font-size: 28px;
line-height: 28px;
}
}
}
</style>
......@@ -9,13 +9,16 @@
</div>
<div class="inscription-search-content">
<div class="inscription-search-table">
<CustomTable
:data="tableList"
:columns="columns"
:loading="loading"
></CustomTable>
<template v-if="!dialog_visible">
<CustomTable
:data="tableList"
:columns="columns"
:loading="loading"
></CustomTable>
</template>
</div>
</div>
<CastableDialog v-model="dialog_visible" :delay="2000"></CastableDialog>
</Layout>
</template>
......@@ -31,6 +34,7 @@ import CustomTooltip from "@/components/tooltip.vue";
import { inscriptionWasCast } from "@/utils/api/external";
import { showMessage, isDev, getMask, timeFormatSeconds } from "@/utils/tool";
import { test_wallet_list } from "@/constants/testData";
import CastableDialog from "./components/CastableDialog.vue";
defineProps({ info: Object });
/**
* 按钮组的value
......@@ -40,6 +44,9 @@ const groupBtn_all = "all";
// 搜索框的值
const inputValue = ref("");
// 弹窗状态
const dialog_visible = ref(false);
const pageNum = ref(1);
const pageSize = ref(10);
const loading = ref(false);
......@@ -155,6 +162,21 @@ const listResult = (list: any[]) => {
allTableList[groupBtn_all] = list;
};
// 判断result的结果
const resultEvent = (res: any) => {
if (res && res.result) {
// 已经铸造--显示表格
dialog_visible.value = false;
listResult([res.ethscription]);
tableList.value = allTableList[groupBtn_all];
} else {
// 无效
dialog_visible.value = true;
tableList.value = [];
allTableList[groupBtn_all] = [];
}
};
const getList = async () => {
try {
if (!inputValue.value) {
......@@ -164,7 +186,8 @@ const getList = async () => {
if (isDev()) {
// 本地环境
let res = {
result: true,
// true 已铸造
result: false,
ethscription: {
transaction_hash:
"0xa34274bb32c63fa0b19b1bbf6629582b4e53fb1e1a867bb906f92e921e02e884",
......@@ -182,19 +205,14 @@ const getList = async () => {
min_block_confirmations: 14454,
},
};
// 判断参数
if (res.ethscription.valid_data_uri) {
// 有效
listResult([res.ethscription]);
tableList.value = allTableList[groupBtn_all];
} else {
// 无效
}
resultEvent(res);
} else {
const res: any = await inscriptionWasCast(inputValue.value);
if (res) {
console.log(res);
let res: any = await inscriptionWasCast(inputValue.value);
if (typeof res === "string") {
res = JSON.parse(res);
}
// 返回结果
resultEvent(res);
}
} catch (e) {
console.log(e);
......
<template>
<div class="">2</div>
</template>
<script lang="ts" setup></script>
<style lang="less"></style>
<template>
<Head :title="info.title" />
<Layout>
<Navbar
title="使用您优选的付款方式买卖ERC-20"
content="立即使用您的首选支付方式通过C2C交易ERC20,尽享安全交易"
></Navbar>
<div class="inscription-shelves-content">
<div class="shelves-label">我的资产</div>
<CustomTabs :tabList="tabList"></CustomTabs>
</div>
</Layout>
</template>
<script lang="tsx" setup>
import Layout from "@/layout/index.vue";
import { Head } from "@inertiajs/vue3";
import Navbar from "@/components/navbar.vue";
import CustomTable from "@/components/table.vue";
import CustomInput from "@/components/input/index.vue";
import { reactive, ref } from "vue";
import CustomGroupButton from "@/components/groupButton.vue";
import TipsSvg from "@/assets/svg/content/tips.svg";
import CustomTooltip from "@/components/tooltip.vue";
import CustomPagination from "@/components/pagination.vue";
import { getUserInscriptionList } from "@/utils/api/external";
import { showMessage, isDev, getMask, timeFormatSeconds } from "@/utils/tool";
import { test_wallet_list } from "@/constants/testData";
import CustomTabs from "@/components/tabs.vue";
import MyInscription from "./components/MyInscription.vue";
import TradeLog from "./components/TradeLog.vue";
defineProps({ info: Object });
// 请求接口放这里
const tabList = [
{
label: "我的铭文",
value: "inscription",
panel: () => <MyInscription></MyInscription>,
},
{
label: "我的订单",
value: "order",
panel: () => <TradeLog></TradeLog>,
},
];
</script>
<style lang="less">
.inscription-shelves-content {
max-width: 1224px;
flex: 1;
border-radius: 8px;
background: white;
padding: 20px;
margin: 0 auto;
display: flex;
flex-direction: column;
.shelves-label {
font-size: 31px;
font-weight: 600;
color: #000000;
margin: 20px 0;
}
}
</style>
<template>
<div class="start-trade-tabpanel">
<div class="trade-filter-box">
<div class="trade-filter">
<span>价格:</span>
<CustomSelect
:options="options"
v-model="selectValue"
:autoWidth="true"
:borderless="true"
></CustomSelect>
</div>
</div>
<t-row class="trade-card-box">
<template v-for="item in tradeList.list" :key="item.id">
<t-col :span="1.5">
<div class="trade-card">
<span class="id">#{{ item.id }}</span>
<div class="total">
<img class="logo" :src="imgs.eth" alt="" />
<span>{{ item.total_cast }}</span>
<span>{{ item.tick }}</span>
</div>
<div class="pairs">
<span class="num">{{ item.num_1 }}</span>
<span>{{ item.pairs }}</span>
</div>
<div class="value">
<!-- 价值 -->
${{ item.value }}
</div>
<div class="chain-value">
<div class="token-num">
{{ item.currency_num }}{{ item.currency }}
</div>
<div class="token-amount">
${{ item.currency_amount }}
</div>
</div>
<t-button class="trade-buy-now">立即购买</t-button>
</div>
</t-col>
</template>
</t-row>
</div>
</template>
<script lang="ts" setup>
import CustomSelect from "@/components/select.vue";
import { ref, reactive } from "vue";
const imgs = {
eth: new URL("../../../assets/svg/trade/eth2.svg", import.meta.url).href,
};
// 当前select
const selectValue = ref("asc");
const options = [
{
label: "从低到高",
value: "asc",
},
{
label: "从高到低",
value: "desc",
},
];
// 生成测试数据
const testData = () => {
let list = [];
for (let i = 0; i < 31; i++) {
list.push({
id: "13465971",
total_cast: 1000,
tick: "eths",
num_1: "1",
pairs: "eths/usdt",
value: "0.3",
currency: "eth",
currency_num: "0.3",
currency_amount: "300",
});
}
return list;
};
const tradeList = reactive({
list: testData(),
});
</script>
<style lang="less">
.start-trade-tabpanel {
.trade-filter-box {
text-align: right;
.trade-filter {
margin: 20px 0;
display: inline-flex;
align-items: center;
justify-content: flex-end;
white-space: nowrap;
& > :last-child {
margin-left: 12px;
}
}
}
.trade-card-box {
margin-left: -40px !important;
margin-top: -40px;
display: flex;
justify-content: space-between;
& > * {
margin-left: 40px;
margin-top: 40px;
}
.trade-card {
width: 184px;
border-radius: 12px;
border: 1px solid #dbdbdb;
padding: 12px;
box-sizing: border-box;
.id {
height: 16px;
border-radius: 50px;
background: #f2f2f2;
font-size: 12px;
color: #3d3d3d;
line-height: 16px;
display: inline-block;
padding: 0 12px;
}
.total {
font-size: 16px;
font-weight: 600;
display: flex;
justify-content: center;
align-items: center;
margin: 6px 0;
& > * {
padding: 0 4px;
}
.logo {
width: 16px;
height: 16px;
}
}
.pairs {
font-size: 11px;
color: #929292;
display: flex;
justify-content: center;
align-items: center;
margin-top: 12px;
& > * {
padding: 0 2px;
}
.num {
color: #000000;
}
}
.value {
color: #929292;
font-size: 11px;
text-align: center;
}
.chain-value {
background: #f9f9f9;
height: 48px;
border-radius: 8px;
margin: 12px 0;
font-size: 11px;
padding: 8px;
box-sizing: border-box;
.token-num {
line-height: 16px;
color: #000000;
}
.token-amount {
line-height: 16px;
color: #929292;
}
}
.trade-buy-now {
width: 100%;
height: 36px;
border-radius: 60px;
background-color: #ffffff;
border: 1px solid #dbdbdb;
--ripple-color: #ddd !important;
color: #000000;
}
}
}
}
</style>
<template>
<div class="custom-trade-header-box">
<div class="custom-trade-header">
<div class="trade-header-info1">
<span class="info-logo">
<EthSvg></EthSvg>
</span>
<div class="info">
<div class="info-row-one">
<div class="tick-label">ETHS</div>
<div class="detail-label">币种详情></div>
<t-button
class="top-inscription-button"
@click="onShelves"
>上架铭文</t-button
>
</div>
<div>
<div class="cast-number">
<span>已铸造:262,626,081,725,358</span>
<span>总供应量:2,100,000,000,000,000</span>
</div>
<div class="info-progress">
<CustomProgress
:num="20"
width="63%"
:strokeWidth="'4px'"
:label="false"
></CustomProgress>
</div>
</div>
</div>
</div>
<div class="trade-header-info2">
<div class="transaction-value">
<div>
<Eth2Svg></Eth2Svg>
<span class="num">9.1918</span>
</div>
<div>总交易额</div>
</div>
<div class="line"></div>
<div class="transaction-value">
<div>
<Eth2Svg></Eth2Svg>
<span class="num">9.1918</span>
</div>
<div>24 小时交易额</div>
</div>
<div class="line"></div>
<div class="transaction-value">
<div>
<span class="num">0.000025 sats</span>
</div>
<div>价格</div>
</div>
<div class="line"></div>
<div class="transaction-value">
<div>
<span class="num">9.1918</span>
</div>
<div>交易笔数</div>
</div>
<div class="line"></div>
<div class="transaction-value">
<div>
<span class="num">9.1918</span>
</div>
<div>持有人</div>
</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import EthSvg from "@/assets/svg/trade/eth.svg";
import Eth2Svg from "@/assets/svg/trade/eth2.svg";
import CustomProgress from "@/components/progress.vue";
import router from "@/constants/router";
// 上架按钮
const onShelves = () => {
window.location.href = router.shelves;
};
</script>
<style lang="less">
.custom-trade-header-box {
position: relative;
&::before {
content: "";
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 50px;
background-color: #1e2329;
}
.custom-trade-header {
width: 100%;
max-width: 1224px;
margin: 0 auto;
.trade-header-info1 {
display: flex;
width: 100%;
.info-logo {
position: relative;
}
.info {
flex: 1;
padding-left: 12px;
& > :nth-child(2) {
margin-top: 14px;
font-size: 11px;
color: #3d3d3d;
.cast-number {
display: flex;
justify-content: space-between;
width: 62%;
}
.info-progress {
margin-top: 12px;
}
}
.info-row-one {
display: flex;
align-items: center;
justify-content: space-between;
& > :nth-child(2) {
margin-left: 20%;
}
}
.tick-label {
font-size: 31px;
font-weight: 600;
color: #e9e9e9;
position: relative;
}
.detail-label {
font-size: 14px;
color: #929292;
position: relative;
}
.top-inscription-button {
border: 1px solid #000000;
background-color: #ffffff;
border-radius: 52px;
font-size: 14px;
color: #000000;
height: 42px;
padding: 0 20px;
--ripple-color: #ddd !important;
}
}
}
.trade-header-info2 {
display: flex;
flex-wrap: wrap;
row-gap: 20px;
padding-left: 20px;
margin-top: 12px;
margin-left: -50px;
& > * {
margin-left: 50px;
}
.transaction-value {
& > :first-child {
font-size: 24px;
font-weight: 600;
color: #000000;
display: flex;
align-items: center;
.num {
margin-left: 6px;
}
}
& > :last-child {
font-size: 14px;
font-weight: 400;
color: #929292;
margin-top: 6px;
text-align: center;
}
}
.line {
height: 40px;
width: 1px;
background: #ebebeb;
}
}
}
}
</style>
<template>
<div class="">2</div>
</template>
<script lang="ts" setup></script>
<style lang="less"></style>
<template>
<Head :title="info.title" />
<Layout>
<Navbar
title="使用您优选的付款方式买卖ERC-20"
content="立即使用您的首选支付方式通过C2C交易ERC20,尽享安全交易"
></Navbar>
<TradeHeader></TradeHeader>
<div class="inscription-trade-content">
<CustomTabs :tabList="tabList"></CustomTabs>
</div>
</Layout>
</template>
<script lang="tsx" setup>
import Layout from "@/layout/index.vue";
import { Head } from "@inertiajs/vue3";
import Navbar from "@/components/navbar.vue";
import CustomTable from "@/components/table.vue";
import CustomInput from "@/components/input/index.vue";
import { reactive, ref } from "vue";
import CustomGroupButton from "@/components/groupButton.vue";
import TipsSvg from "@/assets/svg/content/tips.svg";
import CustomTooltip from "@/components/tooltip.vue";
import CustomPagination from "@/components/pagination.vue";
import { getUserInscriptionList } from "@/utils/api/external";
import { showMessage, isDev, getMask, timeFormatSeconds } from "@/utils/tool";
import { test_wallet_list } from "@/constants/testData";
import TradeHeader from "./components/TradeHeader.vue";
import CustomTabs from "@/components/tabs.vue";
import MarketVue from "./components/Market.vue";
import TradeLog from "./components/TradeLog.vue";
defineProps({ info: Object });
// 请求接口放这里
const tabList = [
{
label: "市场",
value: "market",
panel: () => <MarketVue></MarketVue>,
},
{
label: "交易动态",
value: "trade_log",
panel: () => <TradeLog></TradeLog>,
},
];
</script>
<style lang="less">
.inscription-trade-box {
height: 130px;
display: flex;
justify-content: center;
align-items: center;
}
.inscription-trade-content {
max-width: 1224px;
flex: 1;
border-radius: 8px;
background: white;
padding: 20px;
margin: 0 auto;
display: flex;
flex-direction: column;
}
</style>
......@@ -5,6 +5,7 @@ import "../css/app.css";
import { createApp, createSSRApp, h } from "vue";
import { createInertiaApp } from "@inertiajs/vue3";
import Tdesign from "./utils/tdesign";
import store from "./store";
createInertiaApp({
id: "app",
......@@ -17,6 +18,7 @@ createInertiaApp({
const app = createApp({ render: () => h(App, props) });
app.use(plugin);
app.use(Tdesign);
app.use(store);
app.mount(el);
},
});
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_54_3775)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M15.2307 20.4027C18.2316 19.2481 20.4577 16.5321 20.9137 13.25H16.9718C16.8248 16.1102 16.1791 18.638 15.2307 20.4027ZM14.473 13.25C14.2952 17.3518 13.2556 20.5 11.9998 20.5C10.744 20.5 9.70447 17.3518 9.52667 13.25H14.473ZM14.473 10.75H9.52667C9.70447 6.64821 10.744 3.5 11.9998 3.5C13.2556 3.5 14.2952 6.64821 14.473 10.75ZM16.9718 10.75H20.9137C20.4577 7.46786 18.2316 4.75191 15.2307 3.59731C16.1791 5.36198 16.8248 7.88979 16.9718 10.75ZM7.03566 10.75C7.18282 7.88774 7.82928 5.35836 8.77882 3.59353C5.77291 4.74598 3.54249 7.46427 3.08594 10.75H7.03566ZM7.03566 13.25H3.08594C3.54249 16.5357 5.77291 19.254 8.77882 20.4065C7.82928 18.6416 7.18282 16.1123 7.03566 13.25Z" fill="#EAECEF"/>
</g>
<defs>
<clipPath id="clip0_54_3775">
<rect width="24" height="24" fill="white"/>
</clipPath>
</defs>
</svg>
<svg width="60" height="60" viewBox="0 0 60 60" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M30 0C13.5 0 0 13.5 0 30C0 46.5 13.5 60 30 60C46.5 60 60 46.5 60 30C60 13.5 46.5 0 30 0ZM44.1818 24.1364L28.5 39.6818C27.9545 40.2273 27.2727 40.5 26.5909 40.5C25.9091 40.5 25.2273 40.2273 24.6818 39.6818L15.8182 30.8182C14.7273 29.7273 14.7273 28.0909 15.8182 27C16.9091 25.9091 18.5455 25.9091 19.6364 27L26.5909 33.9545L40.3636 20.1818C41.4546 19.0909 43.0909 19.0909 44.1818 20.1818C45.2727 21.2727 45.2727 23.0455 44.1818 24.1364Z" fill="#31BD65"/>
</svg>
<svg width="29" height="29" viewBox="0 0 29 29" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<rect width="29" height="29" rx="14.5" fill="url(#pattern0)"/>
<defs>
<pattern id="pattern0" patternContentUnits="objectBoundingBox" width="1" height="1">
<use xlink:href="#image0_82_2151" transform="translate(-0.157895 -0.157895) scale(0.0263158)"/>
</pattern>
<image id="image0_82_2151" width="50" height="50" xlink:href="data:image/png;base64,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"/>
</defs>
</svg>
<svg width="116" height="116" viewBox="0 0 116 116" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_52_5920)">
<rect x="10" y="6" width="96" height="96" rx="48" fill="white"/>
<rect x="13" y="9" width="90" height="90" rx="45" fill="#E9E9E9"/>
<g clip-path="url(#clip0_52_5920)">
<path d="M57.9928 20.25L57.5532 21.7023V63.8458L57.9928 64.2724L78.1184 52.709L57.9928 20.25Z" fill="#343434"/>
<path d="M57.9933 20.25L37.8677 52.709L57.9933 64.2725V43.8173V20.25Z" fill="#8C8C8C"/>
<path d="M57.9933 67.9765L57.7456 68.27V83.2825L57.9933 83.9857L78.131 56.4189L57.9933 67.9765Z" fill="#3C3C3B"/>
<path d="M57.9933 83.9855V67.9762L37.8677 56.4186L57.9933 83.9855Z" fill="#8C8C8C"/>
<path d="M57.9927 64.2724L78.118 52.7092L57.9927 43.8175V64.2724Z" fill="#141414"/>
<path d="M37.8677 52.709L57.993 64.2723V43.8173L37.8677 52.709Z" fill="#393939"/>
</g>
<rect x="11.5" y="7.5" width="93" height="93" rx="46.5" stroke="white" stroke-width="3"/>
</g>
<defs>
<filter id="filter0_d_52_5920" x="0" y="0" width="116" height="116" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.2 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_52_5920"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_52_5920" result="shape"/>
</filter>
<clipPath id="clip0_52_5920">
<rect width="40.2632" height="63.75" fill="white" transform="translate(37.8677 20.25)"/>
</clipPath>
</defs>
</svg>
<svg width="29" height="28" viewBox="0 0 29 28" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.779785" width="28" height="28" rx="14" fill="#E9E9E9"/>
<g clip-path="url(#clip0_54_3120)">
<path d="M14.7774 3.5L14.6406 3.95184V17.0631L14.7774 17.1958L21.0387 13.5984L14.7774 3.5Z" fill="#343434"/>
<path d="M14.7779 3.5L8.5166 13.5984L14.7779 17.1959V10.8321V3.5Z" fill="#8C8C8C"/>
<path d="M14.7777 18.3482L14.7007 18.4396V23.1101L14.7777 23.3289L21.0428 14.7526L14.7777 18.3482Z" fill="#3C3C3B"/>
<path d="M14.7779 23.3288V18.3481L8.5166 14.7524L14.7779 23.3288Z" fill="#8C8C8C"/>
<path d="M14.7773 17.1959L21.0385 13.5984L14.7773 10.8321V17.1959Z" fill="#141414"/>
<path d="M8.5166 13.5983L14.7778 17.1958V10.832L8.5166 13.5983Z" fill="#393939"/>
</g>
<defs>
<clipPath id="clip0_54_3120">
<rect width="12.5263" height="19.8333" fill="white" transform="translate(8.5166 3.5)"/>
</clipPath>
</defs>
</svg>
// @import "@/style/color.less";
.t-button.connect-wallet-button {
width: 87px;
height: 32px;
background-color: #003470;
color: #ffffff;
border-radius: 4px;
font-size: 14px;
border-color: #003470;
}
.t-button.connect-success-button {
height: 39px;
background-color: transparent;
border-radius: 30px;
border: 1px solid #ffffff;
color: #ffffff;
font-size: 16px;
.t-button__text {
padding-left: 12px;
}
&:hover {
background-color: transparent;
border-color: #ffffff;
--ripple-color: none !important;
}
}
.wallect-connect-success-popup {
width: 168px;
.t-popup__content {
background-color: #1e2329;
border: 1px solid #ffffff;
border-radius: 8px;
.item-box {
text-align: center;
font-size: 16px;
color: white;
cursor: pointer;
}
}
}
// @media (max-device-width: @max-device-width-1) {
// .custom-connect-fox-dialog {
// .t-dialog {
// width: 90vw;
// .fox-wallect-list-li {
// width: 100% !important;
// }
// }
// }
// }
import { computed, defineComponent, onMounted, reactive, ref } from "vue";
import "./index.less";
import { Connect_Fox_tp_wallet, Connect_BK_wallet } from "@/utils/ethers";
import { showMessage, setLocal, getLocal } from "@/utils/tool";
import WalletConnectedSvg from "@/assets/svg/content/wallectConneted.svg";
import { userWalletKey } from "@/constants/token";
import { useStore } from "vuex";
export default defineComponent({
setup(props) {
const store = useStore();
// 本地存储的key
const localKey = userWalletKey;
const loading = ref(false);
// 弹出层选项列表
const popupChoseList = [
{
label: "我的资产",
value: "assets",
},
];
// 用户地址
const userAddress = computed(() => store.getters["user/address"]);
// 存储
const setWalletLocalData = () => {
const { address, maskAddress, type } = userAddress.value;
setLocal(
localKey,
{
address: address,
maskAddress: maskAddress,
type: type,
},
"session"
);
};
// 用户取消连接
const cancelConnection = (res: any) => {
if (res && res.code == 4001) {
// 清空本地的数据
setLocal(localKey, "", "session");
}
};
// 连接小狐狸或tp
const getConnectFox = async (tooltip: boolean) => {
// 这里是用户主动连接,临时存储到本地,刷新页面时自动赋值
let eth: any = window;
try {
// 连接小狐狸或tp
let address_list = await Connect_Fox_tp_wallet();
if (address_list.address) {
store.commit("user/setAddress", {
address: address_list.address,
maskAddress: address_list.MaskAddress,
type: "fox",
});
// 记录本次连接的钱包
setWalletLocalData();
}
if (tooltip) {
showMessage("连接成功", "success");
}
} catch (e: any) {
if (tooltip) {
if (e.code == -32002) {
showMessage("连接请求已存在");
return;
}
showMessage("连接失败", "error");
}
cancelConnection(e);
console.log(e);
}
};
const CustConnectBk = async (tooltip: boolean) => {
try {
let address_list: any = await Connect_BK_wallet();
if (address_list.address) {
store.commit("user/setAddress", {
address: address_list.address,
maskAddress: address_list.MaskAddress,
type: "bk",
});
// 记录本次连接的钱包
setWalletLocalData();
if (tooltip) {
showMessage("连接成功", "success");
}
}
} catch (e) {
cancelConnection(e);
console.log(e);
}
};
// 连接钱包
const ToConnectWallet = async (value: string = "fox") => {
try {
loading.value = false;
if (value == "fox") {
// 连接钱包--主动连接--需要提示文字
console.log("连接小狐狸");
getConnectFox(true);
} else if (value == "bk") {
// 连接bk
console.log("连接bk");
CustConnectBk(true);
}
} catch (e) {
console.log(e);
loading.value = false;
}
};
// 自动连接--
const custConnect = () => {
let ConnectFox = userAddress.value.type;
if (ConnectFox == "fox") {
// 不显示提示文字
getConnectFox(false);
} else if (ConnectFox == "bk") {
// 连接bk
CustConnectBk(false);
} else {
console.log("不连接");
}
};
onMounted(() => {
custConnect();
});
// 弹出层
const walletConnectedContent = () => {
return (
<>
{popupChoseList.map((item: any) => (
<div class="item-box">{item.label}</div>
))}
</>
);
};
return () => (
<>
{userAddress.value.address ? (
<t-popup
trigger="click"
overlayClassName="wallect-connect-success-popup"
v-slots={{
content: walletConnectedContent,
}}
>
<t-button
class="connect-success-button"
v-slots={{
icon: () => (
<WalletConnectedSvg></WalletConnectedSvg>
),
}}
>
{userAddress.value.maskAddress}
</t-button>
</t-popup>
) : (
<t-button
class="connect-wallet-button"
onClick={ToConnectWallet.bind(this, "fox")}
>
连接钱包
</t-button>
)}
</>
);
},
});
<template>
<div class="custom-group-buttons">
<div
class="custom-group-buttons"
:style="{
border: needBorder(),
height: parentHeight,
}"
>
<div
class="group-button"
:class="{
'group-button_active': item.value === currentBtn,
}"
:style="{
height: childHeight,
}"
v-for="item in list"
:key="item.value"
@click="change(item.value)"
......@@ -21,13 +30,35 @@ const props = withDefaults(
defineProps<{
modelValue: string;
list: any[];
bordered?: boolean | string;
parentHeight?: string;
childHeight?: string;
}>(),
{}
{
bordered: true,
parentHeight: "40px",
childHeight: "32px",
}
);
const emit = defineEmits(["update:modelValue", "change"]);
const currentBtn = ref(props.modelValue);
// 是否需要边框
const needBorder = () => {
const { bordered } = props;
if (typeof bordered === "boolean") {
if (bordered) {
return "1px solid #dedede";
}
return "none";
} else if (typeof bordered === "string") {
return bordered;
}
console.warn("groupbutton border type error");
return "";
};
const change = (value: string) => {
if (currentBtn.value !== value) {
emit("change", value);
......@@ -55,20 +86,18 @@ watch(
<style lang="less">
.custom-group-buttons {
height: 40px;
border-radius: 4px;
border: 1px solid #dedede;
display: inline-flex;
align-items: center;
background: #f5f5f5;
padding: 0 6px;
box-sizing: border-box;
.group-button {
background: transparent;
border-radius: 4px;
font-size: 13px;
font-weight: 400;
transition: all 0.2s;
height: 32px;
width: 105px;
display: flex;
align-items: center;
......
<template>
<div class="custom-input-global">
<div class="custom-input-global" :class="[className]">
<div
class="custom-input-box"
:class="{ 'custom-input-error': ruleError.status }"
......@@ -89,6 +89,7 @@ const props = withDefaults(
selectList?: any;
searchIcon?: boolean;
clear?: boolean;
className?: string;
}>(),
{
// 输入框类型
......@@ -100,6 +101,7 @@ const props = withDefaults(
disabled: false,
searchIcon: true,
clear: false,
className: "",
}
);
const emit = defineEmits([
......@@ -284,7 +286,7 @@ watch(
}
.input-clear-icon {
cursor: pointer;
padding-right: 12px;
margin-right: 12px;
}
.input-search-icon {
padding-right: 16px;
......
<template>
<div
:style="{
width: width,
}"
>
<t-progress
:percentage="num"
:color="color"
:label="label"
:strokeWidth="strokeWidth"
:trackColor="trackColor"
/>
</div>
</template>
<script lang="ts" setup>
import { Progress as TProgress } from "tdesign-vue-next";
const props = withDefaults(
defineProps<{
num?: number;
width?: string;
color?: string;
label?: string | boolean;
strokeWidth?: string | number;
trackColor?: string;
}>(),
{
num: 0,
width: "200px",
color: "#31BD65",
label: true,
strokeWidth: "6px",
trackColor: "#EBEBEB",
}
);
</script>
<style lang="less"></style>
<template>
<t-select
v-model="value"
:options="options"
:placeholder="placeholder"
:autoWidth="autoWidth"
:borderless="borderless"
></t-select>
</template>
<script lang="tsx" setup>
import { Select as TSelect } from "tdesign-vue-next";
import { ref, watch } from "vue";
const props = withDefaults(
defineProps<{
modelValue: string;
options: any[];
placeholder?: string;
autoWidth?: boolean;
borderless?: boolean;
}>(),
{
placeholder: "",
autoWidth: false,
borderless: false,
}
);
const emit = defineEmits(["update:modelValue"]);
const value = ref(props.modelValue);
watch(
() => props.modelValue,
(v) => {
value.value = v;
}
);
watch(
() => value.value,
(v) => {
emit("update:modelValue", v);
}
);
</script>
<style lang="less"></style>
<template>
<t-tabs v-model="tab" :list="tabList" class="custom-reset-tabs" />
</template>
<script lang="tsx" setup>
import { Tabs as TTabs } from "tdesign-vue-next";
import { ref } from "vue";
const props = withDefaults(
defineProps<{
tabList: any[];
}>(),
{}
);
const tab = ref(props.tabList[0].value);
</script>
<style lang="less">
.custom-reset-tabs {
.t-tabs__nav-item-wrapper {
font-size: 16px;
font-weight: 600;
}
.t-is-active {
color: black;
}
.t-tabs__bar.t-is-top {
background: black;
}
}
</style>
// 所有的路由
export default {
trade: "/trade",
// 铭文上架页面
shelves: "/inscription/shelves",
};
// 邮箱正则
export const emailReg = /^\w{3,}(\.\w+)*@[A-z0-9]+(\.[A-z]{2,8}){1,2}$/;
// 用户钱包地址key
export const userWalletKey = "ConnectFox";
......@@ -12,7 +12,8 @@
</div>
</div>
<div class="layout-head-right">
<!-- <t-button class="logout" @click="logout"> 退出 </t-button> -->
<ConnectWallet></ConnectWallet>
<LanguageSvg></LanguageSvg>
</div>
</div>
</template>
......@@ -22,6 +23,8 @@ import { ref } from "@vue/reactivity";
import { computed } from "@vue/runtime-core";
import { MessagePlugin } from "tdesign-vue-next";
import { getRoute } from "@/utils/tool";
import ConnectWallet from "@/components/connectWallet";
import LanguageSvg from "@/assets/svg/content/language.svg";
const { pathname } = getRoute();
const currentBtn = ref(pathname);
const btns = [
......@@ -42,20 +45,7 @@ const btns = [
path: "/inscription/search",
},
];
const logout = async () => {
// try {
// let res: any = await useLogout();
// if (res.code == 0) {
// // 清空账户列表
// MessagePlugin.success("退出成功");
// router.replace({
// path: "/",
// });
// }
// } catch (e) {
// console.log(e);
// }
};
const changeBtn = (item: any) => {
currentBtn.value = item.path;
// 路由跳转
......@@ -86,6 +76,7 @@ const changeBtn = (item: any) => {
color: #eaecef;
transition: all 0.1s;
cursor: pointer;
white-space: nowrap;
}
.active {
color: #fd1753;
......@@ -96,11 +87,8 @@ const changeBtn = (item: any) => {
}
.layout-head-right {
.da();
.logout {
background: #fd1753;
border: none;
margin-right: 20px;
--ripple-color: #fd6053 !important;
& > * {
margin-right: 40px;
}
}
}
......
import { createStore } from "vuex";
import user from "./modules/user";
export const store = createStore({
modules: {
user,
},
});
export default store;
const state = {
language: '',
};
type StateType = typeof state;
const mutations = {
setLang(state: StateType, info: string) {
state.language = info;
// 设置html 属性
document.documentElement.setAttribute('lang', info);
},
};
const getters = {
getLang: (state: StateType) => {
return state.language;
},
};
const actions = {};
export default {
namespaced: true,
state,
mutations,
actions,
getters,
};
import { getLocal } from "@/utils/tool";
import { userWalletKey } from "@/constants/token";
// 获取本地数据
const getWalletLocalData = (
key: "type" | "address" | "maskAddress" = "type"
) => {
// 格式错误时,清空本地数据
// setLocal(localKey, "", "session");
const res = getLocal(userWalletKey, "session");
if (res) {
return res[key];
}
return "";
};
interface MyState {
address: {
address: string;
maskAddress: string;
type: string;
};
}
// 定义的state初始值
const state: MyState = {
address: {
address: getWalletLocalData("address"),
maskAddress: getWalletLocalData("maskAddress"),
type: getWalletLocalData("type"),
},
};
type StateType = typeof state;
const mutations = {
setAddress(state: StateType, obj: any) {
state.address.address = obj.address;
state.address.maskAddress = obj.maskAddress;
if (obj.type) {
state.address.type = obj.type;
}
},
};
const getters = {
address: (state: StateType) => {
return state.address;
},
};
const actions = {
async login({ commit }: any, loginInfo: any) {
//
},
};
export default {
namespaced: true,
state,
mutations,
actions,
getters,
};
[
{
"constant": true,
"inputs": [],
"name": "name",
"outputs": [{ "name": "", "type": "string" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [{ "name": "_upgradedAddress", "type": "address" }],
"name": "deprecate",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{ "name": "_spender", "type": "address" },
{ "name": "_value", "type": "uint256" }
],
"name": "approve",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "deprecated",
"outputs": [{ "name": "", "type": "bool" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [{ "name": "_evilUser", "type": "address" }],
"name": "addBlackList",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "totalSupply",
"outputs": [{ "name": "", "type": "uint256" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{ "name": "_from", "type": "address" },
{ "name": "_to", "type": "address" },
{ "name": "_value", "type": "uint256" }
],
"name": "transferFrom",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "upgradedAddress",
"outputs": [{ "name": "", "type": "address" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [{ "name": "", "type": "address" }],
"name": "balances",
"outputs": [{ "name": "", "type": "uint256" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "decimals",
"outputs": [{ "name": "", "type": "uint256" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "maximumFee",
"outputs": [{ "name": "", "type": "uint256" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "_totalSupply",
"outputs": [{ "name": "", "type": "uint256" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [],
"name": "unpause",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [{ "name": "_maker", "type": "address" }],
"name": "getBlackListStatus",
"outputs": [{ "name": "", "type": "bool" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{ "name": "", "type": "address" },
{ "name": "", "type": "address" }
],
"name": "allowed",
"outputs": [{ "name": "", "type": "uint256" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "paused",
"outputs": [{ "name": "", "type": "bool" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [{ "name": "who", "type": "address" }],
"name": "balanceOf",
"outputs": [{ "name": "", "type": "uint256" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [],
"name": "pause",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "getOwner",
"outputs": [{ "name": "", "type": "address" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "owner",
"outputs": [{ "name": "", "type": "address" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "symbol",
"outputs": [{ "name": "", "type": "string" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{ "name": "_to", "type": "address" },
{ "name": "_value", "type": "uint256" }
],
"name": "transfer",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{ "name": "newBasisPoints", "type": "uint256" },
{ "name": "newMaxFee", "type": "uint256" }
],
"name": "setParams",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [{ "name": "amount", "type": "uint256" }],
"name": "issue",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [{ "name": "amount", "type": "uint256" }],
"name": "redeem",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [
{ "name": "_owner", "type": "address" },
{ "name": "_spender", "type": "address" }
],
"name": "allowance",
"outputs": [{ "name": "remaining", "type": "uint256" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "basisPointsRate",
"outputs": [{ "name": "", "type": "uint256" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [{ "name": "", "type": "address" }],
"name": "isBlackListed",
"outputs": [{ "name": "", "type": "bool" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [{ "name": "_clearedUser", "type": "address" }],
"name": "removeBlackList",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "MAX_UINT",
"outputs": [{ "name": "", "type": "uint256" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [{ "name": "newOwner", "type": "address" }],
"name": "transferOwnership",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [{ "name": "_blackListedUser", "type": "address" }],
"name": "destroyBlackFunds",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{ "name": "_initialSupply", "type": "uint256" },
{ "name": "_name", "type": "string" },
{ "name": "_symbol", "type": "string" },
{ "name": "_decimals", "type": "uint256" }
],
"payable": false,
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [{ "indexed": false, "name": "amount", "type": "uint256" }],
"name": "Issue",
"type": "event"
},
{
"anonymous": false,
"inputs": [{ "indexed": false, "name": "amount", "type": "uint256" }],
"name": "Redeem",
"type": "event"
},
{
"anonymous": false,
"inputs": [{ "indexed": false, "name": "newAddress", "type": "address" }],
"name": "Deprecate",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{ "indexed": false, "name": "feeBasisPoints", "type": "uint256" },
{ "indexed": false, "name": "maxFee", "type": "uint256" }
],
"name": "Params",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{ "indexed": false, "name": "_blackListedUser", "type": "address" },
{ "indexed": false, "name": "_balance", "type": "uint256" }
],
"name": "DestroyedBlackFunds",
"type": "event"
},
{
"anonymous": false,
"inputs": [{ "indexed": false, "name": "_user", "type": "address" }],
"name": "AddedBlackList",
"type": "event"
},
{
"anonymous": false,
"inputs": [{ "indexed": false, "name": "_user", "type": "address" }],
"name": "RemovedBlackList",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{ "indexed": true, "name": "owner", "type": "address" },
{ "indexed": true, "name": "spender", "type": "address" },
{ "indexed": false, "name": "value", "type": "uint256" }
],
"name": "Approval",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{ "indexed": true, "name": "from", "type": "address" },
{ "indexed": true, "name": "to", "type": "address" },
{ "indexed": false, "name": "value", "type": "uint256" }
],
"name": "Transfer",
"type": "event"
},
{ "anonymous": false, "inputs": [], "name": "Pause", "type": "event" },
{ "anonymous": false, "inputs": [], "name": "Unpause", "type": "event" }
]
export const centerbnox = 1;
import { ethers } from 'ethers';
import { MessagePlugin } from 'tdesign-vue-next';
import ERC20ABI from './ERC20ABI.json';
let eth: any = window;
// 发起交易--小狐狸-tp支付
export const fox_EtherPay = async (to: string, price: number) => {
try {
// 代币地址
const USDT = '0xc5a25e92e691635BDd6DF2e904633Dc3152360cD';
const provider = new ethers.providers.Web3Provider(eth.ethereum);
const signer = new ethers.providers.Web3Provider(eth.ethereum).getSigner();
const tokenContract = new ethers.Contract(USDT, ERC20ABI, provider);
// const tokenBalance = await tokenContract.balanceOf(
// eth.ethereum.selectedAddress
// );
// const tokenAmount = ethers.utils.parseUnits(
// ethers.utils.formatUnits(price),
// 18
// );
let tokenAmount = price * Math.pow(10, 18);
let big_num = BigInt(Math.floor(tokenAmount));
console.log(big_num);
const tokenSigner = tokenContract.connect(signer);
const transaction = await tokenSigner.transfer(to, big_num);
console.log(transaction);
console.log(transaction.hash);
return transaction.hash ? transaction.hash : '';
} catch (e: any) {
console.log(e);
if (e.code) {
MessagePlugin.warning(e.code);
}
return '';
}
};
export const bk_EtherPay = async (to: string, price: number) => {
try {
} catch (e) {
console.log(e);
}
};
// 是否安装小狐狸钱包插件
export const CanNotDownLoadFoxWallet = () => {};
// 连接小狐狸或tp钱包
export const Connect_Fox_tp_wallet = async () => {
const accounts = await eth.ethereum.request({
method: 'eth_requestAccounts',
});
return address_filter(accounts);
};
// 连接bk钱包
export const Connect_BK_wallet = async () => {
const provider = eth.bitkeep && eth.bitkeep.ethereum;
if (!provider) {
MessagePlugin.warning('尚未安装BitKeep');
return;
}
// 连接钱包
const accounts = await provider.request({ method: 'eth_requestAccounts' });
return address_filter(accounts);
};
// 地址过滤
export const address_filter = (accounts: string[]) => {
if (accounts && accounts[0]) {
return {
address: accounts[0],
MaskAddress: `${accounts[0].slice(0, 6)}...${accounts[0].slice(
accounts[0].length - 4,
accounts[0].length
)}`,
};
}
return {
address: '',
MaskAddress: '',
};
};
......@@ -3,9 +3,12 @@ import {
Button as TButton,
Table as TTable,
Tooltip as TTooltip,
Popup as TPopup,
Row as TRow,
Col as TCol,
} from "tdesign-vue-next";
const components = [TDialog, TButton, TTooltip];
const components = [TDialog, TButton, TTooltip, TPopup, TRow, TCol];
export default {
install(app: any) {
......
......@@ -62,3 +62,40 @@ export const timeFormatSeconds = (time: string) => {
year + "-" + month + "-" + day + " " + hours + ":" + min + ":" + seconds
);
};
// 数据存本地
export const setLocal = (
key: string,
data: any,
type: "local" | "session" = "local"
) => {
if (type === "local") {
window.localStorage.setItem(key, JSON.stringify(data));
} else {
window.sessionStorage.setItem(key, JSON.stringify(data));
}
};
// 取本地数据
export const getLocal = (key: string, type: "local" | "session" = "local") => {
let data = null;
if (type === "local") {
let localData = window.localStorage.getItem(key);
if (localData) {
data = JSON.parse(localData);
}
} else {
let localData = window.sessionStorage.getItem(key);
if (localData) {
data = JSON.parse(localData);
}
}
return data;
};
// 获取指定时间 距 当前时间的间隔
export const getCreatedHowLongAgo = (old_time: string | number) => {
if (typeof old_time === "string") {
// 日期格式
}
};
......@@ -19,7 +19,9 @@
Route::get('/', 'InscriptionController@market')->name('home.index');
// OTC 交易
Route::get('/otcTrade', 'OtcController@index')->name('otc.index');
// 铭文交易
Route::get('/trade', 'TradeController@index')->name('trade.index');
// 铭文
Route::group([
'prefix' => '/inscription',
......@@ -30,5 +32,7 @@
Route::get('/wallet', 'InscriptionController@wallet')->name('inscription.wallet');
// 铭文查询(是否被铸造)
Route::get('/search', 'InscriptionController@search')->name('inscription.search');
// 铭文上架
Route::get('/shelves', 'TradeController@shelves')->name('inscription.shelves');
});
});
{
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"module": "ESNext",
"moduleResolution": "Node",
"strict": true,
"jsx": "preserve",
"resolveJsonModule": true,
"isolatedModules": true,
"esModuleInterop": true,
"lib": ["ESNext", "DOM"],
"skipLibCheck": true,
"noEmit": true,
"baseUrl": "./",
"paths": {
"@/*": ["resources/js/*"]
}
},
"include": [
"resources/js/**/*.ts",
"resources/js/**/*.d.ts",
"resources/js/**/*.tsx",
"resources/js/**/*.vue",
"resources/js/**/*.svg",
"node_modules/tdesign-vue-next/global.d.ts"
],
"references": [{ "path": "./tsconfig.node.json" }]
}
{
"compilerOptions": {
"composite": true,
"module": "ESNext",
"moduleResolution": "Node",
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts"]
}
......@@ -17,6 +17,10 @@ export default defineConfig({
svgLoader(),
vueJsx(),
],
optimizeDeps: {
// 解决外部包504问题
include: ["ethers"],
},
resolve: {
alias: {
"@": "/resources/js",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment