Escrow, end to end

This guide follows one escrow from open to release. You need two funded wallets, one for the payer and one for the payee, each served by its own payment_node.

1. Agree on the job

Before any money moves, both robots agree on the payee address, the amount, a timeout, and a terms hash that identifies the job. How they agree is up to you. An invoice on /payment_requests is one way.

2. Open

The payer opens the escrow through the escrow action. The easiest way is the EscrowClient helper:

from robopay_core.client import EscrowClient

class Payer(Node):
    def __init__(self):
        super().__init__("payer")
        self.escrow = EscrowClient(self)

    def hire(self, payee):
        self.escrow_handle = self.escrow.open(
            payer=self.my_address,
            payee=payee,
            amount="2.50",
            timeout_seconds=600,
            on_done=self._finished,
        )

    def _finished(self, result):
        self.get_logger().info(f"escrow {result.status}: {result.tx_hash}")

The action’s feedback reports the escrow_id as soon as the deposit confirms. Share that id with the payee. The id is derived from the escrow’s contents, so both sides can check it describes what they agreed.

The first escrow from a wallet also sends a one-time USDC approval so the contract can take the deposit. Later escrows skip it.

3. Do the work

The payee can confirm the funds are really locked before starting, by reading the escrow from the contract. Nothing about the payee’s side depends on trusting the payer’s word.

4. Sign

When each robot is satisfied, it signs:

self.escrow.sign(escrow_id, role="payer")   # on the payer
self.escrow.sign(escrow_id, role="payee")   # on the payee

Or from the command line:

ros2 service call /escrow/sign robopay_interfaces/srv/EscrowSign \
  "{escrow_id: '0x...', signer_address: '<your-address>', role: 'payee'}"

Each signature has to reach the other side. See Signature exchange.

5. Release

Once the payer’s node holds both signatures, its escrow action submits the release. The contract checks both signatures and transfers the funds to the payee. The action finishes with released: true and the transaction hash.

If it goes wrong

If both signatures do not arrive before the deadline, the escrow can be refunded. The payer’s resolver does this automatically. Anyone else can also call refund on the contract after the deadline; the money can only go back to the payer.

Releases and refunds are safe to retry. If the escrow has already been settled, the node reports that instead of sending a failing transaction.

What escrow does not do

Escrow guarantees that neither robot can take the money alone. It does not decide whether the job was done. That decision comes from your own sensing: a load cell, an RFID scan, a camera frame, a human confirmation.