diff --git a/package.json b/package.json index 26db783b445..3afd8938e89 100644 --- a/package.json +++ b/package.json @@ -122,7 +122,7 @@ "dependencies": { "@bitcoinerlab/secp256k1": "1.0.2", "@coinbase/cbpay-js": "1.0.2", - "@dlc-link/dlc-tools": "1.0.9", + "@dlc-link/dlc-tools": "1.1.1", "@fungible-systems/zone-file": "2.0.0", "@hirosystems/token-metadata-api-client": "1.1.0", "@ledgerhq/hw-transport-webusb": "6.27.19", diff --git a/scripts/generate-manifest.js b/scripts/generate-manifest.js index 877d5ef8b6c..498eac28e6a 100644 --- a/scripts/generate-manifest.js +++ b/scripts/generate-manifest.js @@ -30,10 +30,15 @@ const environmentIcons = { }, }; +const devCsp = + "script-src 'self' 'wasm-unsafe-eval'; object-src 'self'; frame-src https://ordinals.com/; frame-ancestors 'none';"; + +const prodCsp = `default-src 'none'; connect-src *; style-src 'unsafe-inline'; img-src 'self' data: https:; script-src 'self' 'wasm-unsafe-eval'; object-src 'none'; frame-src https://ordinals.com/; frame-ancestors 'none';`; + const contentSecurityPolicyEnvironment = { - development: - "script-src 'self' 'wasm-unsafe-eval'; object-src 'self'; frame-src 'none'; frame-ancestors 'none';", - production: `default-src 'none'; connect-src *; style-src 'unsafe-inline'; img-src 'self' data: https:; script-src 'self' 'wasm-unsafe-eval'; object-src 'none'; frame-src 'none'; frame-ancestors 'none';`, + testing: prodCsp, + development: devCsp, + production: prodCsp, }; const defaultIconEnvironment = { diff --git a/src/app/common/hooks/use-bitcoin-contracts.ts b/src/app/common/hooks/use-bitcoin-contracts.ts index 1f434476aaa..88355b05eb5 100644 --- a/src/app/common/hooks/use-bitcoin-contracts.ts +++ b/src/app/common/hooks/use-bitcoin-contracts.ts @@ -207,17 +207,27 @@ export function useBitcoinContracts() { close(); } - async function getAllSignedBitcoinContracts(): Promise { + async function getAllActiveBitcoinContracts(): Promise { const bitcoinContractInterface = await getBitcoinContractInterface(); if (!bitcoinContractInterface) return; + await bitcoinContractInterface.periodic_check(); const bitcoinContracts = await bitcoinContractInterface.get_contracts(); - const signedBitcoinContracts = bitcoinContracts.filter( - (bitcoinContract: BitcoinContractListItem) => bitcoinContract.state === 'Signed' - ); - return signedBitcoinContracts; + const stateOrder = ['Signed', 'Confirmed']; + + const activeBitcoinContracts = bitcoinContracts + .filter( + (bitcoinContract: BitcoinContractListItem) => + bitcoinContract.state === 'Signed' || bitcoinContract.state === 'Confirmed' + ) + .sort( + (a: BitcoinContractListItem, b: BitcoinContractListItem) => + stateOrder.indexOf(a.state) - stateOrder.indexOf(b.state) + ); + + return activeBitcoinContracts; } function getTransactionDetails(txId: string, bitcoinCollateral: number) { @@ -239,7 +249,7 @@ export function useBitcoinContracts() { async function sumBitcoinContractCollateralAmounts(): Promise { let bitcoinContractsCollateralSum = 0; - const bitcoinContracts = await getAllSignedBitcoinContracts(); + const bitcoinContracts = await getAllActiveBitcoinContracts(); if (!bitcoinContracts) return createMoneyFromDecimal(0, 'BTC'); bitcoinContracts.forEach((bitcoinContract: BitcoinContractListItem) => { @@ -313,7 +323,7 @@ export function useBitcoinContracts() { handleOffer, handleAccept, handleReject, - getAllSignedBitcoinContracts, + getAllActiveBitcoinContracts, sumBitcoinContractCollateralAmounts, sendRpcResponse, }; diff --git a/src/app/components/brc20-tokens-loader.tsx b/src/app/components/brc20-tokens-loader.tsx index e51b9807bca..042559d4670 100644 --- a/src/app/components/brc20-tokens-loader.tsx +++ b/src/app/components/brc20-tokens-loader.tsx @@ -1,13 +1,13 @@ import { Brc20Token, - useBrc20TokensQuery, + useGetBrc20TokensQuery, } from '@app/query/bitcoin/ordinals/brc20/brc20-tokens.query'; interface Brc20TokensLoaderProps { children(brc20Tokens: Brc20Token[]): React.JSX.Element; } export function Brc20TokensLoader({ children }: Brc20TokensLoaderProps) { - const { data: allBrc20TokensResponse } = useBrc20TokensQuery(); + const { data: allBrc20TokensResponse } = useGetBrc20TokensQuery(); const brc20Tokens = allBrc20TokensResponse?.pages .flatMap(page => page.brc20Tokens) .filter(token => token.length > 0) diff --git a/src/app/components/fees-row/components/fees-row.layout.tsx b/src/app/components/fees-row/components/fees-row.layout.tsx index 5bcec46c849..6c3eff8bac4 100644 --- a/src/app/components/fees-row/components/fees-row.layout.tsx +++ b/src/app/components/fees-row/components/fees-row.layout.tsx @@ -23,7 +23,7 @@ export function FeesRowLayout(props: FeesRowLayoutProps) { const [_, meta] = useField('fee'); return ( - + @@ -39,7 +39,7 @@ export function FeesRowLayout(props: FeesRowLayoutProps) { {feeField} {isSponsored && } - {!meta.error && fieldWarning && {fieldWarning}} + {!meta.error && fieldWarning && {fieldWarning}} ); } diff --git a/src/app/features/collectibles/components/_collectible-types/collectible-audio.tsx b/src/app/features/collectibles/components/_collectible-types/collectible-audio.tsx new file mode 100644 index 00000000000..3688d5b3037 --- /dev/null +++ b/src/app/features/collectibles/components/_collectible-types/collectible-audio.tsx @@ -0,0 +1,19 @@ +import { ReactNode } from 'react'; + +import { AudioIcon } from '@app/ui/components/icons/audio-icon'; + +import { CollectibleItemLayout, CollectibleItemLayoutProps } from '../collectible-item.layout'; +import { CollectiblePlaceholderLayout } from './collectible-placeholder.layout'; + +interface CollectibleAudioProps extends Omit { + icon: ReactNode; +} +export function CollectibleAudio({ icon, ...props }: CollectibleAudioProps) { + return ( + + + + + + ); +} diff --git a/src/app/features/collectibles/components/_collectible-types/collectible-iframe.tsx b/src/app/features/collectibles/components/_collectible-types/collectible-iframe.tsx new file mode 100644 index 00000000000..4b413b68dda --- /dev/null +++ b/src/app/features/collectibles/components/_collectible-types/collectible-iframe.tsx @@ -0,0 +1,35 @@ +import { ReactNode, useState } from 'react'; + +import { Iframe } from '@app/ui/components/iframe'; + +import { CollectibleItemLayout, CollectibleItemLayoutProps } from '../collectible-item.layout'; +import { ImageUnavailable } from '../image-unavailable'; + +interface CollectibleIframeProps extends Omit { + icon: ReactNode; + src: string; +} +export function CollectibleIframe({ icon, src, ...props }: CollectibleIframeProps) { + const [isError, setIsError] = useState(false); + + if (isError) + return ( + + + + ); + + return ( + +