> For the complete documentation index, see [llms.txt](https://docs.bitsafe.finance/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.bitsafe.finance/beth/guides/transfer-and-receive-beth.md).

# Transfer and receive BETH

[BETH overview](/beth/overview.md) · [BETH environments and prerequisites](/beth/get-started/environments-and-prerequisites.md) · [Transfer and receive BETH](/beth/guides/transfer-and-receive-beth.md)

### Outcome

Send BETH from one Canton party to another, read the result of the transfer, and accept, reject, or cancel a transfer offer.

### Before you start

* Use an Engineering-approved `bitsafe-token-lib`, `canton-lib`, DAR, and Canton compatibility row. This guide describes `bitsafe-token-lib` `v0.2.0`.
* Confirm authentication, the sender party, the receiver party, and the registry URL for the intended environment.
* Confirm the BETH instrument identifier. The identifier is the instrument ID `BETH` and the administrator party. The library matches both values exactly.
* Query the sender's holdings, and confirm that the sender has enough available BETH.

### How a transfer settles

A transfer has one of two outcomes:

* **Offer:** the registry creates a transfer instruction. The receiver accepts or rejects it, or it expires at `execute_before`. The sender can cancel it before the receiver acts.
* **Settled on submission:** the registry moves the BETH at once, and no offer exists. The registry does this for a self-transfer and for a receiver that pre-approved the sender.

The library tells you which outcome occurred. Do not assume that the receiver must accept.

### 1. Send BETH

Call `bitsafe_token::transfer::submit` as the sender. The call returns a `TransferReceipt`.

```rust
let receipt = bitsafe_token::transfer::submit(bitsafe_token::transfer::Params {
    transfer: bitsafe_token::Transfer {
        sender: sender_party.clone(),
        receiver: receiver_party.clone(),
        amount: bitsafe_token::DamlDecimal::parse("0.01")?,
        instrument_id: bitsafe_token::InstrumentId {
            admin: decentralized_party_id.clone(),
            id: bitsafe_token::tokens::beth::TICKER.to_string(),
        },
        requested_at: chrono::Utc::now().to_rfc3339(),
        execute_before: (chrono::Utc::now() + chrono::Duration::hours(168)).to_rfc3339(),
        input_holding_cids: None, // None lets the library select the sender's holdings
        meta: None,
    },
    ledger_host: ledger_host.clone(),
    access_token: sender_token.clone(),
    registry_url: registry_url.clone(),
    decentralized_party_id: decentralized_party_id.clone(),
}).await?;
```

Run the repository example with `ASSET=beth cargo run --example send`.

### 2. Read the transfer receipt

The receipt contains three fields:

| Field                | Meaning                                                                                          |
| -------------------- | ------------------------------------------------------------------------------------------------ |
| `outcome`            | `TransferOutcome::Pending` for an offer, or `TransferOutcome::Completed` for a settled transfer. |
| `sender_change_cids` | The sender holdings that remain after the transfer.                                              |
| `update_id`          | The Canton update identifier of the transaction.                                                 |

`receipt.outcome.transfer_offer_cid()` returns the offer contract ID for a pending transfer. It returns `None` for a settled transfer. Record the offer ID, because the receiver and the sender need it in the next steps.

### 3. Receive BETH

Skip this step when the outcome is `Completed`. The receiver already holds the BETH.

For a pending transfer, the receiver authenticates as the receiver party and does one of these actions:

* **Accept one offer:** call `bitsafe_token::accept::submit` with the offer contract ID and the receiver party.
* **Accept all offers:** call `bitsafe_token::accept::accept_all`. It returns one result for each offer and the successful and failed counts. Read `failed_count` before you treat the step as done.
* **Reject an offer:** call `bitsafe_token::reject::submit` with the offer contract ID and the receiver party. The BETH returns to the sender.

To list the receiver's pending offers, run `ASSET=beth cargo run --example list_incoming_offers`.

### 4. Cancel an outgoing offer

The sender can withdraw an offer that the receiver has not accepted or rejected:

* `bitsafe_token::cancel_offers::submit` withdraws one offer.
* `bitsafe_token::cancel_offers::withdraw_batch` withdraws a list of offers.
* `bitsafe_token::cancel_offers::withdraw_all` withdraws all pending offers of the instrument.

To list the sender's pending offers, run `ASSET=beth cargo run --example list_outgoing_offers`. To withdraw them, run `ASSET=beth cargo run --example cancel_offers`.

### Token Standard V2

Each operation in this guide also has a Token Standard V2 form in a `v2` submodule, such as `bitsafe_token::transfer::v2::submit`. The V2 transfer takes the sender and the receiver as `bitsafe_token::Account` values instead of party strings. The accept, reject, and cancel V2 forms take the same parameters as V1.

Run the V2 transfer example with `ASSET=beth cargo run --example send_v2`.

### Expected result

* The sender has a `TransferReceipt` and a recorded outcome for each transfer.
* For a settled transfer, the receiver holds the BETH.
* For an offer, the receiver accepted or rejected it, the sender cancelled it, or it expired.

### Troubleshooting

| Symptom                                     | Check                                                                                                       |
| ------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| The receiver sees no offer.                 | Read the sender's receipt. A `Completed` outcome creates no offer, and the receiver already holds the BETH. |
| The receiver's balance does not change.     | Confirm the instrument ID and the administrator. The library ignores holdings of another administrator.     |
| Accept or reject fails.                     | Confirm that the token authenticates the receiver party and that the offer is still active.                 |
| The transfer fails with insufficient funds. | Query the sender's holdings. Holdings locked in another offer are not available.                            |

### Technical sources

* [`bitsafe-token-lib` README at `v0.2.0`](https://github.com/DLC-link/bitsafe-token-lib/blob/v0.2.0/README.md)
* [Transfer implementation and receipt model](https://github.com/DLC-link/canton-lib/blob/v0.11.0/crates/token/src/transfer.rs)
* [Accept implementation](https://github.com/DLC-link/canton-lib/blob/v0.11.0/crates/token/src/accept.rs)
* [Reject implementation](https://github.com/DLC-link/canton-lib/blob/v0.11.0/crates/token/src/reject.rs)
* [Cancel implementation](https://github.com/DLC-link/canton-lib/blob/v0.11.0/crates/token/src/cancel_offers.rs)
* [Send example](https://github.com/DLC-link/bitsafe-token-lib/blob/v0.2.0/examples/send.rs)
* [Reject example](https://github.com/DLC-link/bitsafe-token-lib/blob/v0.2.0/examples/reject_transfer.rs)

### Related pages

* [Batch transfers and UTXO management](/beth/guides/batch-transfers-and-management.md)
* [Token standard and contract model](/beth/concepts-and-reference/token-standard-and-contract-model.md)

### Next step

👉 **Send to many receivers:** [Batch transfers and UTXO management](/beth/guides/batch-transfers-and-management.md).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.bitsafe.finance/beth/guides/transfer-and-receive-beth.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
