Images are displaying as blank images

You should generate the attachment metadata such as width and height — and file path, and also thumbnails, after you created the attachment:

$attach_id = wp_insert_attachment( $attachment, $filename );

if ( $attach_id ) {
    require_once ABSPATH . 'wp-admin/includes/image.php';
    $metadata = wp_generate_attachment_metadata( $attach_id, $filename );
    wp_update_attachment_metadata( $attach_id, $metadata );
}
$attach_id = wp_insert_attachment( $attachment, $filename );

if ( $attachment = get_post( $attach_id ) ) {
    require_once ABSPATH . 'wp-admin/includes/image.php';
    wp_maybe_generate_attachment_metadata( $attachment );
}

Or you could simply use media_handle_sideload() instead of wp_handle_sideload() to create the attachment (and its metadata). So you’d use this in place of what you currently have in between the // upload file to server and return $attach_id;:

// upload file to server
require_once ABSPATH . 'wp-admin/includes/media.php';
require_once ABSPATH . 'wp-admin/includes/image.php';
$attach_id = media_handle_sideload( $file, 0 );

return $attach_id;