> ## Documentation Index
> Fetch the complete documentation index at: https://build.onswig.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Sell transfer

## Introduction

Move the approved crypto amount from a Swig wallet to the provider’s deposit
for an existing sell order. The order must be `awaiting-transfer` and include
deposit details. Use this flow after [sell checkout](https://build.onswig.com/developer-sdk/ramp-sell.md),
including recovery of a submitted attempt after an uncertain response.

The examples use the same mainnet client, saved sell order, and configured
requester authority. Application callbacks own signing and durable storage.

## SDK examples

### Prepare and submit the sell transfer

Review the provider’s current deposit against the approved order. `signTransaction` and `saveTransferAttempt` (snake\_case in Python/Rust) are application-owned callbacks for signing and durable storage.

```typescript TypeScript theme={null}
import { signPreparedTransaction } from '@swig-wallet/developer-sdk/signers';

const prepared = await swig.ramp.prepareTransfer({
  orderId: sellOrder.id,
  requesterAuthority: { ed25519: { publicKey: requester } },
  feePayer,
});

const signed = await signPreparedTransaction(prepared.preparedTransaction, {
  signTransaction,
});

await saveTransferAttempt({
  orderId: sellOrder.id,
  transferId: prepared.transfer.transferId,
  signedTransaction: signed.transaction,
});

const transfer = await swig.ramp.submitTransfer({
  orderId: sellOrder.id,
  transferId: prepared.transfer.transferId,
  signedTransaction: signed.transaction,
});
```

```python Python theme={null}
from swig_developer_sdk.signers import sign_prepared_transaction

prepared = await swig.ramp.prepare_transfer(
    order_id=sell_order.id,
    requester_authority={"ed25519": {"publicKey": requester}},
    fee_payer=fee_payer,
)

signed = await sign_prepared_transaction(
    prepared.prepared_transaction,
    sign_transaction=sign_transaction,
)

await save_transfer_attempt(
    order_id=sell_order.id,
    transfer_id=prepared.transfer.transfer_id,
    signed_transaction=signed.transaction,
)

transfer = await swig.ramp.submit_transfer(
    order_id=sell_order.id,
    transfer_id=prepared.transfer.transfer_id,
    signed_transaction=signed.transaction,
)
```

```rust Rust theme={null}
use swig_developer_sdk::{
    PrepareRampTransferArgs, SubmitRampTransferArgs, WalletAuthority,
};

let prepared = ramp
    .prepare_transfer(PrepareRampTransferArgs {
        order_id: order_id.clone(),
        requester_authority: WalletAuthority::Ed25519 {
            public_key: requester_public_key,
        },
        fee_payer,
    })
    .await?;

let signed_transaction = sign_transaction(&prepared.prepared_transaction).await?;

save_transfer_attempt(
    &order_id, &prepared.transfer.transfer_id, &signed_transaction,
).await?;

let transfer = ramp
    .submit_transfer(SubmitRampTransferArgs {
        order_id: order_id.clone(),
        transfer_id: prepared.transfer.transfer_id.clone(),
        signed_transaction: Some(signed_transaction),
    })
    .await?;
```

Preparation returns transaction bytes once. Save the order ID, transfer ID, and exact signed bytes before submission. The Rust signing callback returns a native `VersionedTransaction`.

### Resolve a submitted transfer

For an attempt already in `submitted`, resolve the same transfer without signing or paying again.

```typescript TypeScript theme={null}
await swig.ramp.submitTransfer({
  orderId: sellOrder.id,
  transferId: prepared.transfer.transferId,
});
```

```python Python theme={null}
await swig.ramp.submit_transfer(
    order_id=sell_order.id,
    transfer_id=prepared.transfer.transfer_id,
)
```

```rust Rust theme={null}
use swig_developer_sdk::SubmitRampTransferArgs;

let transfer = ramp
    .submit_transfer(SubmitRampTransferArgs {
        order_id,
        transfer_id,
        signed_transaction: None,
    })
    .await?;
```

## Flow

```text theme={null}
Prepare deposit transfer
  └─ Review and sign
      └─ Save exact bytes
          └─ Submit
              └─ Resolve
```

## Input

| Operation | Input | Requirement |
| :- | :- | :- |
| Prepare transfer | `orderId`, `requesterAuthority`, `feePayer` | Eligible sell with a ready deposit. Rust supports Ed25519/secp256r1 on mainnet, without ParticipantSet approvals. |
| Submit transfer | `orderId`, `transferId`, optional `signedTransaction` | A prepared attempt requires saved signed bytes. A submitted attempt can be resolved without bytes. Keep the same IDs throughout. |

TypeScript names are shown; Python uses snake\_case. Preparation and transfer
submission are not retried automatically; Rust quotes also send once.
Only prepare a replacement after the previous attempt is failed or expired
and the order is still eligible. An uncertain response alone is insufficient.

## Output

| Operation | Field | Meaning |
| :- | :- | :- |
| Preparation | `preparedTransaction`, `deposit`, `transfer` | Unsigned transaction and the exact transfer attempt. Order reads cannot recover its transaction bytes. |
| Transfer | `transferId`, `state`, `expiresAt`, optional `solanaSignature` | Prepared, submitted, landed, failed, or expired. Landed means confirmed or better; order settlement is tracked separately. |

## Errors

| Error | Meaning |
| :- | :- |
| `the deposit address is not ready` | Checkout has not produced a transferable deposit; preparation must wait. |
| Transfer not eligible | Order or attempt state does not permit preparation, resubmission, or replacement. |
| Uncertain submission | The same transfer may already have broadcast. Resolve its stored IDs and state before considering another attempt. |
| Provider or network failure | The provider, RPC, or transfer confirmation is unavailable; preserve attempt identifiers and signed bytes. |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.