It printed "paste" because you passed the following arguments to os.queueEvent: "paste", "paste", "h", nil
The first argument to os.queueEvent is the event type, for the paste event the second is what was actually in the clipboard when ctrl+v was pressed, so that is where the "h" should be.
os.queueEvent("paste","h")
Although that would probably work I would personally use the char and key event (I would queue both solely because many programs use both events for different things).
str = "hello"
for letter in string.gmatch(".") do
os.queueEvent("char",letter)
os.queueEvent("key", keys[letter],false)
end
Keep in mind though that this would break if there was more than 120ish letters in the string.
edit:
Luckily all of the built in scripts support char events that are more than a single char (whether or not this was intentional).
example:
str = "hello"
os.queueEvent("char",str,false)