Solana DEV #02: Retrieve all Deposit transactions of your wallet
Tags: solana, webdev, typescript, blockchain
Published: 2022-08-29 14:07:28

If you use Phantom wallet to pay for transactions on Solana blockchain, you may recognize that every time you send SOL or SPL tokens to another address, that transaction will be recorded and listed on Phantom wallet interface. 

![Phantom deposit transaction interface](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rhhfn8drqbe9endnk0kt.png)


At first, I thought that it is just similar to any other data fetched by using **`getProgramAccounts`** with filtering stuffs. However, it does not work that way. 

## Fetching signatures and transactions
To fetch all deposit transactions of one address, you must get all signatures of that address by using the method `getSignaturesForAddress`
```typescript
const signatureInfos = await connection.getSignaturesForAddress(vaultAddress);
```
And then map the info to get only transaction signatures
```typescript
const signatures = signatureInfos.map(sig => sig.signature);
const transactions = await connection.getParsedTransactions(signatures);
```
This approach has a very big problem. It does not allow you to filter out fetched signatures like what you usually do with `getProgramAccounts`. And in that way, it will just fetch a bulk load of transactions from your address as your address have other wallet interaction beside receive and send coins. To make it more efficient, I try to filter out success signatures from the return data
```typescript
const filteredSignatureInfos = signatureInfos.filter(sig => !sig.err && !sig.memo);
```
But unlucky, if your wallet has around 300 or more transactions, the RPC won't allow you to fetch as there's a rate limit. I don't know if there are any other better approaches but this is the one that I found. 

### How to improve the approach?
This might not be an acceptable answer but there's a few ways that you can improve the case.
- Trying to separate a **vault** from a **wallet**. A vault will be a **PDA** that use the wallet address as a seed. In that way, all transactions that the vault includes will be related to tokens and native SOL only. Even the most traffic vault can only have around **50-100 transactions**. 
- Using cache database, partition and event listener: This technique is commonly used in tradition backend development. If you have around 300 transactions for an address, try to partition those into smaller parts: **50 transactions** per each. Cache those data and then only update the database if there is a new data coming (use `onAccountChange`).

## Filtering transactions
There will be two types of transactions that you may want to fetch to display a similar result from Phantom: Native SOL deposit transactions and SPL tokens deposit transactions. If you use `getParsedTransactions` like what I did above, all the data is already converted into human readable language. The raw transactions using `getTransactions` return only hexadecimal data. I wrote these two methods so that you can reuse it, it's quite simple because all data is parsed already.
```typescript
// Filter SPL token deposit transaction
isSplTokenDepositTx(tx: any): boolean {
  const ixs = tx.transaction.message.instructions;
  const ix: any = ixs[ixs.length - 1];
  return (
    ix.programId.equals(TOKEN_PROGRAM_ID) &&
    (ix.parsed.type === 'transfer' || ix.parsed.type === 'transferChecked')
  );
}

// Filter Native SOL deposit transaction
isSolDepositTx(tx: any): boolean {
  const ix: any = tx.transaction.message.instructions[0];
  return ix.programId.equals(SYSTEM_PROGRAM_ID) && ix.parsed.type === 'transfer';
}
```