Skip to main content
A transfer moves an item between existing owners. Unlike a claim, the item already has an owner, so only that current owner can complete it: Endstate authorizes the move and hands back a transaction, but never moves an item on an owner’s behalf. That is why transfer() takes no execution option - there is no Endstate-submitted mode. transfer() prepares the move against the active session useSession holds and returns a Transfer whose transaction field is the authorized payload. The current owner broadcasts that transaction with their own signer, outside this hook - so preparing and broadcasting are separate steps, and transfer() does not wait for settlement by default.

Example

Once the owner broadcasts the returned transaction, poll the original transfer for settlement - session.transfers.waitUntilSettled(data.id) with the session from useSession(). Calling transfer() again would create a second transfer, not observe the first (each call uses a fresh idempotency key). Broadcast well within about 30 minutes: the signed authorization expires after that and the transfer settles expired.

The transfer call

string
required
The recipient’s EVM wallet address (0x followed by 40 hex characters) - the account that will receive the item. Required: a transfer always names its recipient.
string
Makes the transfer safe to retry. Replaying the same key with the same body returns the original transfer; omit it and core generates one.
boolean
default:"false"
Waiting is opt-in because the owner broadcasts the transaction externally. Leave it unset to resolve as soon as the transfer is prepared; set it to true to poll to a terminal status after the owner has broadcast.

Returns

(args) => Promise<Transfer>
Prepares the transfer and returns it with an authorized transaction. Rejects with a typed error; throws if there is no active session yet. It never broadcasts - the current owner does that with their own signer.
TransferStatus
"idle" before a transfer, "preparing" while the request is in flight, "settling" once prepared and awaiting the owner’s broadcast, then terminal "confirmed", "expired", or "failed"; "error" when the call throws. On "expired" or "failed", prepare a new transfer.
Transfer | null
The latest transfer resource, including the authorized transaction to broadcast, or null before the first call.
Error | null
The failure that moved status to "error", or null. Branch on the error code; see Errors and retries.
() => void
Clears status, data, and error back to idle and aborts an in-flight settlement poll.
Broadcasting the returned transaction with the current owner’s signer is a core concern, not part of this hook. See session.transfers.create for the transaction shape and who must send it.

See also

Transfer ownership

The transfer flow, who broadcasts, and settlement in prose.

useClaim

Assign first ownership out of a tap - the sibling action.

session.transfers.create

The request body, the returned transaction, and every error code.

useSession

The session a transfer is prepared against.