Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stores-bitcoin - balance query #1343

Open
wants to merge 14 commits into
base: Thunnini/bitcoin
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
"@keplr-wallet/router-extension": "0.12.190",
"@keplr-wallet/simple-fetch": "0.12.190",
"@keplr-wallet/stores": "0.12.190",
"@keplr-wallet/stores-bitcoin": "0.12.190",
"@keplr-wallet/stores-core": "0.12.190",
"@keplr-wallet/stores-etc": "0.12.190",
"@keplr-wallet/stores-eth": "0.12.190",
Expand Down
66 changes: 62 additions & 4 deletions apps/extension/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3186,6 +3186,16 @@ export const EmbedChainInfos: (ChainInfo | ModularChainInfo)[] = [
rpc: "",
rest: "",
coinType: 0,
currencies: [
{
coinDenom: "BTC",
coinMinimalDenom: "taproot:bitcoinMainnet", // TODO: 추후 변경 필요
coinDecimals: 8,
coinGeckoId: "bitcoin",
coinImageUrl:
"https://cryptologos.cc/logos/bitcoin-btc-logo.png?v=040",
},
],
},
},
{
Expand All @@ -3202,6 +3212,16 @@ export const EmbedChainInfos: (ChainInfo | ModularChainInfo)[] = [
rpc: "",
rest: "",
coinType: 0,
currencies: [
{
coinDenom: "BTC",
coinMinimalDenom: "nativeSegwit:bitcoinMainnet",
coinDecimals: 8,
coinGeckoId: "bitcoin",
coinImageUrl:
"https://cryptologos.cc/logos/bitcoin-btc-logo.png?v=040",
},
],
},
},
{
Expand All @@ -3216,8 +3236,17 @@ export const EmbedChainInfos: (ChainInfo | ModularChainInfo)[] = [
chainId:
"bip122:000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943",
rpc: "",
rest: "",
rest: "https://blockstream.info/testnet/api",
coinType: 1,
currencies: [
{
coinDenom: "tBTC",
coinMinimalDenom: "taproot:bitcoinTestnet",
coinDecimals: 8,
coinImageUrl:
"https://cryptologos.cc/logos/bitcoin-btc-logo.png?v=040",
},
],
},
},
{
Expand All @@ -3232,8 +3261,17 @@ export const EmbedChainInfos: (ChainInfo | ModularChainInfo)[] = [
chainId:
"bip122:000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943",
rpc: "",
rest: "",
rest: "https://blockstream.info/testnet/api",
coinType: 1,
currencies: [
{
coinDenom: "tBTC",
coinMinimalDenom: "nativeSegwit:bitcoinTestnet",
coinDecimals: 8,
coinImageUrl:
"https://cryptologos.cc/logos/bitcoin-btc-logo.png?v=040",
},
],
},
},
{
Expand All @@ -3248,8 +3286,18 @@ export const EmbedChainInfos: (ChainInfo | ModularChainInfo)[] = [
chainId:
"bip122:00000008819873e925422c1ff0f99f7cc9bbb232af63a077a480a3633bee1ef6",
rpc: "",
rest: "",
rest: "https://explorer.bc-2.jp/api",
coinType: 1,
currencies: [
{
coinDenom: "sBTC",
coinMinimalDenom: "taproot:bitcoinSignet",
coinDecimals: 8,
coinGeckoId: "bitcoin", // TODO: temporal value for query price test
coinImageUrl:
"https://cryptologos.cc/logos/bitcoin-btc-logo.png?v=040",
},
],
},
},
{
Expand All @@ -3264,8 +3312,18 @@ export const EmbedChainInfos: (ChainInfo | ModularChainInfo)[] = [
chainId:
"bip122:00000008819873e925422c1ff0f99f7cc9bbb232af63a077a480a3633bee1ef6",
rpc: "",
rest: "",
rest: "https://explorer.bc-2.jp/api",
coinType: 1,
currencies: [
{
coinDenom: "sBTC",
coinMinimalDenom: "nativeSegwit:bitcoinSignet",
coinDecimals: 8,
coinGeckoId: "bitcoin",
coinImageUrl:
"https://cryptologos.cc/logos/bitcoin-btc-logo.png?v=040",
},
],
},
},
];
Expand Down
26 changes: 14 additions & 12 deletions apps/extension/src/pages/main/available.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,29 +106,31 @@ export const AvailableTabView: FunctionComponent<{
(chainInfo) => !chainStore.isEnabledChain(chainInfo.chainId)
);

