import { getAppPrivateKey , Wallet } from '@stacks/wallet-sdk' ; import { TransactionPayload } from '@stacks/connect' ; import { decodeToken , TokenVerifier } from 'jsontokens' ; import { getPublicKeyFromPrivate } from '@stacks/encryption' ; import { getAddressFromPrivateKey , TransactionVersion } from '@stacks/transactions' ; function getTransactionVersionFromRequest ( tx ) { const { network } = tx ; if ( ! network ) return TransactionVersion . Mainnet ; if ( ! [ TransactionVersion . Mainnet , TransactionVersion . Testnet ] . includes ( network . version ) ) { throw new Error ( 'Invalid network version provided' ) ; } return network . version ; } export const UNAUTHORIZED_TX_REQUEST = 'The transaction request provided is not signed by this wallet.' ; returns throws export const verifyTxRequest = async ( { requestToken , wallet , appDomain , } ) : Promise < TransactionPayload > => { const token = decodeToken ( requestToken ) ; const tx = token . payload as unknown as TransactionPayload ; const { publicKey , stxAddress } = tx ; const txVersion = getTransactionVersionFromRequest ( tx ) ; const verifier = new TokenVerifier ( 'ES256k' , publicKey ) ; const isSigned = await verifier . verifyAsync ( requestToken ) ; if ( ! isSigned ) { throw new Error ( 'Transaction request is not signed' ) ; } const foundAccount = wallet . accounts . find ( account => { const appPrivateKey = getAppPrivateKey ( { account , appDomain , } ) ; const appPublicKey = getPublicKeyFromPrivate ( appPrivateKey ) ; if ( appPublicKey !== publicKey ) return false ; if ( ! stxAddress ) return true ; const accountStxAddress = getAddressFromPrivateKey ( account . stxPrivateKey , txVersion ) ; if ( stxAddress !== accountStxAddress ) return false ; return true ; } ) ; if ( ! foundAccount ) { throw new Error ( UNAUTHORIZED_TX_REQUEST ) ; } return tx ; } ;