Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
riverrun46 committed Sep 27, 2023
2 parents 4486a0e + aef0f93 commit 75b3c56
Show file tree
Hide file tree
Showing 10 changed files with 173 additions and 77 deletions.
13 changes: 1 addition & 12 deletions src/content-script/inject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const callMetalet = async (params: MetaletParams) => {
window.postMessage(response, '*')
}
} catch (e: any) {
if (!e.message.includes('Could not establish connection.')) {
if (!e.message.includes('Could not establish connection.') && params.action.includes('query')) {
throw e
}

Expand All @@ -47,17 +47,6 @@ const callMetalet = async (params: MetaletParams) => {
}

await tryCall(params)

// try {
// await tryCall(params)
// } catch (e: any) {
// // If the error comes from timeout, we try again
// if (e.message.includes('Could not establish connection.')) {
// setTimeout(async () => {
// await tryCall(params)
// }, 1000)
// }
// }
}

window.addEventListener(
Expand Down
2 changes: 2 additions & 0 deletions src/lib/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ export async function addAccount(newAccount: Omit<Account, 'id' | 'name'>) {

async function getAccountProperty(chain: Chain, key: keyof ChainDetail[Chain]): Promise<string> {
const account = await getCurrentAccount()
console.log('current account', account)

if (!account) {
return ''
}
Expand Down
2 changes: 1 addition & 1 deletion src/lib/actions/btc/sign-psbt.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import ECPairFactory from 'ecpair'
import { getPrivateKey, getCurrentAccount, getAddressType, getPublicKey, getAddress } from '@/lib/account'
import { getPrivateKey, getAddressType, getPublicKey, getAddress } from '@/lib/account'
import bitcoin, { address as PsbtAddress, networks } from 'bitcoinjs-lib'
import * as ecc from '@bitcoin-js/tiny-secp256k1-asmjs'
import { getNetwork } from '@/lib/network'
Expand Down
23 changes: 23 additions & 0 deletions src/lib/balance.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { computed, ref } from 'vue'

interface Asset {
name: string
value: number
}

export const totalBalance = computed(() => {
console.log('assetList', assetList.value)

return assetList.value.reduce((sum, asset) => sum + asset.value, 0)
})

export const assetList = ref<Asset[]>([])

export async function updateAsset(asset: Asset) {
const preAsset = assetList.value.find((assetItem) => assetItem.name === asset.name)
if (!preAsset) {
assetList.value.push(asset)
} else {
preAsset.value = asset.value
}
}
38 changes: 11 additions & 27 deletions src/pages/wallet/Import.vue
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ const onSubmit = async () => {
// 转化成私钥
try {
const btcPath = selectedScript.value.path
const fullPath = `m/44'/${pathDepth.value}'/0'/0/0`
const btcPath = `m/86'/0'/0'/0/0`
const allAddresses = deriveAllAddresses({
mnemonic: mnemonicStr,
Expand Down Expand Up @@ -177,35 +177,23 @@ const onSubmit = async () => {
<Listbox v-model="selectedScript">
<div class="relative mt-1">
<ListboxButton
class="relative w-full cursor-default rounded-lg bg-[#f5f5f5] py-2 pl-3 pr-10 text-left shadow-md focus:outline-none focus-visible:border-indigo-500 focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75 focus-visible:ring-offset-2 focus-visible:ring-offset-orange-300 sm:text-sm"
>
class="relative w-full cursor-default rounded-lg bg-[#f5f5f5] py-2 pl-3 pr-10 text-left shadow-md focus:outline-none focus-visible:border-indigo-500 focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75 focus-visible:ring-offset-2 focus-visible:ring-offset-orange-300 sm:text-sm">
<span class="block truncate">{{ selectedScript.path }}</span>
<span class="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2">
<ChevronUpDownIcon class="h-5 w-5 text-gray-400" aria-hidden="true" />
</span>
</ListboxButton>

<transition
leave-active-class="transition duration-100 ease-in"
leave-from-class="opacity-100"
leave-to-class="opacity-0"
>
<transition leave-active-class="transition duration-100 ease-in" leave-from-class="opacity-100"
leave-to-class="opacity-0">
<ListboxOptions
class="absolute mt-1 max-h-60 w-full overflow-auto rounded-md bg-[#f5f5f5] py-2 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm"
>
<ListboxOption
v-slot="{ selected }"
v-for="script in scripts"
:key="script.name"
:value="script"
as="template"
>
class="absolute mt-1 max-h-60 w-full overflow-auto rounded-md bg-[#f5f5f5] py-2 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm">
<ListboxOption v-slot="{ selected }" v-for="script in scripts" :key="script.name" :value="script"
as="template">
<li :class="['text-gray-900', 'relative cursor-pointer select-none py-1 pl-3 pr-4']">
<span :class="[selected ? 'font-medium' : 'font-normal', 'block truncate']">{{ script.path }}</span>
<span
v-if="selected"
class="absolute inset-y-2 right-2 flex h-5 w-5 items-center justify-center rounded-md bg-[#1E2BFF] text-white"
>
<span v-if="selected"
class="absolute inset-y-2 right-2 flex h-5 w-5 items-center justify-center rounded-md bg-[#1E2BFF] text-white">
<CheckIcon class="h-4 w-4" aria-hidden="true" />
</span>
</li>
Expand All @@ -217,12 +205,8 @@ const onSubmit = async () => {

<!-- ok -->
<div class="mt-32 flex items-center justify-center">
<button
class="main-btn-bg mt-8 grow rounded-md py-3 text-sm font-bold text-sky-50"
:class="[!finished && 'muted']"
:disabled="!finished"
@click="onSubmit"
>
<button class="main-btn-bg mt-8 grow rounded-md py-3 text-sm font-bold text-sky-50" :class="[!finished && 'muted']"
:disabled="!finished" @click="onSubmit">
OK
</button>
</div>
Expand Down
2 changes: 2 additions & 0 deletions src/pages/wallet/components/AssetItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { type Asset, getTagInfo, Tag } from '@/data/assets'
import { useExchangeRatesQuery } from '@/queries/exchange-rates'
import { getCurrentAccount } from '@/lib/account'
import { getNetwork } from '@/lib/network'
import { updateAsset } from '@/lib/balance'
const { asset } = defineProps<{
asset: Asset
Expand Down Expand Up @@ -46,6 +47,7 @@ const exchange = computed(() => {
const usdRate: number = Number(exchangeRate.value.price)
const balanceInStandardUnit = balance.value.total / 10 ** asset.decimal
const exchanged = balanceInStandardUnit * usdRate
updateAsset({ name: asset.symbol, value: exchanged })
return `$${exchanged.toFixed(2)} USD`
}
Expand Down
19 changes: 14 additions & 5 deletions src/pages/wallet/components/AssetList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,28 @@ import useTokensQuery from '@/queries/tokens'
import { getAssetsDisplay } from '@/lib/assets'
import { BTCAssets, MVCAssets } from '@/data/assets'
import { fetchBtcAsset } from '@/queries/btc'
const router = useRouter()
const address = ref<string>('')
getAddress().then((add) => {
if (!add) return router.push('/welcome')
const btcAssets = ref(BTCAssets)
address.value = add
// TODO Refactor into hooks
getAddress("btc").then((addr) => {
if (!addr) return router.push('/welcome')
address.value = addr
fetchBtcAsset(addr).then(userBRC20Asset => {
btcAssets.value = btcAssets.value
.filter(asset =>
asset.symbol === 'BTC' || userBRC20Asset.includes(asset.symbol))
})
})
const enabled = computed(() => !!address.value)
const btcAssets = ref(BTCAssets)
const listedAssets = ref(MVCAssets)
const enabled = computed(() => !!address.value)
const { isLoading, data: userOwnedTokens } = useTokensQuery(address, { enabled })
type UserOwnedToken = NonNullable<typeof userOwnedTokens.value>[number]
Expand Down
34 changes: 3 additions & 31 deletions src/pages/wallet/components/Balance.vue
Original file line number Diff line number Diff line change
@@ -1,37 +1,10 @@
<script lang="ts" setup>
import { useRouter } from 'vue-router'
import { computed, ref, Ref } from 'vue'
import { totalBalance } from '@/lib/balance'
import { ArrowUpRightIcon, QrCodeIcon } from '@heroicons/vue/20/solid'
import { useBalanceQuery } from '@/queries/balance'
import { useExchangeRatesQuery } from '@/queries/exchange-rates'
import { getAddress } from '@/lib/account'
const router = useRouter()
const address: Ref<string> = ref('')
getAddress('mvc').then((add) => {
address.value = add!
})
const enabled = computed(() => !!address.value)
const { isLoading, data: balance } = useBalanceQuery(address, 'SPACE', { enabled })
const { isLoading: isExchangeRateLoading, data: exchangeRate } = useExchangeRatesQuery('SPACE', { enabled })
const exchange = computed(() => {
if (balance.value && exchangeRate.value) {
const usdRate: number = Number(exchangeRate.value.price)
const balanceInStandardUnit = balance.value.total / 10 ** 8
const exchanged = balanceInStandardUnit * usdRate
// 保留两位
return `$${exchanged.toFixed(2)}`
}
return '--'
})
function toSelectAsset(purpose: 'receive' | 'send') {
const selectAssetRoute = {
name: 'select-asset',
Expand All @@ -46,9 +19,8 @@ function toSelectAsset(purpose: 'receive' | 'send') {
<template>
<div class="pt-4">
<div class="text-gray-500">Total Balance</div>
<div class="mt-2 text-3xl font-bold" v-if="isLoading || isExchangeRateLoading">--</div>
<div class="mt-2 text-3xl font-bold" v-else>
{{ exchange }}
<div class="mt-2 text-3xl font-bold">
$ {{ totalBalance.toFixed(2) }} USD
</div>

<!-- 接收和发送按钮 -->
Expand Down
23 changes: 22 additions & 1 deletion src/queries/btc.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import dayjs from 'dayjs'
import { ordersApi } from '@/queries/request'
import { ordersApi, metaletApi } from '@/queries/request'
import { BRC20_Symbol_UC } from '@/lib/asset-symbol'

export const getBTCBalance = (address: string) => {
return ordersApi('/balance').get({ address })
Expand Down Expand Up @@ -51,3 +52,23 @@ export const getBTActivities = async (address: string): Promise<Tx[]> => {
export const getBTCPrice = () => {
return ordersApi('/btc-price').get()
}

type TokenType = 'BRC20'

interface Tick {
token: BRC20_Symbol_UC
tokenType: TokenType
balance: string
availableBalance: string
transferBalance: string
}

export const fetchBtcAsset = async (address: string): Promise<string[]> => {
const brc20Assets = await metaletApi(`/address/brc20/asset`)
.get({ address, chain: 'btc' })
.then((res) => {
return res.data.tickList.map((tick: Tick) => tick.token)
})

return brc20Assets
}
94 changes: 94 additions & 0 deletions src/queries/utxo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { useQuery } from '@tanstack/vue-query'
import { metaletApi, mvcApi } from './request'
import { ComputedRef, Ref } from 'vue'
import { SymbolUC, BRC20_SYMBOLS } from '@/lib/asset-symbol'

type TokenType = "BRC20"

interface Tick {
token: SymbolUC
tokenType: TokenType
balance: string
availableBalance: string
transferBalance: string
}

export type Balance = {
address: string
confirmed?: number
unconfirmed?: number
availableBalance?: number
transferBalance?: number
total: number
}

export const fetchSpaceBalance = async (address: string): Promise<Balance> => {
const balance: any = await mvcApi(`/address/${address}/balance`).get()
balance.total = balance.confirmed + balance.unconfirmed
return balance
}

export const fetchBtcBalance = async (address: string): Promise<Balance> => {
const balance: any = await metaletApi(`/address/balance`)
.get({ address, chain: 'btc' })
.then((res) => res.data)

balance.total = balance.confirmed + balance.unconfirmed

return balance
}

export const fetchBRC20Balance = async (address: string, symbol: SymbolUC): Promise<Balance> => {
const { tickList } = await metaletApi(`/address/brc20/asset`)
.get({ address, chain: 'btc', tick: symbol.toLowerCase() })
.then((res) => res.data)

const tickAsset = tickList.find((tick: Tick) => tick.token === symbol)

if (tickAsset) {
return {
address,
availableBalance: Number(tickAsset.availableBalance),
transferBalance: Number(tickAsset.transferBalance),
total: Number(tickAsset.balance),
}
}

return {
address,
availableBalance: 0,
transferBalance: 0,
total: 0,
}
}

export const doNothing = async (): Promise<Balance> => {
return {
address: '',
confirmed: 0,
unconfirmed: 0,
total: 0,
}
}

export const useBalanceQuery = (address: Ref, symbol: SymbolUC, options: { enabled: ComputedRef<boolean> }) => {
return useQuery({
queryKey: ['balance', { address, symbol }],
queryFn: () => {
switch (symbol) {
case 'SPACE':
return fetchSpaceBalance(address.value)
case 'BTC':
return fetchBtcBalance(address.value)
default: {
if (BRC20_SYMBOLS.includes(symbol)) {
return fetchBRC20Balance(address.value, symbol)
}
return doNothing()
}
}
},
...options,

})
}

0 comments on commit 75b3c56

Please sign in to comment.