const disabledStarknetChainInfos = chainStore.modularChainInfos.filter(
(modularChainInfo) =>
"starknet" in modularChainInfo &&
!chainStore.isEnabledChain(modularChainInfo.chainId) &&
trimSearch.length >= 3 &&
(modularChainInfo.chainId.toLowerCase().includes(trimSearch) ||
modularChainInfo.chainName.toLowerCase().includes(trimSearch) ||
trimSearch === "eth")
);
const disabledModularChainInfos =
chainStore.groupedModularChainInfos.filter(
(modularChainInfo) =>
("starknet" in modularChainInfo || "bitcoin" in modularChainInfo) &&
!chainStore.isEnabledChain(modularChainInfo.chainId) &&
trimSearch.length >= 3 &&
(modularChainInfo.chainId.toLowerCase().includes(trimSearch) ||
modularChainInfo.chainName.toLowerCase().includes(trimSearch) ||
trimSearch === "eth" ||
trimSearch === "btc")
);

disabledChainInfos = [
...new Set([...disabledChainInfos, ...disabledStarknetChainInfos]),
...new Set([...disabledChainInfos, ...disabledModularChainInfos]),
].sort((a, b) => a.chainName.localeCompare(b.chainName));

return disabledChainInfos.reduce(
(acc, chainInfo) => {
let embedded: boolean | undefined = false;
let stored: boolean = true;

const isStarknet = "starknet" in chainInfo;
const isModular = "starknet" in chainInfo || "bitcoin" in chainInfo;

try {
if (isStarknet) {
if (isModular) {
embedded = true;
} else {
const chainInfoInStore = chainStore.getChain(chainInfo.chainId);
Expand Down
21 changes: 16 additions & 5 deletions apps/extension/src/pages/main/token-detail/address-chip/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,14 @@ export const AddressChip: FunctionComponent<{
navigator.clipboard.writeText(
isEVMOnlyChain ? account.ethereumHexAddress : account.bech32Address
);
} else {
} else if ("starknet" in modularChainInfo) {
// copy address
navigator.clipboard.writeText(account.starknetHexAddress);
} else if ("bitcoin" in modularChainInfo) {
// copy address
navigator.clipboard.writeText(
account.bitcoinAddress?.bech32Address ?? ""
);
}
setAnimCheck(true);
}}
Expand All @@ -108,11 +113,17 @@ export const AddressChip: FunctionComponent<{
10
)}...${account.ethereumHexAddress.slice(32)}`
: Bech32Address.shortenAddress(account.bech32Address, 16);
} else if ("starknet" in modularChainInfo) {
return `${account.starknetHexAddress.slice(
0,
10
)}...${account.starknetHexAddress.slice(56)}`;
} else if ("bitcoin" in modularChainInfo) {
return Bech32Address.shortenAddress(
account.bitcoinAddress?.bech32Address ?? "",
16
);
}
return `${account.starknetHexAddress.slice(
0,
10
)}...${account.starknetHexAddress.slice(56)}`;
})()}
</Body3>
<Gutter size="0.4rem" />
Expand Down
54 changes: 43 additions & 11 deletions apps/extension/src/pages/main/token-detail/modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ export const TokenDetailModal: FunctionComponent<{
accountStore,
queriesStore,
starknetQueriesStore,
bitcoinQueriesStore,
priceStore,
price24HChangesStore,
skipQueriesStore,
Expand All @@ -87,9 +88,13 @@ export const TokenDetailModal: FunctionComponent<{
// TODO: 일단 cosmos가 아니면 대충에기에다가 force currency 로직을 박아놓는다...
// 나중에 이런 기능을 chain store 자체에다가 만들어야한다.
const modularChainInfoImpl = chainStore.getModularChainInfoImpl(chainId);
const res = modularChainInfoImpl
.getCurrencies("starknet")
.find((cur) => cur.coinMinimalDenom === coinMinimalDenom);
const modularChainInfoImplImpl =
"bitcoin" in modularChainInfo
? modularChainInfoImpl.getCurrencies("bitcoin")
: modularChainInfoImpl.getCurrencies("starknet");
const res = modularChainInfoImplImpl.find(
(cur) => cur.coinMinimalDenom === coinMinimalDenom
);
if (res) {
return res;
}
Expand Down Expand Up @@ -132,14 +137,30 @@ export const TokenDetailModal: FunctionComponent<{
.getQueryBech32Address(account.bech32Address)
.getBalance(currency);
}
return starknetQueriesStore
.get(chainId)
.queryStarknetERC20Balance.getBalance(
chainId,
chainStore,
account.starknetHexAddress,
currency.coinMinimalDenom
);

if ("starknet" in modularChainInfo) {
return starknetQueriesStore
.get(chainId)
.queryStarknetERC20Balance.getBalance(
chainId,
chainStore,
account.starknetHexAddress,
currency.coinMinimalDenom
);
}

if ("bitcoin" in modularChainInfo) {
return bitcoinQueriesStore
.get(chainId)
.queryBitcoinBalance.getBalance(
chainId,
chainStore,
account.bitcoinAddress?.bech32Address ?? "",
currency.coinMinimalDenom
);
}

return undefined;
})();

const price24HChange = (() => {
Expand Down Expand Up @@ -285,6 +306,11 @@ export const TokenDetailModal: FunctionComponent<{
`/starknet/send?chainId=${chainId}&coinMinimalDenom=${coinMinimalDenom}`
);
}
if ("bitcoin" in modularChainInfo) {
navigate(
`/bitcoin/send?chainId=${chainId}&coinMinimalDenom=${coinMinimalDenom}`
);
}
},
},
];
Expand All @@ -298,6 +324,12 @@ export const TokenDetailModal: FunctionComponent<{
if ("cosmos" in modularChainInfo) {
return accountStore.getAccount(chainId).bech32Address;
}
// TODO: handle bitcoin tx history
// if ("bitcoin" in modularChainInfo) {
// return (
// accountStore.getAccount(chainId).bitcoinAddress?.bech32Address ?? ""
// );
// }
return accountStore.getAccount(chainId).starknetHexAddress;
})()}?relations=${Relations.join(",")}&denoms=${encodeURIComponent(
currency.coinMinimalDenom
Expand Down
65 changes: 61 additions & 4 deletions apps/extension/src/stores/huge-queries/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { BinarySortArray } from "./sort";
import { StarknetQueriesStore } from "@keplr-wallet/stores-starknet";
import { ChainIdHelper } from "@keplr-wallet/cosmos";
import { ModularChainInfo } from "@keplr-wallet/types";
import { BitcoinQueriesStore } from "@keplr-wallet/stores-bitcoin";

interface ViewToken {
chainInfo: IChainInfoImpl | ModularChainInfo;
Expand Down Expand Up @@ -54,6 +55,7 @@ export class HugeQueriesStore {
protected readonly chainStore: ChainStore,
protected readonly queriesStore: IQueriesStore<CosmosQueries>,
protected readonly starknetQueriesStore: StarknetQueriesStore,
protected readonly bitcoinQueriesStore: BitcoinQueriesStore,
protected readonly accountStore: IAccountStore,
protected readonly priceStore: CoinGeckoPriceStore
) {
Expand Down Expand Up @@ -277,6 +279,60 @@ export class HugeQueriesStore {
}
}
}

if ("bitcoin" in modularChainInfo) {
if (!account.bitcoinAddress) {
continue;
}

const modularChainInfoImpl = this.chainStore.getModularChainInfoImpl(
modularChainInfo.chainId
);
const queries = this.bitcoinQueriesStore.get(modularChainInfo.chainId);
const currencies = modularChainInfoImpl.getCurrencies("bitcoin");

// TODO: bitcoin coinMinimalDenom 변경 시 수정 필요
const currency = currencies.find(
(currency) =>
currency.coinMinimalDenom.startsWith("taproot:bitcoin") ||
currency.coinMinimalDenom.startsWith("nativeSegwit:bitcoin")
);
if (!currency) {
continue;
}

const queryBalance = queries.queryBitcoinBalance.getBalance(
modularChainInfo.chainId,
this.chainStore,
account.bitcoinAddress.bech32Address,
currency.coinMinimalDenom
);

if (!queryBalance) {
continue;
}

const key = `${
ChainIdHelper.parse(modularChainInfo.chainId).identifier
}/${currency.coinMinimalDenom}`;
if (!keysUsed.get(key)) {
if (queryBalance.balance.toDec().equals(HugeQueriesStore.zeroDec)) {
continue;
}

keysUsed.set(key, true);
prevKeyMap.delete(key);
this.balanceBinarySort.pushAndSort(key, {
chainInfo: modularChainInfo,
token: queryBalance.balance,
price: currency.coinGeckoId
? this.priceStore.calculatePrice(queryBalance.balance)
: undefined,
isFetching: queryBalance.isFetching,
error: queryBalance.error,
});
}
}
}

for (const removedKey of prevKeyMap.keys()) {
Expand Down Expand Up @@ -309,13 +365,14 @@ export class HugeQueriesStore {
keys.set(key, true);
}
}
if ("starknet" in modularChainInfo) {
if ("starknet" in modularChainInfo || "bitcoin" in modularChainInfo) {
const module =
"starknet" in modularChainInfo ? "starknet" : "bitcoin";

const modularChainInfoImpl = this.chainStore.getModularChainInfoImpl(
modularChainInfo.chainId
);
for (const currency of modularChainInfoImpl.getCurrencies(
"starknet"
)) {
for (const currency of modularChainInfoImpl.getCurrencies(module)) {
const key = `${
ChainIdHelper.parse(modularChainInfo.chainId).identifier
}/${currency.coinMinimalDenom}`;
Expand Down
Loading
Loading