pub fn try_parse_withdrawal_request(
	network: BitcoinNetwork,
	tx: Transaction,
) -> SBTCResult<WithdrawalRequestData> {
	let mut output_iter = tx.output.into_iter();

	let data_output = output_iter.next().ok_or(SBTCError::NotSBTCOperation)?;

	let mut instructions_iter = data_output.script_pubkey.instructions();

	let Some(Ok(Instruction::Op(OP_RETURN))) = instructions_iter.next() else {
		return Err(SBTCError::NotSBTCOperation);
	};

	let Some(Ok(Instruction::PushBytes(mut data))) = instructions_iter.next()
	else {
		return Err(SBTCError::NotSBTCOperation);
	};

	let withdrawal_data =
		WithdrawalRequestDataOutputData::codec_deserialize(&mut data)
			.map_err(|_| SBTCError::NotSBTCOperation)?;

	let recipient_pubkey_output =
		output_iter.next().ok_or(SBTCError::NotSBTCOperation)?;

	let recipient_address = BitcoinAddress::from_script(
		&recipient_pubkey_output.script_pubkey,
		network,
	)
	.map_err(|_| SBTCError::NotSBTCOperation)?;

	let drawee_stacks_public_key = recover_signature(
		withdrawal_data.amount(),
		&recipient_address,
		&withdrawal_data.signature(),
	)?;
	let drawee_stacks_address_version = match network {
		BitcoinNetwork::Bitcoin => StacksAddressVersion::MainnetSingleSig,
		_ => StacksAddressVersion::TestnetSingleSig,
	};
	let drawee_stacks_address = StacksAddress::from_public_key(
		drawee_stacks_address_version,
		&drawee_stacks_public_key,
	);

	let fulfillment_fee_output =
		output_iter.next().ok_or(SBTCError::NotSBTCOperation)?;

	let sbtc_wallet = BitcoinAddress::from_script(
		&fulfillment_fee_output.script_pubkey,
		network,
	)
	.map_err(|_| SBTCError::NotSBTCOperation)?;

	Ok(WithdrawalRequestData {
		payee_bitcoin_address: recipient_address,
		drawee_stacks_address,
		amount: withdrawal_data.amount(),
		signature: withdrawal_data.signature(),
		fulfillment_amount: fulfillment_fee_output.value,
		sbtc_wallet,
	})
}
Tries to parse a Bitcoin transation into a withdrawal request
sbtc-core/src/operations/op_return/withdrawal_request.rs