This commit is contained in:
2021-12-21 13:33:40 +08:00
parent de7d9b29b2
commit 896a3be236
14 changed files with 238 additions and 77 deletions

View File

@@ -1,5 +1,6 @@
{
"name": "league-explorer",
"license": "MIT",
"version": "0.1.0",
"private": true,
"scripts": {
@@ -12,6 +13,7 @@
"@33cn/chain33-rpc-api": "^1.5.29",
"@element-plus/icons": "^0.0.11",
"axios": "^0.21.4",
"clipboard": "^2.0.8",
"element-plus": "^1.1.0-beta.16",
"vue": "^3.2.11",
"vue-router": "^4.0.11",

View File

@@ -1,8 +1,11 @@
import auth from './interfaces/auth'
import user from './interfaces/user'
import block from './interfaces/block'
import esdb from './interfaces/esdb'
import user from './interfaces/user'
export {
auth,
user,
block
block,
esdb,
user
}

View File

@@ -1,3 +1,3 @@
import Chain33Rpc from '@33cn/chain33-rpc-api'
export default new Chain33Rpc(process.env.VUE_APP_BLOCK_URL, null)
export default new Chain33Rpc(process.env.VUE_APP_BLOCK_URL as string, null)

View File

@@ -0,0 +1,46 @@
import { AuthResponse } from '@/types/auth'
import axios, { AxiosRequestConfig } from 'axios'
const request = axios.create({
baseURL: process.env.VUE_APP_API_URL as string + process.env.VUE_APP_ESDB_URL as string,
timeout: 5000
})
const axiosConf = (config: AxiosRequestConfig) => {
config.headers.Accept = 'application/json'
return config
}
request.interceptors.response.use(async (response) => {
if (response.data?.error !== null) {
return Promise.reject(response.data.error)
}
return Promise.resolve(response.data?.result)
}, () => {
return Promise.reject('网络请求超时')
})
request.interceptors.request.use(axiosConf, err => {
return Promise.reject(err)
})
const txList = (size?: number): Promise<AuthResponse> => {
const body = {
id: 1,
method: 'Tx.TxList',
params: [{
'sort': [{
'key': 'height',
'ascending': false
}],
'page': {
'number': 1,
'size': size
}
}]
}
return request.post('', body)
}
export default {
txList
}

View File

@@ -2,7 +2,7 @@
<div class="header">
<div class="wrap">
<div class="logo" @click="router.push({name: 'Home'})">
LOGO
JZC Explorer
</div>
<Nav/>
</div>
@@ -34,6 +34,7 @@ const router = useRouter()
}
.logo {
font-size: 32px;
align-items: center;
display: flex;
margin-right: 32px;

View File

@@ -32,10 +32,10 @@ const navList = ref<NavItem[]>([
title: 'Token',
route: 'Token'
},
{
title: '节点',
route: 'Nodes'
},
// {
// title: '节点',
// route: 'Nodes'
// },
{
title: '解析数据',
route: 'Analytical'

View File

@@ -5,12 +5,14 @@ import App from './App.vue'
import router from './router'
import store, { key } from './store'
import zhCn from 'element-plus/es/locale/lang/zh-cn'
import directives from '@/utils/directives'
const app = createApp(App)
app.use(ElementPlus, {
locale: zhCn,
})
app.use(directives)
app.use(store, key)
app.use(router)
app.mount('#app')

22
src/utils/directives.ts Normal file
View File

@@ -0,0 +1,22 @@
import { App, DirectiveBinding } from '@vue/runtime-core'
import ClipboardJS from 'clipboard'
import { ElMessage } from 'element-plus'
export default (Vue: App) => {
Vue.directive('copy', {
updated (el: Element, binding: DirectiveBinding) {
const clipboard = new ClipboardJS(el, {
text: () => {
return binding.value
}
})
clipboard.on('error', (): void => {
ElMessage.warning({
message: '当前浏览器不支持复制'
})
clipboard.destroy()
})
}
})
}

View File

@@ -3,8 +3,12 @@
<Breadcrumb :path="[{name: '地址信息'}]"/>
<div class="top-info">
<span>地址</span>
<span>地址:</span>
<span class="addr">{{ address }}</span>
<el-tag size="medium" v-if="isContract">合约地址</el-tag>
<el-tag size="medium" type="info" v-else>普通地址</el-tag>
<el-button type="primary" v-copy="address" size="mini">复制</el-button>
</div>
<div class="assets">
@@ -16,24 +20,24 @@
<div class="item">
<img src="../../assets/dots/red.png">
<label>余额</label>
<span>{{ balance.balance.toFixed(2) }} {{ store.getters.symbol }}</span>
<span>{{ balance.balance.toFixed(2) }} {{ symbol }}</span>
</div>
<div class="item">
<img src="../../assets/dots/blue.png">
<label>总接收</label>
<span>{{ balance.reciver.toFixed(2) }} {{ store.getters.symbol }}</span>
<span>{{ balance.reciver.toFixed(2) }} {{ symbol }}</span>
</div>
<div class="item">
<img src="../../assets/dots/green.png">
<label>总发送</label>
<span>{{ sended.toFixed(2) }} {{ store.getters.symbol }}</span>
<span>{{ sended.toFixed(2) }} {{ symbol }}</span>
</div>
</div>
<div class="right">
<div class="item">
<img src="../../assets/dots/blue.png">
<label>冻结</label>
<span>{{ frozen.toFixed(2) }} {{ store.getters.symbol }}</span>
<span>{{ frozen.toFixed(2) }} {{ symbol }}</span>
</div>
<div class="item">
<img src="../../assets/dots/green.png">
@@ -78,7 +82,7 @@
<el-empty description="暂无数据"></el-empty>
</template>
<el-table-column width="80" prop="height" label="高度"/>
<el-table-column prop="height" label="高度"/>
<el-table-column width="34" align="right">
<template #default="scope">
<el-icon v-if="scope.row.receipt.ty == 1">
@@ -87,17 +91,18 @@
</template>
</el-table-column>
<el-table-column label="交易哈希">
<el-table-column width="200" label="交易哈希">
<template #default="scope">
<router-link :to="{name: 'TradeDetail', params: { hash: scope.row.txHash }}">
{{ filterHash(scope.row.txHash, 32) }}
{{ filterHash(scope.row.txHash, 16) }}
</router-link>
</template>
</el-table-column>
<el-table-column width="200" label="发送方">
<el-table-column width="160" label="发送方">
<template #default="scope">
<router-link :to="{name: 'Address', params: { address: scope.row.fromAddr }}">
{{ filterHash(scope.row.fromAddr) }}
{{ filterHash(scope.row.fromAddr, 10) }}
</router-link>
</template>
</el-table-column>
@@ -113,28 +118,38 @@
</template>
</el-table-column>
<el-table-column width="200" label="接收方">
<el-table-column width="160" label="接收方">
<template #default="scope">
<router-link :to="{name: 'Address', params: { address: scope.row.tx.to }}">
{{ filterHash(scope.row.tx.to) }}
{{ filterHash(scope.row.tx.to, 10) }}
</router-link>
</template>
</el-table-column>
<el-table-column width="100" label="交易量" align="center">
<el-table-column label="交易量" align="center">
<template #default="scope">
{{ scope.row.amount }} {{ parseSymbol(scope.row.assets) }}
{{ (scope.row.amount / 1e8).toFixed(4) }}
</template>
</el-table-column>
<el-table-column width="100" label="手续费" align="center">
<el-table-column label="手续费" align="center">
<template #default="scope">
{{ scope.row.tx.feefmt }} {{ parseSymbol(scope.row.assets) }}
{{ scope.row.tx.feefmt }}
</template>
</el-table-column>
<el-table-column prop="" label="上链时间" width="165" align="center">
<el-table-column label="调用函数" align="center">
<template #default="scope">
{{ scope.row.actionName }}
</template>
</el-table-column>
<el-table-column width="165" label="上链时间" align="center">
<template #default="scope">
<TimeFormat :time="scope.row.blockTime"/>
</template>
</el-table-column>
<el-table-column label="交易资产" align="center">
<template #default="scope">
{{ parseSymbol(scope.row.assets) }}
</template>
</el-table-column>
</el-table>
</template>
</Pagination>
@@ -156,6 +171,8 @@ const route = useRoute()
const address = computed<string>(() => route.params.address as string)
const pageSize = Number(process.env.VUE_APP_BLOCK_DETAIL_LIST_SIZE)
const symbol = computed<string>(() => store.getters.symbol)
const balance = ref<AddrOverview>({
balance: 0,
reciver: 0,
@@ -167,6 +184,7 @@ const records = ref<BlockDetail[]>([])
const token = ref<string>('')
const assets = ref<TokenAssetItem[]>([])
const loading = ref<boolean>(false)
const isContract = ref<boolean>(false)
watch(route, (to) => {
if (to.name == 'Address') {
@@ -180,6 +198,15 @@ onMounted(() => {
})
const initAddressData = () => {
block.callPromiseAPI('Query', {
execer: 'evm',
funcName: 'CheckAddrExists',
payload: {
addr: address.value
}
}).then(res => {
isContract.value = res.result.contract
})
/**
* 获取地址的基本信息
*/
@@ -259,6 +286,13 @@ const loadTradeList = () => {
color: #516379;
font-weight: 500;
}
.el-tag,
.el-button {
vertical-align: middle;
margin-left: 16px;
}
}
.warning {

View File

@@ -5,7 +5,7 @@
<div class="height">
<h2>区块高度 {{ info.height }}</h2>
<div>区块哈希 {{ info.hash }}
<el-button type="primary" round size="mini"> </el-button>
<el-button type="primary" v-copy="info.hash" round size="mini"> </el-button>
</div>
</div>
@@ -28,7 +28,7 @@
<div class="item">
<img src="../../assets/dots/green.png">
<label>上个区块</label>
<span v-if="info.height -1 > 0">
<span v-if="info.height - 1 > 0">
<router-link :to="{name: 'BlockDetail', params: {hash: info.parentHash}}">
{{ info.height - 1 }}
</router-link>
@@ -42,7 +42,7 @@
<div class="item">
<img src="../../assets/dots/red.png">
<label>时间</label>
<span>{{ info.blockTime }}</span>
<span><TimeFormat :time="info.blockTime"/></span>
</div>
<div class="item">
<img src="../../assets/dots/green.png">
@@ -76,35 +76,44 @@
<el-empty description="暂无数据"></el-empty>
</template>
<el-table-column label="交易哈希">
<el-table-column width="200" label="交易哈希">
<template #default="scope">
<router-link :to="{name: 'TradeDetail', params: { hash: scope.row.txHash }}">
{{ filterHash(scope.row.txHash) }}
{{ filterHash(scope.row.txHash, 16) }}
</router-link>
</template>
</el-table-column>
<el-table-column label="发送方">
<el-table-column width="160" label="发送方">
<template #default="scope">
<router-link :to="{name: 'Address', params: { address: scope.row.fromAddr }}">
{{ filterHash(scope.row.fromAddr) }}
{{ filterHash(scope.row.fromAddr, 10) }}
</router-link>
</template>
</el-table-column>
<el-table-column label="接收方">
<el-table-column width="160" label="接收方">
<template #default="scope">
<router-link :to="{name: 'Address', params: { address: scope.row.tx.to }}">
{{ filterHash(scope.row.tx.to) }}
{{ filterHash(scope.row.tx.to, 10) }}
</router-link>
</template>
</el-table-column>
<el-table-column width="100" prop="amount" label="交易量" align="center"/>
<el-table-column width="100" prop="tx.feefmt" label="手续费" align="center"/>
<el-table-column prop="" label="上链时间" width="165" align="center">
<el-table-column label="交易量" align="center">
<template #default="scope">
{{ (scope.row.amount / 1e8).toFixed(4) }}
</template>
</el-table-column>
<el-table-column prop="tx.feefmt" label="手续费" align="center"/>
<el-table-column label="上链时间" width="165" align="center">
<template #default="scope">
<TimeFormat :time="scope.row.blockTime"/>
</template>
</el-table-column>
<el-table-column width="100" label="交易资产" align="center">
<el-table-column label="调用函数" align="center">
<template #default="scope">
{{ scope.row.actionName }}
</template>
</el-table-column>
<el-table-column label="交易资产" align="center">
<template #default="scope">
{{ parseSymbol(scope.row.assets) }}
</template>
@@ -124,18 +133,20 @@ import { useRoute } from 'vue-router'
const route = useRoute()
const pageSize = Number(process.env.VUE_APP_BLOCK_DETAIL_LIST_SIZE)
const thisHash = ref<string>('')
onMounted(() => {
thisHash.value = route.params.hash as string
loadBlockData()
})
watch(route, (to) => {
if (to.name === 'BlockDetail') {
thisHash.value = info.value.parentHash
loadBlockData()
}
})
const hash: string = route.params.hash as string
const handleCurrentChange = (e: number) => {
console.log(e)
@@ -157,10 +168,7 @@ const next = ref({
const records = ref([])
const loadBlockData = () => {
console.log('jiazai shuju ')
block.getBlockOverview(hash).then(res => {
console.log('更新INFO A ')
block.getBlockOverview(thisHash.value).then(res => {
info.value = res.result.head
block.getTxByHashes(res.result.txHashes).then(txs => {

View File

@@ -77,7 +77,7 @@ export default {
</script>
<script lang="ts" setup>
import { block } from '@/api'
import { block, esdb } from '@/api'
import { Banner, TimeFormat } from '@/components'
import useGetMaxHeight from '@/hooks/useGetMaxHeight'
import { BlockItem, TradeItem } from '@/types/block'
@@ -262,6 +262,10 @@ async function getTradeList () {
flex-direction: column;
justify-content: space-between;
}
.asset {
text-align: right;
}
}
}
}

View File

@@ -5,7 +5,7 @@
<div class="height">
<h2>数据详情</h2>
<div>数据哈希 {{ detail.tx.hash }}
<el-button type="primary" round size="mini"> </el-button>
<el-button type="primary" v-copy="detail.tx.hash" round size="mini"> </el-button>
</div>
</div>
@@ -45,7 +45,7 @@
</div>
<div class="item">
<label>资产</label>
<div>{{ detail.amount }} {{ parseSymbol(detail.assets) }}</div>
<div>{{ (detail.amount / 1e8).toFixed(4) }} {{ parseSymbol(detail.assets) }}</div>
</div>
<div class="item">
<label>GAS费</label>
@@ -108,7 +108,9 @@ const detail = ref<BlockDetail>({
payload: {}
}
} as BlockDetail)
const blockHash = ref('')
const blockHash = ref<string>('')
block.queryTransaction(route.params.hash as string).then(res => {
detail.value = res.result
@@ -116,7 +118,6 @@ block.queryTransaction(route.params.hash as string).then(res => {
blockHash.value = res.result.hash
})
})
</script>
<style scoped lang="less">

View File

@@ -21,15 +21,21 @@ module.exports = {
javascriptEnabled: true
}
}
},
devServer: {
proxy: {
'/api': {
target: 'https://explorer.lianshang.vip/api',
pathRewrite: {
'^/api': ''
}
},
'/esdb': {
target: 'https://explorer.lianshang.vip/esdb',
pathRewrite: {
'^/esdb': ''
}
}
}
}
// devServer: {
// proxy: {
// '/api': {
// target: '',
// pathRewrite: {
// '^/api': ''
// }
// }
// }
// }
}

View File

@@ -990,10 +990,10 @@
"@nodelib/fs.scandir" "2.1.5"
fastq "^1.6.0"
"@popperjs/core@^2.10.1":
version "2.10.1"
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.10.1.tgz#728ecd95ab207aab8a9a4e421f0422db329232be"
integrity sha512-HnUhk1Sy9IuKrxEMdIRCxpIqPw6BFsbYSEUO9p/hNw5sMld/+3OLMWQP80F8/db9qsv3qUjs7ZR5bS/R+iinXw==
"@popperjs/core@^2.10.2":
version "2.11.0"
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.0.tgz#6734f8ebc106a0860dff7f92bf90df193f0935d7"
integrity sha512-zrsUxjLOKAzdewIDRWy9nsV1GQsKBCWaGwsZQlCgr6/q+vjyZhFgqedLfFBuI9anTPEUT4APq9Mu0SZBTzIcGQ==
"@soda/friendly-errors-webpack-plugin@^1.7.1":
version "1.8.0"
@@ -2064,10 +2064,10 @@ async-limiter@~1.0.0:
resolved "https://registry.nlark.com/async-limiter/download/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd"
integrity sha1-3TeelPDbgxCwgpH51kwyCXZmF/0=
async-validator@^3.4.0:
version "3.5.2"
resolved "https://registry.yarnpkg.com/async-validator/-/async-validator-3.5.2.tgz#68e866a96824e8b2694ff7a831c1a25c44d5e500"
integrity sha512-8eLCg00W9pIRZSB781UUX/H6Oskmm8xloZfr09lz5bikRpBVDlJ3hRVuxxP1SxcwsEYfJ4IU8Q19Y8/893r3rQ==
async-validator@^4.0.3:
version "4.0.7"
resolved "https://registry.yarnpkg.com/async-validator/-/async-validator-4.0.7.tgz#034a0fd2103a6b2ebf010da75183bec299247afe"
integrity sha512-Pj2IR7u8hmUEDOwB++su6baaRi+QvsgajuFB9j95foM1N2gy5HM4z60hfusIO0fBPG5uLAEl6yCJr1jNSVugEQ==
async@^2.6.2:
version "2.6.3"
@@ -2737,6 +2737,15 @@ cli-width@^3.0.0:
resolved "https://registry.nlark.com/cli-width/download/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6"
integrity sha1-ovSEN6LKqaIkNueUvwceyeYc7fY=
clipboard@^2.0.8:
version "2.0.8"
resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-2.0.8.tgz#ffc6c103dd2967a83005f3f61976aa4655a4cdba"
integrity sha512-Y6WO0unAIQp5bLmk1zdThRhgJt/x3ks6f30s3oE3H1mgIEU33XyQjEf8gsf6DxC7NPX8Y1SsNWjUjL/ywLnnbQ==
dependencies:
good-listener "^1.2.2"
select "^1.1.2"
tiny-emitter "^2.0.0"
clipboardy@^2.3.0:
version "2.3.0"
resolved "https://registry.nlark.com/clipboardy/download/clipboardy-2.3.0.tgz#3c2903650c68e46a91b388985bc2774287dba290"
@@ -3446,6 +3455,11 @@ delayed-stream@~1.0.0:
resolved "https://registry.nlark.com/delayed-stream/download/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
delegate@^3.1.2:
version "3.2.0"
resolved "https://registry.yarnpkg.com/delegate/-/delegate-3.2.0.tgz#b66b71c3158522e8ab5744f720d8ca0c2af59166"
integrity sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==
depd@~1.1.2:
version "1.1.2"
resolved "https://registry.nlark.com/depd/download/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
@@ -3648,17 +3662,18 @@ electron-to-chromium@^1.3.830:
integrity sha1-J6WyFGjp/vsOMooClANhfyCs7Jw=
element-plus@^1.1.0-beta.16:
version "1.1.0-beta.16"
resolved "https://registry.yarnpkg.com/element-plus/-/element-plus-1.1.0-beta.16.tgz#4409d9e33d005693f6039f5ed1fe05e301b3170d"
integrity sha512-4BZEldnIfFZs5A/saRqaWE4PwTot4p3YZU7qsDr3ev2zp35pcCL9TtpWMLIvNTMxvxKew0HTDPTk9fAWIZFQrQ==
version "1.1.0-beta.24"
resolved "https://registry.yarnpkg.com/element-plus/-/element-plus-1.1.0-beta.24.tgz#858b05932ebc0be15419d3974d15be2a4f4b696c"
integrity sha512-dmo61e/D6mwJVacMhxOMSPb5sZPt/FPsuQQfsOs1kJWkhGDmTlny/sZvgIQr1z0zh3pjlJadGAlNS+0nySPMmw==
dependencies:
"@popperjs/core" "^2.10.1"
"@element-plus/icons" "^0.0.11"
"@popperjs/core" "^2.10.2"
"@vueuse/core" "~6.1.0"
async-validator "^3.4.0"
async-validator "^4.0.3"
dayjs "^1.10.7"
lodash "^4.17.21"
memoize-one "^5.2.1"
normalize-wheel "^1.0.1"
normalize-wheel-es "^1.1.0"
resize-observer-polyfill "^1.5.1"
elliptic@^6.5.3:
@@ -4618,6 +4633,13 @@ globby@^9.2.0:
pify "^4.0.1"
slash "^2.0.0"
good-listener@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/good-listener/-/good-listener-1.2.2.tgz#d53b30cdf9313dffb7dc9a0d477096aa6d145c50"
integrity sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=
dependencies:
delegate "^3.1.2"
graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0:
version "4.2.8"
resolved "https://registry.nlark.com/graceful-fs/download/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a"
@@ -6305,10 +6327,10 @@ normalize-url@^3.0.0:
resolved "https://registry.nlark.com/normalize-url/download/normalize-url-3.3.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fnormalize-url%2Fdownload%2Fnormalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559"
integrity sha1-suHE3E98bVd0PfczpPWXjRhlBVk=
normalize-wheel@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/normalize-wheel/-/normalize-wheel-1.0.1.tgz#aec886affdb045070d856447df62ecf86146ec45"
integrity sha1-rsiGr/2wRQcNhWRH32Ls+GFG7EU=
normalize-wheel-es@^1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/normalize-wheel-es/-/normalize-wheel-es-1.1.1.tgz#a8096db6a56f94332d884fd8ebeda88f2fc79569"
integrity sha512-157VNH4CngrcsvF8xOVOe22cwniIR3nxSltdctvQeHZj8JttEeOXffK28jucWfWBXs0QNetAumjc1GiInnwX4w==
npm-run-path@^2.0.0:
version "2.0.2"
@@ -7768,6 +7790,11 @@ select-hose@^2.0.0:
resolved "https://registry.nlark.com/select-hose/download/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca"
integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=
select@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d"
integrity sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=
selfsigned@^1.10.8:
version "1.10.11"
resolved "https://registry.nlark.com/selfsigned/download/selfsigned-1.10.11.tgz#24929cd906fe0f44b6d01fb23999a739537acbe9"
@@ -8490,6 +8517,11 @@ timsort@^0.3.0:
resolved "https://registry.nlark.com/timsort/download/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4"
integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=
tiny-emitter@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423"
integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==
tmp@^0.0.33:
version "0.0.33"
resolved "https://registry.nlark.com/tmp/download/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"