# Transfer Tokens and NFTs

This guide provides a step-by-step walkthrough for transferring fungible tokens (both native and custom) and non-fungible tokens (NFTs or assets) between accounts using the OCAP Client. The primary method for all transfers is `client.transfer()`.

One key feature to remember is that a new account is automatically created on-chain when it receives its first incoming transaction. This means you can transfer tokens or assets to a brand new address without any prior setup for the recipient.


## The `transfer` Method

The `client.transfer()` method is a versatile helper function that simplifies the process of sending assets and tokens. It constructs, signs, and sends the appropriate transaction (`transferV2Tx`) to the blockchain in a single call.

### Parameters

<x-field-group>
  <x-field data-name="to" data-type="string" data-required="true">
    <x-field-desc markdown>The recipient's account address. This must be a valid DID address.</x-field-desc>
  </x-field>
  <x-field data-name="wallet" data-type="WalletObject" data-required="true" data-desc="The sender's wallet object used to sign the transaction."></x-field>
  <x-field data-name="token" data-type="number" data-default="0">
    <x-field-desc markdown>The amount of the chain's native token to transfer. The client handles the conversion to the correct decimal units automatically.</x-field-desc>
  </x-field>
  <x-field data-name="assets" data-type="string[]" data-default="[]" data-desc="An array of asset addresses (NFTs) to transfer."></x-field>
  <x-field data-name="tokens" data-type="object[]" data-default="[]">
    <x-field-desc markdown>An array of custom fungible token objects to transfer.</x-field-desc>
    <x-field data-name="address" data-type="string" data-required="true" data-desc="The address of the custom token contract."></x-field>
    <x-field data-name="value" data-type="number" data-required="true" data-desc="The amount of the custom token to transfer."></x-field>
  </x-field>
  <x-field data-name="memo" data-type="string" data-required="false" data-desc="An optional message or note to include with the transaction."></x-field>
  <x-field data-name="delegator" data-type="string" data-required="false">
    <x-field-desc markdown>If the `wallet` is acting on behalf of another account, this should be the address of the delegating account. See the [Delegate Permissions](./how-to-guides-delegate-permissions.md) guide for more details.</x-field-desc>
  </x-field>
</x-field-group>

### Returns

<x-field data-name="Promise<string>" data-type="Promise">
  <x-field-desc markdown>A Promise that resolves to the transaction hash upon successful submission to the blockchain.</x-field-desc>
</x-field>


## Step-by-Step Examples

### Prerequisites

Before you start, make sure you have:

1. An initialized `GraphQLClient` connected to a chain host like `https://beta.abtnetwork.io`.
2. A sender's wallet object (`senderWallet`) that is funded with enough tokens to cover the transfer and transaction fees.
3. A recipient's wallet object (`recipientWallet`) to get their address. The recipient's account does not need to exist on-chain yet.

```javascript Basic Setup icon=logos:javascript
import GraphQLClient from '@ocap/client';
import { fromRandom } from '@ocap/wallet';

// 1. Initialize the client
const client = new GraphQLClient({ endpoint: 'https://beta.abtnetwork.io/api' });

// 2. Create wallets for sender and recipient
// In a real application, the sender's wallet would be loaded, not created randomly.
const senderWallet = fromRandom(); // Assume this wallet is funded
const recipientWallet = fromRandom();

console.log(`Sender Address: ${senderWallet.address}`);
console.log(`Recipient Address: ${recipientWallet.address}`);

// To fund the sender's wallet for this example, use the faucet:
// https://faucet.abtnetwork.io/
```

### Example 1: Transferring Native Tokens

This example shows how to send 10 native tokens from the sender to the recipient.

```javascript Transfer Native Tokens icon=logos:javascript
async function transferNativeTokens() {
  try {
    const hash = await client.transfer({
      to: recipientWallet.address,
      token: 10, // The amount of native tokens to send
      wallet: senderWallet,
      memo: 'Sending you 10 native tokens!'
    });
    console.log('Native token transfer successful. Tx Hash:', hash);
  } catch (err) {
    console.error('Error transferring tokens:', err);
  }
}

transferNativeTokens();
```

### Example 2: Transferring an NFT (Asset)

To transfer an NFT, you need its unique asset address. First, you would create or acquire an asset (see [Manage Assets (NFTs)](./how-to-guides-manage-assets.md)). For this example, let's assume `senderWallet` already owns an NFT with the address `zNKj...`.

```javascript Transfer an NFT icon=logos:javascript
async function transferNFT() {
  // Assume this is the address of an NFT owned by senderWallet
  const nftAddress = 'zNKjL4wTmxQPk5nN2ADDPCd58286b2de3f3e';

  try {
    const hash = await client.transfer({
      to: recipientWallet.address,
      assets: [nftAddress], // An array of asset addresses
      wallet: senderWallet,
      memo: 'Here is the NFT you wanted.'
    });
    console.log('NFT transfer successful. Tx Hash:', hash);
  } catch (err) {
    console.error('Error transferring NFT:', err);
  }
}

transferNFT();
```

### Example 3: Transferring Custom Tokens

This example demonstrates how to transfer a custom fungible token. You need the token's contract address. See the [Manage Tokens](./how-to-guides-manage-tokens.md) guide for information on creating custom tokens.

```javascript Transfer Custom Tokens icon=logos:javascript
async function transferCustomToken() {
  // Assume this is the address of a custom token owned by senderWallet
  const customTokenAddress = 'z37bA4x...'; 

  try {
    const hash = await client.transfer({
      to: recipientWallet.address,
      wallet: senderWallet,
      tokens: [
        { address: customTokenAddress, value: 50 } // 50 units of a custom token
      ],
      memo: 'Sending 50 custom tokens.'
    });
    console.log('Custom token transfer successful. Tx Hash:', hash);
  } catch (err) {
    console.error('Error transferring custom token:', err);
  }
}

transferCustomToken();
```

### Example 4: A Combined Transfer

You can send native tokens, custom tokens, and multiple NFTs all in a single, atomic transaction. This is highly efficient.

```javascript Combined Transfer icon=logos:javascript
async function combinedTransfer() {
  // Assume these are addresses of assets and tokens owned by senderWallet
  const nftAddress1 = 'zNKjL4wTmxQPk5nN2ADDPCd58286b2de3f3e';
  const nftAddress2 = 'zNKiabcdeQPk5nN2ADDPCd58286b2defghj';
  const customTokenAddress = 'z37bA4x...'; // Address of a custom fungible token

  try {
    const hash = await client.transfer({
      to: recipientWallet.address,
      wallet: senderWallet,
      token: 5, // 5 native tokens
      assets: [nftAddress1, nftAddress2], // An array of two NFTs
      tokens: [
        { address: customTokenAddress, value: 50 } // 50 units of a custom token
      ],
      memo: 'Sending a mix of tokens and NFTs.'
    });
    console.log('Combined transfer successful. Tx Hash:', hash);
  } catch (err) {
    console.error('Error with combined transfer:', err);
  }
}

combinedTransfer();
```

By following these examples, you can easily implement token and NFT transfers in your application. For more details on creating the items you wish to transfer, please see the related guides.

### Further Reading

* [How to Manage Assets (NFTs)](./how-to-guides-manage-assets.md)
* [How to Manage Tokens](./how-to-guides-manage-tokens.md)
* [High-level API](./api-reference-transaction-helpers.md)
