Once you have added all your wallets, Koinly will try to find & match transfers between them. Transfers between your own wallets are not taxed, so having them correctly identified can significantly lower your calculated taxable gains.

πŸ”΅ Example

Let's say you have 2 wallets: Coinbase and MetaMask.

  • You send out 1 ETH from Coinbase.

  • A few minutes later, you receive 1 ETH into your MetaMask wallet.

Here you would initially have 2 separate transactions - a withdrawal of 1 ETH from Coinbase and a deposit of 1 ETH to MetaMask:

But Koinly can see that you are just moving coins from one wallet into another so it automatically merges them into a single transfer transaction. The difference between the sending and receiving amount would be added as a transfer fee. The merged transaction will look like this:

Auto-matching rules

Koinly will automatically merge a deposit and a withdrawal into a transfer if the following rules are met:

  1. Likeness check
    The deposit and withdrawal are for the same asset/currency

  2. Interval check
    Both transactions should be within 12 hours of each other

  3. Chronology check
    The withdrawal happens before the deposit.

  4. Amount check
    The deposited amount is equal to or smaller than the withdrawn amount

  5. Difference check
    The deposit is not significantly smaller than the withdrawal - the maximum difference between the deposit and the withdrawal is 20%.
    Koinly will merge 0.10 BTC >> 0.8 BTC, but will not merge 0.15 ETH >> 0.05 ETH

  6. Hash check
    Transactions have the same transaction hash, or one of the transactions doesn't have a hash at all, or none of them do.

Can Koinly match bridging transactions?

The short answer is - it depends. If you bridge your asset from one blockchain to another, the asset you receive might be a slightly different token than the one you've sent.

  • If the token is the same, then bridging is no different than transferring assets between wallets and Koinly will merge them automatically (assuming all other checks are passed)

  • If the token is different (it may be just the wrapped version, like sending ETH from Ethereum and receiving WETH on Polygon) then Koinly will not merge it automatically, as it's considered a cross-wallet trade.
    In such cases, if all the other checks are passed, you can just merge this manually - note that it will appear as an Exchange, not a transfer (because of the difference in the asset sent and received)

How can I create a Transfer manually?

Before making any manual changes, first ensure your data is accurate. Most issues with transfer matching come from incomplete or incorrect data:

  • Deposits and withdrawals files not imported from an exchange

  • CSV files imported in the wrong timezone

  • etc.

If your transaction history still needs manual amendments after importing, fixing a transfer depends on the scenario - see three possible situations below:

One of the transactions is missing

The transfer could not be automatically merged, because there is only a deposit to one of your wallets, without the corresponding withdrawal from the other wallet.

βœ… Solution: Edit the one transaction that you have. After you change the type to "transfer", you will be able to fill the other side of the transaction.

Both the deposit and the withdrawal are missing

The imported data was incomplete and didn't contain any information about this particular transfer. It has to be added manually.

βœ… Solution: Click "add transaction" and choose either the deposit or withdrawal. Then change the type to "Transfer" and fill all the necessary information.

The deposit and withdrawal are present but weren't merged automatically

This happens if the transactions failed on one of our checks described above.

βœ… Solution: Edit the transactions accordingly so that they pass the checks required to match them into a transfer. Then merge them manually.

The most common issues include:

  • Timestamp mismatch: withdrawal happens after the deposit

  • Amount mismatch: the deposit is larger than the withdrawal (i.e. due to rounding, can be on the 6th decimal place)

🟑 Note: If the transaction was imported via API, it cannot be edited. In such cases, you need to soft-deleted and manually add a mirror transaction with corrected data.

Koinly has created an incorrect transfer pair

Most of the time the transaction matching will work well but sometimes Koinly can make mistakes especially if you are moving the same amount into different wallets.

For example, if the example above was, in fact, a transfer involving a transfer of 1 ETH between three wallets:

  • Transfer of 1 ETH from Coinbase to MetaMask, and right after that:

  • Transfer of 1 ETH from MetaMask to Binance

In such cases, Koinly may incorrectly merge wrong transactions into transfers. A withdrawal from Coinbase and a deposit to Binance fulfill the requirements of transfer matching, so Koinly might merge them:

This leaves the deposit and withdrawal from MetaMask "without a pair" to merge.

We are constantly working on improving our algorithms so this is rare but can happen - especially when Coinbase and Binance are added to Koinly first, and MetaMask later. After all, Koinly didn't know about the MetaMask transactions at that time.

βœ… Solution: You can split the transactions and then merge them manually in the correct order.

Why is there a profit/loss on a transfer to my own wallet?

  • The transactions are not merged into a transfer
    You can see a large profit here because the transactions are not merged - and a withdrawal is equivalent to selling the asset at market price:

  • The profit is on the disposal of the transfer fee only
    If you merge the transaction above, it still shows a profit - but it's on the disposal of fee only. See Why is there a profit/loss on Cost transactions for an explanation of how a cost transaction (a transfer fee) can still create profits

    • If you do not want to realize gains/losses on transfer fees immediately, only once the lot is completely sold, then you can toggle the setting Treat transfer fees as disposals to OFF.

Did this answer your question?