-
Notifications
You must be signed in to change notification settings - Fork 149
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: check utxo ids for inscriptions
- Loading branch information
1 parent
f0f488a
commit 614e81e
Showing
6 changed files
with
280 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
import { useCallback, useState } from 'react'; | ||
|
||
import { useAnalytics } from '@app/common/hooks/analytics/use-analytics'; | ||
import { useBitcoinClient } from '@app/store/common/api-clients.hooks'; | ||
import { useCurrentNetworkState } from '@app/store/networks/networks.hooks'; | ||
|
||
import { useOrdiscanInscriptionsByAddressQuery } from '../ordinals/inscriptions.query'; | ||
|
||
class PreventTransactionError extends Error { | ||
constructor(message: string) { | ||
super(message); | ||
this.name = 'PreventTransactionError'; | ||
} | ||
} | ||
|
||
interface UseCheckInscribedUtxosArgs { | ||
txids: string[]; | ||
address: string; | ||
blockTxAction?(): void; | ||
} | ||
|
||
export function useCheckInscribedUtxos({ | ||
txids, | ||
address, | ||
blockTxAction, | ||
}: UseCheckInscribedUtxosArgs) { | ||
const client = useBitcoinClient(); | ||
const analytics = useAnalytics(); | ||
const [isLoading, setIsLoading] = useState(false); | ||
const { isTestnet } = useCurrentNetworkState(); | ||
const { | ||
data: ordInscriptionsList, | ||
refetch: refetchOrdInscriptionsList, | ||
isError: isOrdRequestError, | ||
} = useOrdiscanInscriptionsByAddressQuery({ | ||
address, | ||
}); | ||
|
||
const preventTransaction = useCallback(() => { | ||
if (blockTxAction) return blockTxAction(); | ||
throw new PreventTransactionError( | ||
'Transaction is prevented due to inscribed utxos in the transaction. Please contact support for more information.' | ||
); | ||
}, [blockTxAction]); | ||
|
||
const checkIfUtxosListIncludesInscribed = useCallback(async () => { | ||
setIsLoading(true); | ||
try { | ||
// no need to check for inscriptions on testnet | ||
if (isTestnet) { | ||
return false; | ||
} | ||
|
||
if (txids.length === 0) { | ||
throw new Error('Utxos list cannot be empty'); | ||
} | ||
|
||
const responses = await Promise.all( | ||
txids.map(id => client.bestinslotInscriptionsApi.getInscriptionsByTransactionId(id)) | ||
); | ||
|
||
const hasInscribedUtxo = responses.some(resp => { | ||
return resp.data.length > 0; | ||
}); | ||
|
||
if (hasInscribedUtxo) { | ||
void analytics.track('utxos_includes_inscribed_one', { | ||
txids, | ||
}); | ||
preventTransaction(); | ||
return true; | ||
} | ||
|
||
return false; | ||
} catch (e) { | ||
if (e instanceof PreventTransactionError) { | ||
throw e; | ||
} | ||
|
||
void analytics.track('error_checking_utxos_from_bestinslot', { | ||
txids, | ||
}); | ||
|
||
// fallback to ordiscan, refetch is used here as request is disabled by default | ||
await refetchOrdInscriptionsList(); | ||
|
||
const hasInscribedUtxo = ordInscriptionsList?.pages.some(page => { | ||
return page.data.some(v => { | ||
return txids.includes(v.owner_output); | ||
}); | ||
}); | ||
|
||
// if there are inscribed utxos in the transaction, and no error => prevent the transaction | ||
if (hasInscribedUtxo && !isOrdRequestError) { | ||
preventTransaction(); | ||
return true; | ||
} | ||
|
||
// if there is an error fetching inscriptions from ordiscan => throw an error | ||
if (isOrdRequestError) { | ||
void analytics.track('error_checking_utxos_from_ordiscan', { | ||
txids, | ||
}); | ||
|
||
throw new Error( | ||
'Error trying to check transaction for inscribed utxos. Please try again later or contact support.' | ||
); | ||
} | ||
|
||
return true; | ||
} finally { | ||
setIsLoading(false); | ||
} | ||
}, [ | ||
client.bestinslotInscriptionsApi, | ||
txids, | ||
isTestnet, | ||
analytics, | ||
preventTransaction, | ||
refetchOrdInscriptionsList, | ||
ordInscriptionsList, | ||
isOrdRequestError, | ||
]); | ||
|
||
return { | ||
checkIfUtxosListIncludesInscribed, | ||
isLoading, | ||
}; | ||
} |