Skip to content

Commit

Permalink
feat: remove helper classes for account (#132)
Browse files Browse the repository at this point in the history
* feat: remove helper classes for account

* refactor: remove unused error for base account

* test: complete unit coverage for base account errors
  • Loading branch information
fazzatti authored Apr 24, 2024
1 parent 210cbd7 commit cf4b2e9
Show file tree
Hide file tree
Showing 16 changed files with 316 additions and 211 deletions.
4 changes: 2 additions & 2 deletions src/stellar-plus/account/account-handler/default/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { FeeBumpTransaction, Keypair, Transaction, authorizeEntry, xdr } from '@stellar/stellar-sdk'

import { DefaultAccountHandler, DefaultAccountHandlerPayload } from 'stellar-plus/account/account-handler/default/types'
import { AccountBaseClient } from 'stellar-plus/account/base'
import { AccountBase } from 'stellar-plus/account/base'
import { TransactionXdr } from 'stellar-plus/types'

import { DAHError } from './errors'

export class DefaultAccountHandlerClient extends AccountBaseClient implements DefaultAccountHandler {
export class DefaultAccountHandlerClient extends AccountBase implements DefaultAccountHandler {
protected secretKey: string

/**
Expand Down
6 changes: 3 additions & 3 deletions src/stellar-plus/account/account-handler/freighter/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ import {
FreighterAccountHandler,
FreighterCallback,
} from 'stellar-plus/account/account-handler/freighter/types'
import { AccountBaseClient } from 'stellar-plus/account/base'
import { AccountBase } from 'stellar-plus/account/base'
import { NetworkConfig } from 'stellar-plus/types'

import { FAHError } from './errors'

export class FreighterAccountHandlerClient extends AccountBaseClient implements FreighterAccountHandler {
private networkConfig: NetworkConfig
export class FreighterAccountHandlerClient extends AccountBase implements FreighterAccountHandler {
protected networkConfig: NetworkConfig

/**
*
Expand Down
8 changes: 6 additions & 2 deletions src/stellar-plus/account/account-handler/types.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { FeeBumpTransaction, Transaction, xdr } from '@stellar/stellar-sdk'

import { HorizonHandler } from 'stellar-plus'
import { AccountBase } from 'stellar-plus/account/base/types'
import { AccountHelpersPayload } from 'stellar-plus/account/helpers/types'
import { NetworkConfig } from 'stellar-plus/constants'
import { TransactionXdr } from 'stellar-plus/types'

export type AccountHandler = AccountBase & {
Expand All @@ -15,7 +16,10 @@ export type AccountHandler = AccountBase & {
signatureSchema?: SignatureSchema
}

export type AccountHandlerPayload = AccountHelpersPayload
export type AccountHandlerPayload = {
networkConfig?: NetworkConfig
horizonHandler?: HorizonHandler
}

export type SignatureSchema = {
threasholds: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,47 +3,40 @@ import { AxiosError } from 'axios'
import { StellarPlusError } from 'stellar-plus/error'
import { AxiosErrorTypes, extractAxiosErrorInfo } from 'stellar-plus/error/helpers/axios'

export enum FriendbotErrorCodes {
// F0 General
FB001 = 'FB001',
FB002 = 'FB002',
FB003 = 'FB003',
// F1 Account creation
FB100 = 'FB100',
FB101 = 'FB101',
FB102 = 'FB102',
FB103 = 'FB103',
export enum AccountBaseErrorCodes {
// AB0 General
AB001 = 'AB001',

// AB1 Account creation
AB100 = 'AB100',
AB101 = 'AB101',
AB102 = 'AB102',
AB103 = 'AB103',

// AB2 Loading from Horizon
AB200 = 'AB200',
AB201 = 'AB201',
}

const friendbotNotAvailableError = (error?: Error): StellarPlusError => {
return new StellarPlusError({
code: FriendbotErrorCodes.FB001,
code: AccountBaseErrorCodes.AB001,
message: 'Friendbot not available!',
source: 'Friendbot',
source: 'AccountBase',
details:
'Friendbot is only available in test networks such as the Testnet and Futurenet. Make sure that the Network configuration object contains a valid Friendbot URL.',
meta: { error },
})
}

const accountHasNoValidPublicKeyError = (error?: Error): StellarPlusError => {
return new StellarPlusError({
code: FriendbotErrorCodes.FB002,
message: 'Account has no valid public key!',
source: 'Friendbot',
details:
'The account has no valid public key. Make sure that this account instance has been initialized correctly and contains a valid public key.',
meta: { error },
})
}

const failedToCreateAccountWithFriendbotError = (error?: Error): StellarPlusError => {
const axiosError = extractAxiosErrorInfo(error as AxiosError)

if (axiosError.type === AxiosErrorTypes.AxiosRequestError) {
return new StellarPlusError({
code: FriendbotErrorCodes.FB101,
code: AccountBaseErrorCodes.AB101,
message: 'Failed request when initializing account with friendbot!',
source: 'Friendbot',
source: 'AccountBase',
details:
'The request failed when initializing the account with the friendbot. Make sure that the network is available and that friendbot URL is correct.',
meta: { axiosError, error },
Expand All @@ -52,26 +45,49 @@ const failedToCreateAccountWithFriendbotError = (error?: Error): StellarPlusErro

if (axiosError.type === AxiosErrorTypes.AxiosResponseError) {
return new StellarPlusError({
code: FriendbotErrorCodes.FB102,
code: AccountBaseErrorCodes.AB102,
message: 'Failed response when initializing account with friendbot!',
source: 'Friendbot',
source: 'AccountBase',
details:
'Received a failed response when initializing the account with the friendbot. Make sure the account has not been already initialized.',
meta: { axiosError, error },
})
}

return new StellarPlusError({
code: FriendbotErrorCodes.FB100,
code: AccountBaseErrorCodes.AB100,
message: 'Unknown error when initializing account with friendbot!',
source: 'Friendbot',
source: 'AccountBase',
details: 'An unexpected error occured during the friendbot invocation to initialize an account.',
meta: { axiosError, error },
})
}

export const FBError = {
accountHasNoValidPublicKeyError,
const horizonHandlerNotAvailableError = (error?: Error): StellarPlusError => {
return new StellarPlusError({
code: AccountBaseErrorCodes.AB200,
message: 'Horizon handler not available!',
source: 'AccountBase',
details:
'Horizon handler is not available. Make sure that the Horizon handler is correctly initialized by providing an instance of Horizon handler or a network configuration when instancing the account.',
meta: { error },
})
}

const failedToLoadBalances = (error?: Error): StellarPlusError => {
return new StellarPlusError({
code: AccountBaseErrorCodes.AB201,
message: 'Failed to load balances!',
source: 'AccountBase',
details:
'Failed to load the account balances from the Horizon server. Make sure that the Horizon handler is correctly initialized and that the account has been correctly initialized.',
meta: { error },
})
}

export const ABError = {
failedToCreateAccountWithFriendbotError,
friendbotNotAvailableError,
horizonHandlerNotAvailableError,
failedToLoadBalances,
}
84 changes: 79 additions & 5 deletions src/stellar-plus/account/base/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import { AccountBase, AccountBasePayload } from 'stellar-plus/account/base/types'
import { AccountHelpers } from 'stellar-plus/account/helpers'
import { Horizon } from '@stellar/stellar-sdk'
import axios from 'axios'

export class AccountBaseClient extends AccountHelpers implements AccountBase {
import { ABError } from 'stellar-plus/account/base/errors'
import { AccountBasePayload, AccountBase as AccountBaseType } from 'stellar-plus/account/base/types'
import { NetworkConfig } from 'stellar-plus/constants'
import { HorizonHandlerClient as HorizonHandler } from 'stellar-plus/horizon/'

export class AccountBase implements AccountBaseType {
protected publicKey: string
protected networkConfig?: NetworkConfig
protected horizonHandler?: HorizonHandler

/**
*
Expand All @@ -13,10 +20,15 @@ export class AccountBaseClient extends AccountHelpers implements AccountBase {
* @description - The base account is used for handling accounts with no management actions.
*/
constructor(payload: AccountBasePayload) {
super(payload)
const { publicKey } = payload as { publicKey: string }
const { publicKey, networkConfig, horizonHandler } = payload

this.publicKey = publicKey
this.networkConfig = networkConfig
this.horizonHandler = horizonHandler as HorizonHandler

if (this.networkConfig && !this.horizonHandler) {
this.horizonHandler = new HorizonHandler(this.networkConfig)
}
}

/**
Expand All @@ -27,4 +39,66 @@ export class AccountBaseClient extends AccountHelpers implements AccountBase {
getPublicKey(): string {
return this.publicKey
}

/**
*
* @returns {void}
* @description - Initialize the account with the friendbot and funds it with 10.000 XLM.
*/
public async initializeWithFriendbot(): Promise<void> {
this.requireTestNetwork()

try {
await axios.get(
`${this.networkConfig!.friendbotUrl}?addr=${encodeURIComponent(this.publicKey)}` // friendbot URL in networkConfig validated in requireTestNetwork()
)

return
} catch (e) {
throw ABError.failedToCreateAccountWithFriendbotError(e as Error)
}
}

/**
*
* @returns {Horizon.BalanceLine[]} A list of the account's balances.
* @description - The account's balances are retrieved from the Horizon server and provided in a list, including all assets.
*/
public async getBalances(): Promise<
(
| Horizon.HorizonApi.BalanceLineNative
| Horizon.HorizonApi.BalanceLineAsset<'credit_alphanum4'>
| Horizon.HorizonApi.BalanceLineAsset<'credit_alphanum12'>
| Horizon.HorizonApi.BalanceLineLiquidityPool
)[]
> {
this.requireHorizonHandler()

try {
const account = await this.horizonHandler!.loadAccount(this.publicKey) // Horizon handler validated in requireHorizonHandler()
return account.balances
} catch (error) {
throw ABError.failedToLoadBalances(error as Error)
}
}

/**
*
* @description - Throws an error if the network is not a test network.
*/
protected requireTestNetwork(): void {
if (!this.networkConfig?.friendbotUrl) {
throw ABError.friendbotNotAvailableError()
}
}

/**
*
* @description - Throws an error if the horizon handler is not set
*/
protected requireHorizonHandler(): void {
if (!this.horizonHandler) {
throw ABError.horizonHandlerNotAvailableError()
}
}
}
Loading

0 comments on commit cf4b2e9

Please sign in to comment.