p2p-org/solana-swift

Change log: 1.x.x to 2.x.x

bigearsenal opened this issue · 0 comments

Edited

  • SolanaSDK namespace will be marked as deprecated, new classes, modules will be implemented without namespace.
  • Better logger has to be integrated

The problems and their solutions

1. Highly coupled features in SolanaSwift library

Problem

Due to lack of knowledges and documentation about Solana blockchain at the beginning of the development, the network client module, blockchain client module and other module are highly coupled in one class SolanaSDK, which is inconvenient for using and really hard to test.

For example: For retrieving list of supported token or calling getBalance for an account, the class SolanaSDK needs to be initialized first. As a result, all another modules has to be initialized too, including AccountStorage, which requires user to authenticate, even the SolanaRPC does not require authorization.

The one-class-to-rule-them-all is a bad idea, as it make the class unscalable and hard to test. The graph below shows the implementation of SolanaSDK at the moment:

SolanaSDK__(class)

Solution

The big class SolanaSDK has to be separated into multiple modules.

The term “independent” in this situation means:

  • The module can be initialized and used independently. For example:APIClient must needs only endpoint to be initialized and can be used independently without authorization.
  • The module has their own responsibility and doesn't need to know about another modules.

All modules has to be written in POP, which always starts with an interface (protocol). For example: class APIClient: SolanaAPIClient.

The SolanaSDK will be marked as deprecated for backward compatible.

The graph of SolanaSDK after refactoring is something like this:

SolanaSDK_-_after

Modules’ explaination:

  1. AccountStorage: SolanaAccountStorage stores user’s credentials and define if user is authorized.
  2. APIClient: SolanaAPIClient api client to connect with Solana RPC API, contains following methods (https://docs.solana.com/developing/clients/jsonrpc-api).
  3. TokensRepository: SolanaTokensRepository repository that provides informations about supported token in Solana blockchain. (https://raw.githubusercontent.com/solana-labs/token-list/main/src/tokens/solana.tokenlist.json)
  4. BlockchainClient: SolanaBlockchainClient the client that helps us preparing, signing and serializing transaction using SolanaPrograms before sending using method sendTransaction, simulateTransaction from SolanaAPIClient or forwarding to FeeRelayer.
  5. SolanaProgram Type of Programs that lives on Solana Blockchain that provides methods for preparing instructions in any transaction.
  6. TransactionParser: SolanaTransactionParser: Custom parser to define readable type of transaction, for example: Send, Swap, Receive,...
  7. Socket: SolanaSocket: Socket connection that provide suitable methods to observe user’s account or transaction signature status.

2. Highly depending on Rx libraries

Problem

The SolanaSwift library is right now deeply depending on RxSwift.

The SolanaSwift library is also depending on RxAlamofire for handling network request, it must be replaced by the native solution to reduce dependency.

Untitled

Solution

As swift concurrency is now backward compatible with iOS 13, we use async/await and URLSession as the replacement for RxSwift and RxAlamofire

Notice

In the scope of this refactoring, there would be no ui part touched, so a bridge needs to be created to convert async/await code to adapt new concurrency solution in UI (the UI will be refactored later).

3. Model is coupled inside namespace SolanaSDK

Problem

Model is coupled inside SolanaSDK

Solution

  • Move models outside of SolanaSDK, for example SolanaSDK.PublicKey becomes PublicKey
  • For backward compatibility, type alias has to be added back to SolanaSDK. For example:
extension SolanaSDK {
   typealias PublicKey = SolanaSwift.PublicKey // (?)
}

What is “neсessary”, and what is “nice to have”?

  1. The SolanaSDK is separated into multiple independent modules, which are located in separated folder. Еach module has to be fully tested.
  2. The SolanaSwift needs to be independent from RxSwift, RxAlamofire.
  3. The concurrency code is lightweight and easy to use.
  4. A bridge need to be built to keep the ui part unchanged (will be refactored later)

Task decomposition

This task has to be separated to child tasks, which equivalent to cleaning, deprecating and creating each modules in SolanaSDK:

  1. Group all deprecated implementation of SolanaSDK in to Deprecated folder, move all Models out of SolanaSDK, but don't break the old working solution.
  2. Implement AccountStorage: SolanaAccountStorage, blocked by 1
  3. Implement APIClient: SolanaAPIClient, blocked by 1
  4. Implement TokensRepository: SolanaTokensRepository, blocked by 1
  5. Implement BlockchainClient: SolanaBlockchainClient, blocked by 1
  6. Implement SolanaProgram , blocked by 1
  7. Implement TransactionParser: SolanaTransactionParser, blocked by 1
  8. Implement Socket: SolanaSocket, blocked by 1

Definition of done

  • RxSwift, RxAlamofire is removed from SolanaSwift’s dependencies, a bridge is created to map async function to return Observable to work with current Rx code in p2p-wallet-ios
  • Several modules in SolanaSDK are independent
  • All modules are fully tested