From f44071fa7659772dea2040e7cf22f173c0f75342 Mon Sep 17 00:00:00 2001 From: Dmytro Vynnyk Date: Thu, 23 Oct 2025 23:29:00 +0200 Subject: [PATCH 01/17] Change `balance` type from `number` to `string` in token and account response models to ensure consistent handling of large values. --- src/data/repositories/accountInfo/types.ts | 2 +- src/data/repositories/tokens/index.ts | 2 +- src/data/repositories/tokens/types.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/data/repositories/accountInfo/types.ts b/src/data/repositories/accountInfo/types.ts index 5ee4539..26dbd12 100644 --- a/src/data/repositories/accountInfo/types.ts +++ b/src/data/repositories/accountInfo/types.ts @@ -2,7 +2,7 @@ import { Maybe } from '../../../typings'; export interface IGetAccountsInfoResponse { account_hash: string; - balance: number; + balance: string; main_purse_uref: string; public_key: string; account_info?: ICloudAccountInfoResult; diff --git a/src/data/repositories/tokens/index.ts b/src/data/repositories/tokens/index.ts index c3a1221..7eb294c 100644 --- a/src/data/repositories/tokens/index.ts +++ b/src/data/repositories/tokens/index.ts @@ -66,7 +66,7 @@ export class TokensRepository implements ITokensRepository { return new CsprBalanceDto(resp?.data); } catch (e) { if (e instanceof HttpClientNotFoundError) { - return new CsprBalanceDto({ balance: 0 }); + return new CsprBalanceDto({ balance: '0' }); } else { this._processError(e, 'getCsprBalance'); } diff --git a/src/data/repositories/tokens/types.ts b/src/data/repositories/tokens/types.ts index 462de13..4848356 100644 --- a/src/data/repositories/tokens/types.ts +++ b/src/data/repositories/tokens/types.ts @@ -2,7 +2,7 @@ import { DataResponse, Network } from '../../../domain'; import { Maybe } from '../../../typings'; export interface IGetCsprBalanceResponse { - balance: number; + balance: string; delegated_balance?: number; undelegating_balance?: number; From 1737d5f0d4549ba9d98e1963dbd61b66f1b7888e Mon Sep 17 00:00:00 2001 From: Dmytro Vynnyk Date: Fri, 24 Oct 2025 00:21:54 +0200 Subject: [PATCH 02/17] Refactor repositories to utilize environment-based and network-based Casper Wallet API URLs; update setup logic for improved configurability and maintainability. --- src/data/repositories/accountInfo/index.ts | 12 +++-- src/data/repositories/appEvents/index.ts | 11 ++-- .../repositories/contractPackage/index.ts | 9 ++-- src/data/repositories/deploys/index.ts | 11 ++-- src/data/repositories/nfts/index.ts | 9 ++-- src/data/repositories/tokens/index.ts | 13 +++-- .../repositories/txSignatureRequest/index.ts | 20 +++++--- src/data/repositories/validators/index.ts | 13 +++-- src/domain/constants/casperNetwork.ts | 5 +- src/domain/tx-signature-request/repository.ts | 2 + src/setup.ts | 50 +++++++++++++++---- 11 files changed, 107 insertions(+), 48 deletions(-) diff --git a/src/data/repositories/accountInfo/index.ts b/src/data/repositories/accountInfo/index.ts index 2050206..9d3f467 100644 --- a/src/data/repositories/accountInfo/index.ts +++ b/src/data/repositories/accountInfo/index.ts @@ -1,7 +1,6 @@ import { LRUCache } from 'lru-cache'; import { CSPR_API_PROXY_HEADERS, - CasperWalletApiUrl, isAccountInfoError, AccountInfoError, IAccountInfoRepository, @@ -23,7 +22,10 @@ import { IGetCsprBalanceResponse } from '../tokens'; export * from './types'; export class AccountInfoRepository implements IAccountInfoRepository { - constructor(private _httpProvider: IHttpDataProvider) {} + constructor( + private _httpProvider: IHttpDataProvider, + private _casperWalletApiUrl: Record, + ) {} private _accountsInfoMapCache = new LRUCache({ max: 100, @@ -45,7 +47,7 @@ export class AccountInfoRepository implements IAccountInfoRepository { ); const resp = await this._httpProvider.post>({ - url: `${CasperWalletApiUrl[network]}/accounts?includes=account_info,centralized_account_info,cspr_name`, + url: `${this._casperWalletApiUrl[network]}/accounts?includes=account_info,centralized_account_info,cspr_name`, data: { account_hashes: accountsHashesForFetch, }, @@ -88,7 +90,7 @@ export class AccountInfoRepository implements IAccountInfoRepository { }: IGetAccountsBalancesParams): Promise> { try { const resp = await this._httpProvider.post>({ - url: `${CasperWalletApiUrl[network]}/accounts${withDelegationBalances ? '?includes=delegated_balance,undelegating_balance' : ''}`, + url: `${this._casperWalletApiUrl[network]}/accounts${withDelegationBalances ? '?includes=delegated_balance,undelegating_balance' : ''}`, data: { account_hashes: accountHashes, }, @@ -119,7 +121,7 @@ export class AccountInfoRepository implements IAccountInfoRepository { ): Promise> { try { const resp = await this._httpProvider.get>({ - url: `${CasperWalletApiUrl[network]}/cspr-name-resolutions/${csprName}`, + url: `${this._casperWalletApiUrl[network]}/cspr-name-resolutions/${csprName}`, params: { includes: 'resolved_public_key,account_info,centralized_account_info', }, diff --git a/src/data/repositories/appEvents/index.ts b/src/data/repositories/appEvents/index.ts index 2883959..fbfd30a 100644 --- a/src/data/repositories/appEvents/index.ts +++ b/src/data/repositories/appEvents/index.ts @@ -1,7 +1,6 @@ import { AppEventsError, AppEventsErrorType, - CasperWalletApiEndpoints, CSPR_API_PROXY_HEADERS, DataResponse, IAppEventsRepository, @@ -17,11 +16,15 @@ import { IMarketingEventApiResponse, IReleaseEventApiResponse } from './types'; import { AppMarketingEventDto, AppReleaseEventDto } from '../../dto'; import { Maybe } from '../../../typings'; import { isAppEventActive } from '../../../utils'; +import { IEnv } from '../../../domain/env'; export * from './types'; export class AppEventsRepository implements IAppEventsRepository { - constructor(private _httpProvider: IHttpDataProvider) {} + constructor( + private _httpProvider: IHttpDataProvider, + private _casperWalletApiByEnvUrl: Record, + ) {} async getReleaseEvents({ currentVersion, @@ -30,7 +33,7 @@ export class AppEventsRepository implements IAppEventsRepository { }: IGetReleaseUpdatesParams): Promise { try { const response = await this._httpProvider.get>({ - url: `${CasperWalletApiEndpoints[env]}/mobile-client-versions`, + url: `${this._casperWalletApiByEnvUrl[env]}/mobile-client-versions`, params: { after: `v${currentVersion}`, }, @@ -50,7 +53,7 @@ export class AppEventsRepository implements IAppEventsRepository { }: IGetMarketingEventsParams = {}): Promise { try { const response = await this._httpProvider.get>({ - url: `${CasperWalletApiEndpoints[env]}/marketing-events`, + url: `${this._casperWalletApiByEnvUrl[env]}/marketing-events`, errorType: 'getMarketingEvents', ...(withProxyHeader ? { headers: CSPR_API_PROXY_HEADERS } : {}), }); diff --git a/src/data/repositories/contractPackage/index.ts b/src/data/repositories/contractPackage/index.ts index 644f490..9752e78 100644 --- a/src/data/repositories/contractPackage/index.ts +++ b/src/data/repositories/contractPackage/index.ts @@ -1,5 +1,5 @@ import { - CasperWalletApiUrl, + CasperNetwork, ContractPackageError, ContractPackageErrorType, CSPR_API_PROXY_HEADERS, @@ -15,7 +15,10 @@ import { ContractPackageDto } from '../../dto'; export * from './types'; export class ContractPackageRepository implements IContractPackageRepository { - constructor(private _httpProvider: IHttpDataProvider) {} + constructor( + private _httpProvider: IHttpDataProvider, + private _casperWalletApiUrl: Record, + ) {} async getContractPackage({ contractPackageHash, @@ -24,7 +27,7 @@ export class ContractPackageRepository implements IContractPackageRepository { }: IGetContractPackageParams) { try { const resp = await this._httpProvider.get>({ - url: `${CasperWalletApiUrl[network]}/contract-packages/${contractPackageHash}`, + url: `${this._casperWalletApiUrl[network]}/contract-packages/${contractPackageHash}`, baseURL: '', errorType: 'getContractPackageRequest', ...(withProxyHeader ? { headers: CSPR_API_PROXY_HEADERS } : {}), diff --git a/src/data/repositories/deploys/index.ts b/src/data/repositories/deploys/index.ts index 872db44..5ae5c53 100644 --- a/src/data/repositories/deploys/index.ts +++ b/src/data/repositories/deploys/index.ts @@ -5,7 +5,6 @@ import { HttpClientNotFoundError, CSPR_API_PROXY_HEADERS, EMPTY_PAGINATED_RESPONSE, - CasperWalletApiUrl, IDeploysRepository, IGetDeploysParams, CloudPaginatedResponse, @@ -13,6 +12,7 @@ import { DataResponse, IDeploy, PaginatedResponse, + CasperNetwork, } from '../../../domain'; import type { IHttpDataProvider, IAccountInfoRepository } from '../../../domain'; import { getAccountHashFromPublicKey } from '../../../utils'; @@ -29,6 +29,7 @@ export class DeploysRepository implements IDeploysRepository { constructor( private _httpProvider: IHttpDataProvider, private _accountInfoRepository: IAccountInfoRepository, + private _casperWalletApiUrl: Record, ) {} async getDeploys({ @@ -41,7 +42,7 @@ export class DeploysRepository implements IDeploysRepository { }: IGetDeploysParams) { try { const resp = await this._httpProvider.get>({ - url: `${CasperWalletApiUrl[network]}/accounts/${activePublicKey}/deploys`, + url: `${this._casperWalletApiUrl[network]}/accounts/${activePublicKey}/deploys`, params: { public_key: activePublicKey, page, @@ -94,7 +95,7 @@ export class DeploysRepository implements IDeploysRepository { const accountHash = getAccountHashFromPublicKey(activePublicKey); const resp = await this._httpProvider.get>({ - url: `${CasperWalletApiUrl[network]}/accounts/${accountHash}/transfers`, + url: `${this._casperWalletApiUrl[network]}/accounts/${accountHash}/transfers`, params: { page, page_size: limit, @@ -142,7 +143,7 @@ export class DeploysRepository implements IDeploysRepository { }: IGetSingleDeployParams) { try { const resp = await this._httpProvider.get>({ - url: `${CasperWalletApiUrl[network]}/deploys/${deployHash}`, + url: `${this._casperWalletApiUrl[network]}/deploys/${deployHash}`, params: { includes: 'rate(1),contract,contract_package,contract_entrypoint,account_info,transfers,nft_token_actions,ft_token_actions', @@ -190,7 +191,7 @@ export class DeploysRepository implements IDeploysRepository { const resp = await this._httpProvider.get< CloudPaginatedResponse >({ - url: `${CasperWalletApiUrl[network]}/accounts/${accountHash}/ft-token-actions`, + url: `${this._casperWalletApiUrl[network]}/accounts/${accountHash}/ft-token-actions`, params: { contract_package_hash: contractPackageHash, // TODO do not worked account_identifier: accountHash, diff --git a/src/data/repositories/nfts/index.ts b/src/data/repositories/nfts/index.ts index 7f8921e..665fc05 100644 --- a/src/data/repositories/nfts/index.ts +++ b/src/data/repositories/nfts/index.ts @@ -1,5 +1,4 @@ import { - CasperWalletApiUrl, DEFAULT_PAGE_LIMIT, EMPTY_PAGINATED_RESPONSE, CSPR_API_PROXY_HEADERS, @@ -11,6 +10,7 @@ import { INft, NftContentType, PaginatedResponse, + CasperNetwork, } from '../../../domain'; import type { IHttpDataProvider } from '../../../domain'; import { getAccountHashFromPublicKey } from '../../../utils'; @@ -20,7 +20,10 @@ import { IApiNft } from './types'; export * from './types'; export class NftsRepository implements INftsRepository { - constructor(private _httpProvider: IHttpDataProvider) {} + constructor( + private _httpProvider: IHttpDataProvider, + private _casperWalletApiUrl: Record, + ) {} async getNfts({ network, @@ -33,7 +36,7 @@ export class NftsRepository implements INftsRepository { const accountHash = getAccountHashFromPublicKey(publicKey); const resp = await this._httpProvider.get>({ - url: `${CasperWalletApiUrl[network]}/accounts/${accountHash}/nft-tokens`, + url: `${this._casperWalletApiUrl[network]}/accounts/${accountHash}/nft-tokens`, params: { page, page_size: limit, diff --git a/src/data/repositories/tokens/index.ts b/src/data/repositories/tokens/index.ts index 7eb294c..0cf48a7 100644 --- a/src/data/repositories/tokens/index.ts +++ b/src/data/repositories/tokens/index.ts @@ -4,7 +4,6 @@ import { TokensError, HttpClientNotFoundError, CSPR_API_PROXY_HEADERS, - CasperWalletApiUrl, ITokensRepository, DataResponse, IGetTokensParams, @@ -12,6 +11,7 @@ import { IToken, IGetCsprFiatCurrencyRateParams, ITokenWithFiatBalance, + CasperNetwork, } from '../../../domain'; import type { IHttpDataProvider } from '../../../domain'; import { CsprBalanceDto, TokenDto, TokenFiatRateDto } from '../../dto'; @@ -21,7 +21,10 @@ import { Erc20Token, IGetCsprBalanceResponse, IGetCurrencyRateResponse } from '. export * from './types'; export class TokensRepository implements ITokensRepository { - constructor(private _httpProvider: IHttpDataProvider) {} + constructor( + private _httpProvider: IHttpDataProvider, + private _casperWalletApiUrl: Record, + ) {} async getTokens({ network, @@ -32,7 +35,7 @@ export class TokensRepository implements ITokensRepository { const accountHash = getAccountHashFromPublicKey(publicKey); const tokensList = await this._httpProvider.get>({ - url: `${CasperWalletApiUrl[network]}/accounts/${accountHash}/ft-token-ownership`, + url: `${this._casperWalletApiUrl[network]}/accounts/${accountHash}/ft-token-ownership`, params: { page_size: 100, // TODO pagination? includes: 'contract_package,friendlymarket_data(1),coingecko_data(1)', @@ -55,7 +58,7 @@ export class TokensRepository implements ITokensRepository { async getCsprBalance({ publicKey, network, withProxyHeader = true }: IGetCsprBalanceParams) { try { const resp = await this._httpProvider.get>({ - url: `${CasperWalletApiUrl[network]}/accounts/${publicKey}`, + url: `${this._casperWalletApiUrl[network]}/accounts/${publicKey}`, errorType: 'getCsprBalance', params: { includes: 'delegated_balance,undelegating_balance', @@ -100,7 +103,7 @@ export class TokensRepository implements ITokensRepository { }: IGetCsprFiatCurrencyRateParams) { try { const resp = await this._httpProvider.get({ - url: `${CasperWalletApiUrl[network]}/rates/1/amount`, + url: `${this._casperWalletApiUrl[network]}/rates/1/amount`, ...(withProxyHeader ? { headers: CSPR_API_PROXY_HEADERS } : {}), errorType: 'getCsprFiatCurrencyRate', }); diff --git a/src/data/repositories/txSignatureRequest/index.ts b/src/data/repositories/txSignatureRequest/index.ts index e0a193f..b66ebe8 100644 --- a/src/data/repositories/txSignatureRequest/index.ts +++ b/src/data/repositories/txSignatureRequest/index.ts @@ -1,9 +1,7 @@ import { CasperNetwork, - CasperWalletApiEndpoints, CSPR_API_PROXY_HEADERS, DataResponse, - GrpcUrl, IAccountInfoRepository, IContractPackage, IContractPackageRepository, @@ -38,6 +36,7 @@ import { TxSignatureRequestDto, } from '../../dto'; import { blake2b } from '@noble/hashes/blake2'; +import { IEnv } from '../../../domain/env'; export * from './types'; @@ -47,12 +46,15 @@ export class TxSignatureRequestRepository implements ITxSignatureRequestReposito private _accountInfoRepository: IAccountInfoRepository, private _tokensRepository: ITokensRepository, private _contractPackageRepository: IContractPackageRepository, + private _casperWalletApiByEnvUrl: Record, + private _grpcUrl: Record, ) {} async prepareSignatureRequest({ transactionJson, signingPublicKeyHex, withProxyHeader = true, + env = 'PRODUCTION', }: IPrepareSignatureRequestParams): Promise { try { const tx = Transaction.fromJSON(transactionJson); @@ -88,7 +90,7 @@ export class TxSignatureRequestRepository implements ITxSignatureRequestReposito } catch (e) {} try { - isWasmProxyOnApi = await this._checkIsWasmProxyTx(tx, withProxyHeader); + isWasmProxyOnApi = await this._checkIsWasmProxyTx(tx, withProxyHeader, env); } catch (e) {} try { @@ -130,7 +132,7 @@ export class TxSignatureRequestRepository implements ITxSignatureRequestReposito } catch (e) {} try { - const handler = new HttpHandler(GrpcUrl[network], 'fetch'); + const handler = new HttpHandler(this._grpcUrl[network], 'fetch'); if (withProxyHeader) { handler.setReferrer(CSPR_API_PROXY_HEADERS.Referer); @@ -263,7 +265,7 @@ export class TxSignatureRequestRepository implements ITxSignatureRequestReposito return null; } - const handler = new HttpHandler(GrpcUrl[network], 'fetch'); + const handler = new HttpHandler(this._grpcUrl[network], 'fetch'); if (withProxyHeader) { handler.setReferrer(CSPR_API_PROXY_HEADERS.Referer); @@ -290,7 +292,11 @@ export class TxSignatureRequestRepository implements ITxSignatureRequestReposito } } - private async _checkIsWasmProxyTx(tx: Transaction, withProxyHeader = true): Promise { + private async _checkIsWasmProxyTx( + tx: Transaction, + withProxyHeader = true, + env: IEnv = 'PRODUCTION', + ): Promise { try { if (!tx.target.session?.moduleBytes) { return false; @@ -301,7 +307,7 @@ export class TxSignatureRequestRepository implements ITxSignatureRequestReposito ); await this._httpProvider.get>({ - url: `${CasperWalletApiEndpoints.PRODUCTION}/odra-wasm-proxies/${blake2bHash}`, + url: `${this._casperWalletApiByEnvUrl[env]}/odra-wasm-proxies/${blake2bHash}`, baseURL: '', errorType: 'checkWasmProxyRequest', ...(withProxyHeader ? { headers: CSPR_API_PROXY_HEADERS } : {}), diff --git a/src/data/repositories/validators/index.ts b/src/data/repositories/validators/index.ts index ecb3737..0e4b2c5 100644 --- a/src/data/repositories/validators/index.ts +++ b/src/data/repositories/validators/index.ts @@ -1,5 +1,5 @@ import { - CasperWalletApiUrl, + CasperNetwork, CloudPaginatedResponse, CSPR_API_PROXY_HEADERS, DataResponse, @@ -20,7 +20,10 @@ import { IApiValidator, IApiValidatorWithStake, IAuctionMetricsResponse } from ' export * from './types'; export class ValidatorsRepository implements IValidatorsRepository { - constructor(private _httpProvider: IHttpDataProvider) {} + constructor( + private _httpProvider: IHttpDataProvider, + private _casperWalletApiUrl: Record, + ) {} async getValidators({ network, @@ -32,7 +35,7 @@ export class ValidatorsRepository implements IValidatorsRepository { const eraId = await this.getCurrentEraId({ network, withProxyHeader }); const resp = await this._httpProvider.get>({ - url: `${CasperWalletApiUrl[network]}/validators`, + url: `${this._casperWalletApiUrl[network]}/validators`, params: { page, page_size: limit, @@ -68,7 +71,7 @@ export class ValidatorsRepository implements IValidatorsRepository { const eraId = await this.getCurrentEraId({ network, withProxyHeader }); const validatorsList = await this._httpProvider.get>({ - url: `${CasperWalletApiUrl[network]}/accounts/${publicKey}/delegations`, + url: `${this._casperWalletApiUrl[network]}/accounts/${publicKey}/delegations`, params: { page: 1, page_size: 100, // TODO Pagination? @@ -90,7 +93,7 @@ export class ValidatorsRepository implements IValidatorsRepository { async getCurrentEraId({ withProxyHeader, network }: IGetGetCurrentEraIdParams): Promise { try { const resp = await this._httpProvider.get>({ - url: `${CasperWalletApiUrl[network]}/auction-metrics`, + url: `${this._casperWalletApiUrl[network]}/auction-metrics`, ...(withProxyHeader ? { headers: CSPR_API_PROXY_HEADERS } : {}), errorType: 'getCurrentEraId', }); diff --git a/src/domain/constants/casperNetwork.ts b/src/domain/constants/casperNetwork.ts index dc2d4a6..b62ad04 100644 --- a/src/domain/constants/casperNetwork.ts +++ b/src/domain/constants/casperNetwork.ts @@ -12,14 +12,15 @@ export const CasperLiveUrl: Record = { integration: 'https://integration.cspr.live', }; -export const CasperWalletApiUrl: Record = { +export const CasperWalletApiByNetworkUrl: Record = { mainnet: 'https://api.mainnet.casperwallet.io', testnet: 'https://api.testnet.casperwallet.io', devnet: 'https://cspr-wallet-api.dev.make.services', integration: 'https://api.integration.casperwallet.io', }; -export const CasperWalletApiEndpoints: Record = { +/** Environment-based url for Casper Wallet Api. Some API network agnostic and do not belong to any {@link CasperWalletApiByNetworkUrl}. Default env is PRODUCTION (in all places where it is used) */ +export const CasperWalletApiByEnvUrl: Record = { PRODUCTION: 'https://api.casperwallet.io', STAGING: 'https://cspr-wallet-api.stg.make.services', }; diff --git a/src/domain/tx-signature-request/repository.ts b/src/domain/tx-signature-request/repository.ts index 75b0175..efeba4f 100644 --- a/src/domain/tx-signature-request/repository.ts +++ b/src/domain/tx-signature-request/repository.ts @@ -1,4 +1,5 @@ import { ITxSignatureRequest } from './entities'; +import { IEnv } from '../env'; export interface ITxSignatureRequestRepository { prepareSignatureRequest(params: IPrepareSignatureRequestParams): Promise; @@ -8,4 +9,5 @@ export interface IPrepareSignatureRequestParams { transactionJson: string; signingPublicKeyHex: string; withProxyHeader?: boolean; + env?: IEnv; } diff --git a/src/setup.ts b/src/setup.ts index 85bbc96..13dba55 100644 --- a/src/setup.ts +++ b/src/setup.ts @@ -11,30 +11,62 @@ import { ContractPackageRepository, } from './data/repositories'; import { Logger } from './utils'; -import { ILogger } from './domain'; +import { + CasperNetwork, + CasperWalletApiByNetworkUrl, + CasperWalletApiByEnvUrl, + GrpcUrl, + ILogger, +} from './domain'; +import { IEnv } from './domain/env'; export interface ISetupRepositoriesParams { debug?: boolean; logger?: ILogger; + casperWalletApiByNetworkUrl?: Record; + /** Environment-based url for Casper Wallet Api. Some API network agnostic and do not belong to any {@link CasperWalletApiByNetworkUrl}. Default env is PRODUCTION (in all places where it is used) */ + casperWalletApiByEnvUrl?: Record; + grpcUrl?: Record; } -export const setupRepositories = ({ logger, debug }: ISetupRepositoriesParams = {}) => { +export const setupRepositories = ({ + logger, + debug, + casperWalletApiByNetworkUrl = CasperWalletApiByNetworkUrl, + casperWalletApiByEnvUrl = CasperWalletApiByEnvUrl, + grpcUrl = GrpcUrl, +}: ISetupRepositoriesParams = {}) => { const log = logger ?? new Logger(); const httpDataProvider = new HttpDataProvider(debug ? log : null); - const accountInfoRepository = new AccountInfoRepository(httpDataProvider); - const tokensRepository = new TokensRepository(httpDataProvider); + const accountInfoRepository = new AccountInfoRepository( + httpDataProvider, + casperWalletApiByNetworkUrl, + ); + const tokensRepository = new TokensRepository(httpDataProvider, casperWalletApiByNetworkUrl); const onRampRepository = new OnRampRepository(httpDataProvider); - const nftsRepository = new NftsRepository(httpDataProvider); - const validatorsRepository = new ValidatorsRepository(httpDataProvider); - const deploysRepository = new DeploysRepository(httpDataProvider, accountInfoRepository); - const appEventsRepository = new AppEventsRepository(httpDataProvider); - const contractPackageRepository = new ContractPackageRepository(httpDataProvider); + const nftsRepository = new NftsRepository(httpDataProvider, casperWalletApiByNetworkUrl); + const validatorsRepository = new ValidatorsRepository( + httpDataProvider, + casperWalletApiByNetworkUrl, + ); + const deploysRepository = new DeploysRepository( + httpDataProvider, + accountInfoRepository, + casperWalletApiByNetworkUrl, + ); + const appEventsRepository = new AppEventsRepository(httpDataProvider, casperWalletApiByEnvUrl); + const contractPackageRepository = new ContractPackageRepository( + httpDataProvider, + casperWalletApiByNetworkUrl, + ); const txSignatureRequestRepository = new TxSignatureRequestRepository( httpDataProvider, accountInfoRepository, tokensRepository, contractPackageRepository, + casperWalletApiByEnvUrl, + grpcUrl, ); return { From a6da9353a84def36e200c6b4b3c79ffe439daaed Mon Sep 17 00:00:00 2001 From: Dmytro Vynnyk Date: Mon, 10 Nov 2025 13:10:03 +0100 Subject: [PATCH 03/17] Update `cep-nft-transfer` to specify `CLTypeUInt8` for `CLOption` initialization, ensuring proper type handling --- src/utils/casperSdk/cep-nft-transfer.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/utils/casperSdk/cep-nft-transfer.ts b/src/utils/casperSdk/cep-nft-transfer.ts index a44e033..5245f6b 100644 --- a/src/utils/casperSdk/cep-nft-transfer.ts +++ b/src/utils/casperSdk/cep-nft-transfer.ts @@ -16,6 +16,7 @@ import { StoredVersionedContractByHash, Timestamp, Transaction, + CLTypeUInt8, } from 'casper-js-sdk'; export enum NFTTokenStandard { @@ -304,6 +305,6 @@ export function getRuntimeArgsForCep95Transfer({ ), ), token_id: CLValue.newCLUInt256(tokenId), - data: CLValue.newCLOption(null), + data: CLValue.newCLOption(null, CLTypeUInt8), }); } From 043df32658ae584c17520a9916ece0db2f7e065e Mon Sep 17 00:00:00 2001 From: Dmytro Vynnyk Date: Mon, 1 Dec 2025 22:40:50 +0100 Subject: [PATCH 04/17] Add support for handling CEP-18 entry points and improve `TxSignatureRequestDto` logic with `isCep18Action` validation --- .../txSignatureRequest/TxSignatureRequestDto.ts | 15 +++++++++++---- src/domain/constants/casperNetwork.ts | 11 +++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/data/dto/txSignatureRequest/TxSignatureRequestDto.ts b/src/data/dto/txSignatureRequest/TxSignatureRequestDto.ts index 81153eb..59979b9 100644 --- a/src/data/dto/txSignatureRequest/TxSignatureRequestDto.ts +++ b/src/data/dto/txSignatureRequest/TxSignatureRequestDto.ts @@ -5,6 +5,7 @@ import { AssociatedKeysContractInfo, AuctionManagerContractInfo, CasperNetwork, + CEP_18_ACTION_ENTRY_POINTS, CSPR_COIN, CSPRMarketContractInfo, IAccountInfo, @@ -188,10 +189,7 @@ export function getTxSignatureRequestAction( contractPackage, collectionContractPackage, ); - } else if ( - contractTypeId === ContractTypeId.CustomCep18 || - contractTypeId === ContractTypeId.Cep18 - ) { + } else if (isCep18Action(tx, contractTypeId)) { return getTxSignatureRequestCep18Action(tx, accountInfoMap, contractPackage); } else if ( contractTypeId === ContractTypeId.CEP78Nft || @@ -263,3 +261,12 @@ function isContractSpecificContractCall(tx: Transaction, contractInfo: IContract storedTargetId?.byPackageName?.name === contractInfo.contractPackageName ); } + +function isCep18Action(tx: Transaction, contractTypeId?: number): boolean { + const entryPoint = tx.entryPoint.customEntryPoint ?? ''; + + return ( + (contractTypeId === ContractTypeId.CustomCep18 || contractTypeId === ContractTypeId.Cep18) && + CEP_18_ACTION_ENTRY_POINTS.includes(entryPoint.toLowerCase()) + ); +} diff --git a/src/domain/constants/casperNetwork.ts b/src/domain/constants/casperNetwork.ts index b62ad04..f21d0b6 100644 --- a/src/domain/constants/casperNetwork.ts +++ b/src/domain/constants/casperNetwork.ts @@ -219,3 +219,14 @@ export const casperChainNameToCasperNetwork: Record Date: Mon, 1 Dec 2025 23:11:18 +0100 Subject: [PATCH 05/17] Add `iconUrl` support to deploy DTOs and entities; refine CEP-18 entry point validation logic --- src/data/dto/deploys/CsprTransferDeployDto.ts | 2 ++ src/data/dto/deploys/DeployDto.ts | 2 ++ src/data/dto/deploys/common.ts | 5 +++-- src/domain/deploys/entities.ts | 1 + 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/data/dto/deploys/CsprTransferDeployDto.ts b/src/data/dto/deploys/CsprTransferDeployDto.ts index 4ecfcaf..60d3921 100644 --- a/src/data/dto/deploys/CsprTransferDeployDto.ts +++ b/src/data/dto/deploys/CsprTransferDeployDto.ts @@ -108,6 +108,7 @@ export class CsprTransferDeployDto implements INativeCsprDeploy { this.cep18ActionsResult = []; this.deployHash = data?.deploy_hash ?? ''; this.id = getUniqueId(); + this.iconUrl = null; } readonly recipientAccountInfo: Maybe; @@ -144,4 +145,5 @@ export class CsprTransferDeployDto implements INativeCsprDeploy { readonly cep18ActionsResult: ICep18ActionsResult[]; readonly id: string; readonly deployHash: string; + readonly iconUrl: Maybe; } diff --git a/src/data/dto/deploys/DeployDto.ts b/src/data/dto/deploys/DeployDto.ts index ad8f0d8..2de5945 100644 --- a/src/data/dto/deploys/DeployDto.ts +++ b/src/data/dto/deploys/DeployDto.ts @@ -50,6 +50,7 @@ export class DeployDto implements IDeploy { ); this.contractHash = data?.contract_hash ?? ''; this.contractPackageHash = data?.contract_package_hash ?? ''; + this.iconUrl = data?.contract_package?.icon_url ?? null; this.entryPoint = getEntryPoint(data) ?? null; this.contractName = data?.contract_package?.name ?? null; @@ -75,6 +76,7 @@ export class DeployDto implements IDeploy { readonly executionTypeId: number; readonly contractHash: string; readonly contractPackageHash: string; + readonly iconUrl: Maybe; readonly entryPoint: Maybe; readonly status: DeployStatus; readonly cost: string; diff --git a/src/data/dto/deploys/common.ts b/src/data/dto/deploys/common.ts index 42212cf..547ea0a 100644 --- a/src/data/dto/deploys/common.ts +++ b/src/data/dto/deploys/common.ts @@ -12,6 +12,7 @@ import { AccountKeyType, AssociatedKeysContractHash, AuctionManagerContractHash, + CEP_18_ACTION_ENTRY_POINTS, CSPRMarketContractHash, CSPRStudioCep47ContractHash, DeployType, @@ -41,8 +42,8 @@ export function getDeployType(network: Network, deploy?: Partial; readonly status: DeployStatus; readonly callerPublicKey: string; From 9375f47147667d0532f5fa63533689b88ba85705 Mon Sep 17 00:00:00 2001 From: Dmytro Vynnyk Date: Mon, 15 Dec 2025 22:19:08 +0100 Subject: [PATCH 06/17] Refactor `TxSignatureRequestDto` and related actions to replace `signingPublicKeyHex` with `senderPublicKeyHex` for improved clarity and consistency. --- src/data/dto/txSignatureRequest/TxSignatureRequestDto.ts | 8 ++++---- src/data/dto/txSignatureRequest/actions/auctionAction.ts | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/data/dto/txSignatureRequest/TxSignatureRequestDto.ts b/src/data/dto/txSignatureRequest/TxSignatureRequestDto.ts index 59979b9..063d6ab 100644 --- a/src/data/dto/txSignatureRequest/TxSignatureRequestDto.ts +++ b/src/data/dto/txSignatureRequest/TxSignatureRequestDto.ts @@ -88,7 +88,7 @@ export class TxSignatureRequestDto implements ITxSignatureRequest { tx, csprFiatRate, network, - signingPublicKeyHex, + this.senderKey, accountInfoMap, contractPackage, collectionContractPackage, @@ -124,7 +124,7 @@ export function getTxSignatureRequestAction( tx: Transaction, csprFiatRate: string, network: Maybe, - signingPublicKeyHex: string, + senderPublicKeyHex: string, accountInfoMap: Record = {}, contractPackage: Maybe, collectionContractPackage: Maybe, @@ -150,7 +150,7 @@ export function getTxSignatureRequestAction( tx, accountInfoMap, csprFiatRate, - signingPublicKeyHex, + senderPublicKeyHex, contractPackage, ); @@ -173,7 +173,7 @@ export function getTxSignatureRequestAction( tx, accountInfoMap, csprFiatRate, - signingPublicKeyHex, + senderPublicKeyHex, contractPackage, ); } else if ( diff --git a/src/data/dto/txSignatureRequest/actions/auctionAction.ts b/src/data/dto/txSignatureRequest/actions/auctionAction.ts index 8b756b2..f281b87 100644 --- a/src/data/dto/txSignatureRequest/actions/auctionAction.ts +++ b/src/data/dto/txSignatureRequest/actions/auctionAction.ts @@ -14,7 +14,7 @@ export function getTxSignatureRequestAuctionAction( tx: Transaction, accountInfoMap: Record = {}, csprFiatRate: string, - signingPublicKeyHex: string, + senderPublicKeyHex: string, contractPackage: Maybe, ): ITxSignatureRequestAuctionAction { const amount = tx.args.getByName('amount')?.toString() ?? '0'; @@ -28,7 +28,7 @@ export function getTxSignatureRequestAuctionAction( fromValidatorKeyType, ); - const toValidator = getToValidator(tx, entryPoint, signingPublicKeyHex); + const toValidator = getToValidator(tx, entryPoint, senderPublicKeyHex); const toValidatorKeyType = deriveKeyType(toValidator); const toValidatorAccountInfo = getAccountInfoFromMap( accountInfoMap, @@ -75,7 +75,7 @@ function getFromValidator(tx: Transaction, entryPoint: string): string | null { return null; } -function getToValidator(tx: Transaction, entryPoint: string, signingPublicKeyHex: string) { +function getToValidator(tx: Transaction, entryPoint: string, senderPublicKeyHex: string) { const new_validator = tx.args.getByName('new_validator'); if (new_validator) { @@ -85,7 +85,7 @@ function getToValidator(tx: Transaction, entryPoint: string, signingPublicKeyHex return validator?.type.getTypeID() === TypeID.PublicKey ? validator.toString() : ''; } else if (entryPoint.toLowerCase() === 'undelegate') { - return signingPublicKeyHex; + return senderPublicKeyHex; } return null; From ad5cad10bf3794016995ef713e6cef4f75334281 Mon Sep 17 00:00:00 2001 From: Dmytro Vynnyk Date: Mon, 15 Dec 2025 22:43:40 +0100 Subject: [PATCH 07/17] Refactor CEP-18 and NFT entry point validation logic by introducing `isCep18Action` and `isNftAction` utilities; clean up related DTOs and constants. --- src/data/dto/common.ts | 19 +++++++++++++ src/data/dto/deploys/common.ts | 16 +++-------- .../TxSignatureRequestDto.ts | 27 +++++++------------ src/domain/constants/casperNetwork.ts | 10 +++++++ 4 files changed, 41 insertions(+), 31 deletions(-) diff --git a/src/data/dto/common.ts b/src/data/dto/common.ts index 93de871..dc9094b 100644 --- a/src/data/dto/common.ts +++ b/src/data/dto/common.ts @@ -8,8 +8,10 @@ import { import Decimal from 'decimal.js'; import { AccountKeyType, + CEP_18_ACTION_ENTRY_POINTS, CSPR_COIN, IAccountInfo, + NFT_ACTION_ENTRY_POINTS, SupportedMarketDataProviders, } from '../../domain'; import { Maybe } from '../../typings'; @@ -103,3 +105,20 @@ export function getMarketDataProviderUrl( return null; } } + +export function isCep18Action(entryPointName: string, contractTypeId?: Maybe): boolean { + return ( + (contractTypeId === ContractTypeId.CustomCep18 || contractTypeId === ContractTypeId.Cep18) && + CEP_18_ACTION_ENTRY_POINTS.includes(entryPointName.toLowerCase()) + ); +} + +export function isNftAction(entryPointName: string, contractTypeId?: Maybe): boolean { + return ( + (contractTypeId === ContractTypeId.CEP78Nft || + contractTypeId === ContractTypeId.CEP47Nft || + contractTypeId === ContractTypeId.CustomCEP78Nft || + contractTypeId === ContractTypeId.CustomCEP47Nft) && + NFT_ACTION_ENTRY_POINTS.includes(entryPointName.toLowerCase()) + ); +} diff --git a/src/data/dto/deploys/common.ts b/src/data/dto/deploys/common.ts index 547ea0a..636aee5 100644 --- a/src/data/dto/deploys/common.ts +++ b/src/data/dto/deploys/common.ts @@ -12,7 +12,6 @@ import { AccountKeyType, AssociatedKeysContractHash, AuctionManagerContractHash, - CEP_18_ACTION_ENTRY_POINTS, CSPRMarketContractHash, CSPRStudioCep47ContractHash, DeployType, @@ -22,7 +21,7 @@ import { import { ExtendedCloudDeploy, ExtendedDeployArgsResult, IApiDeployArgs } from '../../repositories'; import { Maybe } from '../../../typings'; -import { ContractTypeId, getHashByType } from '../common'; +import { getHashByType, isCep18Action, isNftAction } from '../common'; export function getDeployType(network: Network, deploy?: Partial): DeployType { const contractTypeId = @@ -41,18 +40,9 @@ export function getDeployType(network: Network, deploy?: Partial Date: Mon, 15 Dec 2025 22:50:55 +0100 Subject: [PATCH 08/17] Remove unused `isCep18Action` function from `TxSignatureRequestDto` to simplify code structure. --- src/data/dto/txSignatureRequest/TxSignatureRequestDto.ts | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/data/dto/txSignatureRequest/TxSignatureRequestDto.ts b/src/data/dto/txSignatureRequest/TxSignatureRequestDto.ts index bdf9efa..3cc6301 100644 --- a/src/data/dto/txSignatureRequest/TxSignatureRequestDto.ts +++ b/src/data/dto/txSignatureRequest/TxSignatureRequestDto.ts @@ -262,12 +262,3 @@ function isContractSpecificContractCall(tx: Transaction, contractInfo: IContract storedTargetId?.byPackageName?.name === contractInfo.contractPackageName ); } - -function isCep18Action(tx: Transaction, contractTypeId?: number): boolean { - const entryPoint = tx.entryPoint.customEntryPoint ?? ''; - - return ( - (contractTypeId === ContractTypeId.CustomCep18 || contractTypeId === ContractTypeId.Cep18) && - CEP_18_ACTION_ENTRY_POINTS.includes(entryPoint.toLowerCase()) - ); -} From 620915098fd7cc11a571df02aa8eac61532e2733 Mon Sep 17 00:00:00 2001 From: Dmytro Vynnyk Date: Thu, 18 Dec 2025 21:21:49 +0100 Subject: [PATCH 09/17] Add `WASM` and `WASM_PROXY` deploy types and related utilities for deploy type detection --- src/data/dto/deploys/common.ts | 5 ++++- src/domain/deploys/entities.ts | 2 ++ src/utils/deploy.ts | 8 ++++++-- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/data/dto/deploys/common.ts b/src/data/dto/deploys/common.ts index 4161912..1d20ee0 100644 --- a/src/data/dto/deploys/common.ts +++ b/src/data/dto/deploys/common.ts @@ -12,7 +12,6 @@ import { AccountKeyType, AssociatedKeysContractHash, AuctionManagerContractHash, - CEP_18_ACTION_ENTRY_POINTS, CSPRMarketContractHash, CSPRStudioCep47ContractHash, DeployType, @@ -47,6 +46,10 @@ export function getDeployType(network: Network, deploy?: Partial { return deploy.type === 'NFT'; }; +export const isWasmDeploy = (deploy: IDeploy): deploy is INftDeploy => { + return deploy.type === 'WASM'; +}; +export const isWasmProxyDeploy = (deploy: IDeploy): deploy is INftDeploy => { + return deploy.type === 'WASM_PROXY'; +}; export const isUnknownDeploy = (deploy: IDeploy): deploy is IDeploy => { return deploy.type === 'UNKNOWN'; }; -export const isWasmDeployExecutionType = (deploy: IDeploy) => - Number(deploy.executionTypeId) === 1 || Number(deploy.executionTypeId) === 7; export const isContractCallExecutionType = (deploy: IDeploy) => Number(deploy.executionTypeId) > 1 && Number(deploy.executionTypeId) < 6; export const isTransferExecutionType = (deploy: IDeploy) => Number(deploy.executionTypeId) === 6; From 9e68c6e6fd2f39db9078d5fdc05348ea27f22e45 Mon Sep 17 00:00:00 2001 From: Dmytro Vynnyk Date: Mon, 22 Dec 2025 17:11:20 +0100 Subject: [PATCH 10/17] Extend `Cep18DeployDto` to handle `recipientAccountHash` by utilizing `deriveSplitDataFromNamedKeyValue`. --- src/data/dto/deploys/Cep18DeployDto.ts | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/data/dto/deploys/Cep18DeployDto.ts b/src/data/dto/deploys/Cep18DeployDto.ts index 87a2a1a..f8f1c1a 100644 --- a/src/data/dto/deploys/Cep18DeployDto.ts +++ b/src/data/dto/deploys/Cep18DeployDto.ts @@ -1,4 +1,9 @@ -import { getDeployAmount, getEntryPoint, guardedDeriveSplitDataFromArguments } from './common'; +import { + deriveSplitDataFromNamedKeyValue, + getDeployAmount, + getEntryPoint, + guardedDeriveSplitDataFromArguments, +} from './common'; import { formatTokenBalance, getAccountHashFromPublicKey, @@ -101,7 +106,15 @@ export function getCep18RecipientKeyAndType( const owner = guardedDeriveSplitDataFromArguments(data?.args?.owner, 'Account'); const spender = guardedDeriveSplitDataFromArguments(data?.args?.spender, 'Hash'); - const info = recipientAccount ?? owner ?? recipient ?? spender; + const recipientAccountHash = + typeof data?.args?.recipient?.parsed === 'string' + ? { + ...deriveSplitDataFromNamedKeyValue(data?.args?.recipient?.parsed), + keyType: 'accountHash' as const, + } + : null; + + const info = recipientAccount ?? owner ?? recipient ?? spender ?? recipientAccountHash; if (info?.keyType === 'accountHash' && info?.hash) { const publicKey = derivePublicKeyFromCep18ActionResults(info.hash, data); From 3c21b4e37cd03b93153b97242555a3996c47d4d7 Mon Sep 17 00:00:00 2001 From: Dmytro Vynnyk Date: Mon, 22 Dec 2025 18:55:32 +0100 Subject: [PATCH 11/17] Lockfile updates: bump dependencies (`@noble/curves`, `@scure/base`, `@types/node`, `axios`, `humanize-duration`, `undici-types`, and others) to latest compatible versions. --- package.json | 2 +- yarn.lock | 64 ++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 45 insertions(+), 21 deletions(-) diff --git a/package.json b/package.json index 82333d5..86670df 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "@react-native/typescript-config": "0.74.83", "@types/uuid": "^10.0.0", "apisauce": "^3.1.1", - "casper-js-sdk": "^5.0.6", + "casper-js-sdk": "5.0.6", "date-fns": "^2.30.0", "decimal.js": "^10.4.3", "lru-cache": "10.4.3", diff --git a/yarn.lock b/yarn.lock index ffc2138..21e1979 100644 --- a/yarn.lock +++ b/yarn.lock @@ -352,11 +352,11 @@ __metadata: linkType: hard "@noble/curves@npm:^1.1.0, @noble/curves@npm:~1.9.0": - version: 1.9.1 - resolution: "@noble/curves@npm:1.9.1" + version: 1.9.7 + resolution: "@noble/curves@npm:1.9.7" dependencies: "@noble/hashes": "npm:1.8.0" - checksum: 10c0/39c84dbfecdca80cfde2ecea4b06ef2ec1255a4df40158d22491d1400057a283f57b2b26c8b1331006e6e061db791f31d47764961c239437032e2f45e8888c1e + checksum: 10c0/150014751ebe8ca06a8654ca2525108452ea9ee0be23430332769f06808cddabfe84f248b6dbf836916bc869c27c2092957eec62c7506d68a1ed0a624017c2a3 languageName: node linkType: hard @@ -466,9 +466,9 @@ __metadata: linkType: hard "@scure/base@npm:~1.2.5": - version: 1.2.5 - resolution: "@scure/base@npm:1.2.5" - checksum: 10c0/078928dbcdd21a037b273b81b8b0bd93af8a325e2ffd535b7ccaadd48ee3c15bab600ec2920a209fca0910abc792cca9b01d3336b472405c407440e6c0aa8bd6 + version: 1.2.6 + resolution: "@scure/base@npm:1.2.6" + checksum: 10c0/49bd5293371c4e062cb6ba689c8fe3ea3981b7bb9c000400dc4eafa29f56814cdcdd27c04311c2fec34de26bc373c593a1d6ca6d754398a488d587943b7c128a languageName: node linkType: hard @@ -501,11 +501,11 @@ __metadata: linkType: hard "@types/node@npm:*": - version: 22.15.24 - resolution: "@types/node@npm:22.15.24" + version: 25.0.3 + resolution: "@types/node@npm:25.0.3" dependencies: - undici-types: "npm:~6.21.0" - checksum: 10c0/16c38e98168fa6c3d2f2b6e95f14f80878d969b39093bc5384385a884d73a7fe361c563b36f14bc27536b337f5baad74321f717b31d2c061b9c48074567eb8c6 + undici-types: "npm:~7.16.0" + checksum: 10c0/b7568f0d765d9469621615e2bb257c7fd1953d95e9acbdb58dffb6627a2c4150d405a4600aa1ad8a40182a94fe5f903cafd3c0a2f5132814debd0e3bfd61f835 languageName: node linkType: hard @@ -727,7 +727,7 @@ __metadata: "@react-native/typescript-config": "npm:0.74.83" "@types/uuid": "npm:^10.0.0" apisauce: "npm:^3.1.1" - casper-js-sdk: "npm:^5.0.6" + casper-js-sdk: "npm:5.0.6" date-fns: "npm:^2.30.0" decimal.js: "npm:^10.4.3" eslint: "npm:8.22.0" @@ -959,7 +959,7 @@ __metadata: languageName: node linkType: hard -"axios@npm:^1.7.7, axios@npm:^1.8.4": +"axios@npm:^1.7.7": version: 1.9.0 resolution: "axios@npm:1.9.0" dependencies: @@ -970,6 +970,17 @@ __metadata: languageName: node linkType: hard +"axios@npm:^1.8.4": + version: 1.13.2 + resolution: "axios@npm:1.13.2" + dependencies: + follow-redirects: "npm:^1.15.6" + form-data: "npm:^4.0.4" + proxy-from-env: "npm:^1.1.0" + checksum: 10c0/e8a42e37e5568ae9c7a28c348db0e8cf3e43d06fcbef73f0048669edfe4f71219664da7b6cc991b0c0f01c28a48f037c515263cb79be1f1ae8ff034cd813867b + languageName: node + linkType: hard + "balanced-match@npm:^1.0.0": version: 1.0.2 resolution: "balanced-match@npm:1.0.2" @@ -1086,7 +1097,7 @@ __metadata: languageName: node linkType: hard -"casper-js-sdk@npm:^5.0.6": +"casper-js-sdk@npm:5.0.6": version: 5.0.6 resolution: "casper-js-sdk@npm:5.0.6" dependencies: @@ -2015,6 +2026,19 @@ __metadata: languageName: node linkType: hard +"form-data@npm:^4.0.4": + version: 4.0.5 + resolution: "form-data@npm:4.0.5" + dependencies: + asynckit: "npm:^0.4.0" + combined-stream: "npm:^1.0.8" + es-set-tostringtag: "npm:^2.1.0" + hasown: "npm:^2.0.2" + mime-types: "npm:^2.1.12" + checksum: 10c0/dd6b767ee0bbd6d84039db12a0fa5a2028160ffbfaba1800695713b46ae974a5f6e08b3356c3195137f8530dcd9dfcb5d5ae1eeff53d0db1e5aad863b619ce3b + languageName: node + linkType: hard + "fs.realpath@npm:^1.0.0": version: 1.0.0 resolution: "fs.realpath@npm:1.0.0" @@ -2289,9 +2313,9 @@ __metadata: linkType: hard "humanize-duration@npm:^3.24.0": - version: 3.32.2 - resolution: "humanize-duration@npm:3.32.2" - checksum: 10c0/c267d69e3e1206b6326a33218a8dd4c5980adccdd750f1b3e9837719c4519e2587463e86e81fadfa8d8c0e107101b4dfcaa6dd8e99265a794c58907d266c679f + version: 3.33.2 + resolution: "humanize-duration@npm:3.33.2" + checksum: 10c0/eae493c113f1c11c96e42195002e8016ab7c08bfcc3414ba5459027da4faaa2df012429bc4eae200873a65d0a86b7cc6a9656783aa45705ffe6106b5256af973 languageName: node linkType: hard @@ -3957,10 +3981,10 @@ __metadata: languageName: node linkType: hard -"undici-types@npm:~6.21.0": - version: 6.21.0 - resolution: "undici-types@npm:6.21.0" - checksum: 10c0/c01ed51829b10aa72fc3ce64b747f8e74ae9b60eafa19a7b46ef624403508a54c526ffab06a14a26b3120d055e1104d7abe7c9017e83ced038ea5cf52f8d5e04 +"undici-types@npm:~7.16.0": + version: 7.16.0 + resolution: "undici-types@npm:7.16.0" + checksum: 10c0/3033e2f2b5c9f1504bdc5934646cb54e37ecaca0f9249c983f7b1fc2e87c6d18399ebb05dc7fd5419e02b2e915f734d872a65da2e3eeed1813951c427d33cc9a languageName: node linkType: hard From 3842cd779a75f86503bcce6a6280fa193dd64428 Mon Sep 17 00:00:00 2001 From: Dmytro Vynnyk Date: Mon, 2 Mar 2026 23:37:53 +0100 Subject: [PATCH 12/17] Add support for customizable HTTP Authorization headers in setup and HTTP data providers --- src/data/data-providers/http/http.ts | 4 ++-- src/data/repositories/txSignatureRequest/index.ts | 13 +++++++++++++ src/domain/common/http/data-provider.ts | 2 +- src/setup.ts | 7 +++++++ 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/data/data-providers/http/http.ts b/src/data/data-providers/http/http.ts index 0cf92d5..3e73694 100644 --- a/src/data/data-providers/http/http.ts +++ b/src/data/data-providers/http/http.ts @@ -177,8 +177,8 @@ export class HttpDataProvider implements IHttpDataProvider { }); } - setAuthHeader(token: string) { - this.instance.setHeader(HttpDataProvider.AUTH_HEADER_KEY, `Bearer ${token}`); + setAuthHeader(value: string) { + this.instance.setHeader(HttpDataProvider.AUTH_HEADER_KEY, value); } removeAuthHeader() { diff --git a/src/data/repositories/txSignatureRequest/index.ts b/src/data/repositories/txSignatureRequest/index.ts index b66ebe8..4d991c3 100644 --- a/src/data/repositories/txSignatureRequest/index.ts +++ b/src/data/repositories/txSignatureRequest/index.ts @@ -48,6 +48,7 @@ export class TxSignatureRequestRepository implements ITxSignatureRequestReposito private _contractPackageRepository: IContractPackageRepository, private _casperWalletApiByEnvUrl: Record, private _grpcUrl: Record, + private _httpAuthorizationHeader?: string, ) {} async prepareSignatureRequest({ @@ -134,6 +135,12 @@ export class TxSignatureRequestRepository implements ITxSignatureRequestReposito try { const handler = new HttpHandler(this._grpcUrl[network], 'fetch'); + if (this._httpAuthorizationHeader) { + handler.setCustomHeaders({ + Authorization: this._httpAuthorizationHeader, + }); + } + if (withProxyHeader) { handler.setReferrer(CSPR_API_PROXY_HEADERS.Referer); } @@ -267,6 +274,12 @@ export class TxSignatureRequestRepository implements ITxSignatureRequestReposito const handler = new HttpHandler(this._grpcUrl[network], 'fetch'); + if (this._httpAuthorizationHeader) { + handler.setCustomHeaders({ + Authorization: this._httpAuthorizationHeader, + }); + } + if (withProxyHeader) { handler.setReferrer(CSPR_API_PROXY_HEADERS.Referer); } diff --git a/src/domain/common/http/data-provider.ts b/src/domain/common/http/data-provider.ts index 7bb6f91..4dd59f0 100644 --- a/src/domain/common/http/data-provider.ts +++ b/src/domain/common/http/data-provider.ts @@ -21,7 +21,7 @@ export interface IHttpDataProvider { head: (params: HttpMethodParamsType) => Promise | undefined>; setUpBaseUrl: (url: string) => void; - setAuthHeader: (token: string) => void; + setAuthHeader: (value: string) => void; removeAuthHeader: () => void; } diff --git a/src/setup.ts b/src/setup.ts index 13dba55..8ede33b 100644 --- a/src/setup.ts +++ b/src/setup.ts @@ -27,6 +27,7 @@ export interface ISetupRepositoriesParams { /** Environment-based url for Casper Wallet Api. Some API network agnostic and do not belong to any {@link CasperWalletApiByNetworkUrl}. Default env is PRODUCTION (in all places where it is used) */ casperWalletApiByEnvUrl?: Record; grpcUrl?: Record; + httpAuthorizationHeader?: string; } export const setupRepositories = ({ @@ -35,10 +36,15 @@ export const setupRepositories = ({ casperWalletApiByNetworkUrl = CasperWalletApiByNetworkUrl, casperWalletApiByEnvUrl = CasperWalletApiByEnvUrl, grpcUrl = GrpcUrl, + httpAuthorizationHeader, }: ISetupRepositoriesParams = {}) => { const log = logger ?? new Logger(); const httpDataProvider = new HttpDataProvider(debug ? log : null); + if (httpAuthorizationHeader) { + httpDataProvider.setAuthHeader(httpAuthorizationHeader); + } + const accountInfoRepository = new AccountInfoRepository( httpDataProvider, casperWalletApiByNetworkUrl, @@ -67,6 +73,7 @@ export const setupRepositories = ({ contractPackageRepository, casperWalletApiByEnvUrl, grpcUrl, + httpAuthorizationHeader, ); return { From 1c11b290d756778e9cae94708eb14d02cba39e9b Mon Sep 17 00:00:00 2001 From: Dmytro Vynnyk Date: Mon, 2 Mar 2026 23:39:44 +0100 Subject: [PATCH 13/17] Bump `apisauce` to `^3.2.2`, `axios` to `^1.13.6`, and `casper-js-sdk` to `5.0.10`. --- package.json | 4 +- yarn.lock | 115 ++++++++++++++------------------------------------- 2 files changed, 33 insertions(+), 86 deletions(-) diff --git a/package.json b/package.json index 86670df..6ae1dd4 100644 --- a/package.json +++ b/package.json @@ -15,8 +15,8 @@ "@noble/hashes": "^1.8.0", "@react-native/typescript-config": "0.74.83", "@types/uuid": "^10.0.0", - "apisauce": "^3.1.1", - "casper-js-sdk": "5.0.6", + "apisauce": "^3.2.2", + "casper-js-sdk": "5.0.10", "date-fns": "^2.30.0", "decimal.js": "^10.4.3", "lru-cache": "10.4.3", diff --git a/yarn.lock b/yarn.lock index 21e1979..4462043 100644 --- a/yarn.lock +++ b/yarn.lock @@ -726,8 +726,8 @@ __metadata: "@react-native/eslint-config": "npm:0.74.83" "@react-native/typescript-config": "npm:0.74.83" "@types/uuid": "npm:^10.0.0" - apisauce: "npm:^3.1.1" - casper-js-sdk: "npm:5.0.6" + apisauce: "npm:^3.2.2" + casper-js-sdk: "npm:5.0.10" date-fns: "npm:^2.30.0" decimal.js: "npm:^10.4.3" eslint: "npm:8.22.0" @@ -811,12 +811,12 @@ __metadata: languageName: node linkType: hard -"apisauce@npm:^3.1.1": - version: 3.1.1 - resolution: "apisauce@npm:3.1.1" +"apisauce@npm:^3.2.2": + version: 3.2.2 + resolution: "apisauce@npm:3.2.2" dependencies: - axios: "npm:^1.7.7" - checksum: 10c0/a88498049588e803042b1b5e2ffe3670aa61e6381b2c6a88afd4f47b1e50e1bd574ba9719c6891c92cecff207812387f861e4115666600bd8e09e6d3bbab231b + axios: "npm:^1.11.0" + checksum: 10c0/512ea3c454ab9091af89d2b7fb4ab06a6458d5c3ffcdee2b24ac0c00bbe8a612c93ade636d1ecf4c994f89bb3b98a8fb8a3da821f0041f4e73a32fb114c495a6 languageName: node linkType: hard @@ -959,14 +959,14 @@ __metadata: languageName: node linkType: hard -"axios@npm:^1.7.7": - version: 1.9.0 - resolution: "axios@npm:1.9.0" +"axios@npm:^1.11.0": + version: 1.13.6 + resolution: "axios@npm:1.13.6" dependencies: - follow-redirects: "npm:^1.15.6" - form-data: "npm:^4.0.0" + follow-redirects: "npm:^1.15.11" + form-data: "npm:^4.0.5" proxy-from-env: "npm:^1.1.0" - checksum: 10c0/9371a56886c2e43e4ff5647b5c2c3c046ed0a3d13482ef1d0135b994a628c41fbad459796f101c655e62f0c161d03883454474d2e435b2e021b1924d9f24994c + checksum: 10c0/51fb5af055c3b85662fa97df17d986ae2c37d13bf86d50b6bb36b6b3a2dec6966a1d3a14ab3774b71707b155ae3597ed9b7babdf1a1a863d1a31840cb8e7ec71 languageName: node linkType: hard @@ -988,7 +988,7 @@ __metadata: languageName: node linkType: hard -"bn.js@npm:^4.0.0, bn.js@npm:^4.11.9": +"bn.js@npm:^4.0.0": version: 4.12.2 resolution: "bn.js@npm:4.12.2" checksum: 10c0/09a249faa416a9a1ce68b5f5ec8bbca87fe54e5dd4ef8b1cc8a4969147b80035592bddcb1e9cc814c3ba79e573503d5c5178664b722b509fb36d93620dba9b57 @@ -1030,13 +1030,6 @@ __metadata: languageName: node linkType: hard -"brorand@npm:^1.1.0": - version: 1.1.0 - resolution: "brorand@npm:1.1.0" - checksum: 10c0/6f366d7c4990f82c366e3878492ba9a372a73163c09871e80d82fb4ae0d23f9f8924cb8a662330308206e6b3b76ba1d528b4601c9ef73c2166b440b2ea3b7571 - languageName: node - linkType: hard - "browserslist@npm:^4.24.0": version: 4.25.0 resolution: "browserslist@npm:4.25.0" @@ -1097,9 +1090,9 @@ __metadata: languageName: node linkType: hard -"casper-js-sdk@npm:5.0.6": - version: 5.0.6 - resolution: "casper-js-sdk@npm:5.0.6" +"casper-js-sdk@npm:5.0.10": + version: 5.0.10 + resolution: "casper-js-sdk@npm:5.0.10" dependencies: "@ethersproject/bignumber": "npm:^5.0.8" "@ethersproject/bytes": "npm:^5.0.5" @@ -1115,7 +1108,6 @@ __metadata: asn1.js: "npm:^5.4.1" axios: "npm:^1.8.4" bn.js: "npm:^5.2.1" - elliptic: "npm:6.6.1" eventsource: "npm:^2.0.2" glob: "npm:^7.1.6" humanize-duration: "npm:^3.24.0" @@ -1124,7 +1116,7 @@ __metadata: reflect-metadata: "npm:^0.1.13" ts-results: "npm:@casperlabs/ts-results@^3.3.4" typedjson: "npm:^1.6.0-rc2" - checksum: 10c0/66b09b8f2ea9de9078cd3d3a4bf8a1bc0f5cbfad224525a8f240f60f1636b4f023c6b48eecae04566bd85dc5034ba3985bd0a6a6982de07b54101d2d06dac7cc + checksum: 10c0/5e6415b0e1ddbb5711c382dfd5b6ab8d15a9ddd34d9b2f5a51b012909031443831ded2e3a13ae66dd8eb7fe0fcb35a1c7a33c4be2d3e4dc35803f9655f082ef8 languageName: node linkType: hard @@ -1389,21 +1381,6 @@ __metadata: languageName: node linkType: hard -"elliptic@npm:6.6.1": - version: 6.6.1 - resolution: "elliptic@npm:6.6.1" - dependencies: - bn.js: "npm:^4.11.9" - brorand: "npm:^1.1.0" - hash.js: "npm:^1.0.0" - hmac-drbg: "npm:^1.0.1" - inherits: "npm:^2.0.4" - minimalistic-assert: "npm:^1.0.1" - minimalistic-crypto-utils: "npm:^1.0.1" - checksum: 10c0/8b24ef782eec8b472053793ea1e91ae6bee41afffdfcb78a81c0a53b191e715cbe1292aa07165958a9bbe675bd0955142560b1a007ffce7d6c765bcaf951a867 - languageName: node - linkType: hard - "emoji-regex@npm:^9.2.2": version: 9.2.2 resolution: "emoji-regex@npm:9.2.2" @@ -1995,6 +1972,16 @@ __metadata: languageName: node linkType: hard +"follow-redirects@npm:^1.15.11": + version: 1.15.11 + resolution: "follow-redirects@npm:1.15.11" + peerDependenciesMeta: + debug: + optional: true + checksum: 10c0/d301f430542520a54058d4aeeb453233c564aaccac835d29d15e050beb33f339ad67d9bddbce01739c5dc46a6716dbe3d9d0d5134b1ca203effa11a7ef092343 + languageName: node + linkType: hard + "follow-redirects@npm:^1.15.6": version: 1.15.9 resolution: "follow-redirects@npm:1.15.9" @@ -2014,19 +2001,7 @@ __metadata: languageName: node linkType: hard -"form-data@npm:^4.0.0": - version: 4.0.2 - resolution: "form-data@npm:4.0.2" - dependencies: - asynckit: "npm:^0.4.0" - combined-stream: "npm:^1.0.8" - es-set-tostringtag: "npm:^2.1.0" - mime-types: "npm:^2.1.12" - checksum: 10c0/e534b0cf025c831a0929bf4b9bbe1a9a6b03e273a8161f9947286b9b13bf8fb279c6944aae0070c4c311100c6d6dbb815cd955dc217728caf73fad8dc5b8ee9c - languageName: node - linkType: hard - -"form-data@npm:^4.0.4": +"form-data@npm:^4.0.4, form-data@npm:^4.0.5": version: 4.0.5 resolution: "form-data@npm:4.0.5" dependencies: @@ -2275,16 +2250,6 @@ __metadata: languageName: node linkType: hard -"hash.js@npm:^1.0.0, hash.js@npm:^1.0.3": - version: 1.1.7 - resolution: "hash.js@npm:1.1.7" - dependencies: - inherits: "npm:^2.0.3" - minimalistic-assert: "npm:^1.0.1" - checksum: 10c0/41ada59494eac5332cfc1ce6b7ebdd7b88a3864a6d6b08a3ea8ef261332ed60f37f10877e0c825aaa4bddebf164fbffa618286aeeec5296675e2671cbfa746c4 - languageName: node - linkType: hard - "hasown@npm:^2.0.2": version: 2.0.2 resolution: "hasown@npm:2.0.2" @@ -2294,17 +2259,6 @@ __metadata: languageName: node linkType: hard -"hmac-drbg@npm:^1.0.1": - version: 1.0.1 - resolution: "hmac-drbg@npm:1.0.1" - dependencies: - hash.js: "npm:^1.0.3" - minimalistic-assert: "npm:^1.0.0" - minimalistic-crypto-utils: "npm:^1.0.1" - checksum: 10c0/f3d9ba31b40257a573f162176ac5930109816036c59a09f901eb2ffd7e5e705c6832bedfff507957125f2086a0ab8f853c0df225642a88bf1fcaea945f20600d - languageName: node - linkType: hard - "human-signals@npm:^4.3.0": version: 4.3.1 resolution: "human-signals@npm:4.3.1" @@ -2362,7 +2316,7 @@ __metadata: languageName: node linkType: hard -"inherits@npm:2, inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:^2.0.4": +"inherits@npm:2, inherits@npm:^2.0.1": version: 2.0.4 resolution: "inherits@npm:2.0.4" checksum: 10c0/4e531f648b29039fb7426fb94075e6545faa1eb9fe83c29f0b6d9e7263aceb4289d2d4557db0d428188eeb449cc7c5e77b0a0b2c4e248ff2a65933a0dee49ef2 @@ -2941,20 +2895,13 @@ __metadata: languageName: node linkType: hard -"minimalistic-assert@npm:^1.0.0, minimalistic-assert@npm:^1.0.1": +"minimalistic-assert@npm:^1.0.0": version: 1.0.1 resolution: "minimalistic-assert@npm:1.0.1" checksum: 10c0/96730e5601cd31457f81a296f521eb56036e6f69133c0b18c13fe941109d53ad23a4204d946a0d638d7f3099482a0cec8c9bb6d642604612ce43ee536be3dddd languageName: node linkType: hard -"minimalistic-crypto-utils@npm:^1.0.1": - version: 1.0.1 - resolution: "minimalistic-crypto-utils@npm:1.0.1" - checksum: 10c0/790ecec8c5c73973a4fbf2c663d911033e8494d5fb0960a4500634766ab05d6107d20af896ca2132e7031741f19888154d44b2408ada0852446705441383e9f8 - languageName: node - linkType: hard - "minimatch@npm:9.0.3": version: 9.0.3 resolution: "minimatch@npm:9.0.3" From 079845a5e6e1374b8299a1c3efd5841d9d83eb60 Mon Sep 17 00:00:00 2001 From: Dmytro Vynnyk Date: Mon, 2 Mar 2026 23:40:15 +0100 Subject: [PATCH 14/17] Remove unused `CEP_18_ACTION_ENTRY_POINTS` import from `TxSignatureRequestDto`. --- src/data/dto/txSignatureRequest/TxSignatureRequestDto.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/data/dto/txSignatureRequest/TxSignatureRequestDto.ts b/src/data/dto/txSignatureRequest/TxSignatureRequestDto.ts index 3cc6301..f6ee858 100644 --- a/src/data/dto/txSignatureRequest/TxSignatureRequestDto.ts +++ b/src/data/dto/txSignatureRequest/TxSignatureRequestDto.ts @@ -5,7 +5,6 @@ import { AssociatedKeysContractInfo, AuctionManagerContractInfo, CasperNetwork, - CEP_18_ACTION_ENTRY_POINTS, CSPR_COIN, CSPRMarketContractInfo, IAccountInfo, From bae9073e6872fbdeb295ca9e0b2e3ec608682016 Mon Sep 17 00:00:00 2001 From: Dmytro Vynnyk Date: Thu, 5 Mar 2026 22:12:25 +0100 Subject: [PATCH 15/17] Add `getTransactionsFeed` method to deploys repository and extend DTOs to handle `ICloudTransactionFeedItem`. Simplify fiat amount calculations. --- src/data/dto/deploys/ActionResults.ts | 13 ++-- .../dto/deploys/AssociatedKeysDeployDto.ts | 4 +- src/data/dto/deploys/AuctionDeployDto.ts | 15 +++-- src/data/dto/deploys/Cep18DeployDto.ts | 8 +-- src/data/dto/deploys/CsprMarketDeployDto.ts | 11 ++-- src/data/dto/deploys/DeployDto.ts | 18 +++--- src/data/dto/deploys/NativeCsprDeployDto.ts | 11 ++-- src/data/dto/deploys/NftDeployDto.ts | 6 +- src/data/dto/deploys/common.ts | 29 ++++++--- src/data/dto/deploys/index.ts | 4 +- src/data/repositories/deploys/index.ts | 60 ++++++++++++++++++- src/data/repositories/deploys/types.ts | 33 ++++++++++ src/domain/deploys/repository.ts | 1 + 13 files changed, 151 insertions(+), 62 deletions(-) diff --git a/src/data/dto/deploys/ActionResults.ts b/src/data/dto/deploys/ActionResults.ts index ed7ebc4..4cd5cb9 100644 --- a/src/data/dto/deploys/ActionResults.ts +++ b/src/data/dto/deploys/ActionResults.ts @@ -16,7 +16,7 @@ import { NFTEntryPointType, } from '../../../domain'; import { getAccountInfoFromMap, getNftTokenUrlsMap } from '../common'; -import { ExtendedCloudDeploy } from '../../repositories'; +import { ExtendedCloudDeploy, ICloudTransactionFeedItem } from '../../repositories'; import { getCsprFiatAmount } from '../common'; const mapCep18EntryPointIdToName: Record = { @@ -36,7 +36,7 @@ const mapNftentryPointIdToName: Record = { export function getCep18ActionsResult( activePublicKey: string, - deploy?: Partial, + deploy?: Partial, accountInfoMap: Record = {}, ) { return ( @@ -93,7 +93,7 @@ export function getNftActionsResult( activePublicKey: string, network: Network, collectionHash: string, - deploy?: Partial, + deploy?: Partial, accountInfoMap: Record = {}, ) { return ( @@ -141,7 +141,7 @@ export function getNftActionsResult( export function getTransferActionsResult( activePublicKey: string, - deploy?: Partial, + deploy?: Partial, accountInfoMap: Record = {}, ) { return ( @@ -180,10 +180,7 @@ export function getTransferActionsResult( amount: action.amount, decimalAmount: getDecimalTokenBalance(action.amount, CSPR_COIN.decimals), formattedDecimalAmount: formatTokenBalance(action.amount, CSPR_COIN.decimals), - fiatAmount: getCsprFiatAmount( - action.amount, - deploy?.time_transaction_currency_rate ?? deploy?.rate, - ), + fiatAmount: getCsprFiatAmount(action.amount, deploy?.rate), }; }) ?? [] ); diff --git a/src/data/dto/deploys/AssociatedKeysDeployDto.ts b/src/data/dto/deploys/AssociatedKeysDeployDto.ts index 386ec91..dfa4e35 100644 --- a/src/data/dto/deploys/AssociatedKeysDeployDto.ts +++ b/src/data/dto/deploys/AssociatedKeysDeployDto.ts @@ -1,6 +1,6 @@ import { DeployDto } from './DeployDto'; import { getEntryPoint } from './common'; -import { ExtendedCloudDeploy } from '../../repositories'; +import { ExtendedCloudDeploy, ICloudTransactionFeedItem } from '../../repositories'; import { IAccountInfo, IAssociatedKeysDeploy, Network } from '../../../domain'; import { Maybe } from '../../../typings'; @@ -8,7 +8,7 @@ export class AssociatedKeysDeployDto extends DeployDto implements IAssociatedKey constructor( network: Network, activePublicKey: string, - data?: Partial, + data?: Partial, accountInfoMap: Record = {}, ) { super(network, activePublicKey, data, accountInfoMap); diff --git a/src/data/dto/deploys/AuctionDeployDto.ts b/src/data/dto/deploys/AuctionDeployDto.ts index e4f0691..a740853 100644 --- a/src/data/dto/deploys/AuctionDeployDto.ts +++ b/src/data/dto/deploys/AuctionDeployDto.ts @@ -10,7 +10,7 @@ import { getDeployAmount, getEntryPoint } from './common'; import { deriveKeyType, getAccountInfoFromMap } from '../common'; import { formatTokenBalance, getDecimalTokenBalance } from '../../../utils'; import { DeployDto } from './DeployDto'; -import { ExtendedCloudDeploy } from '../../repositories'; +import { ExtendedCloudDeploy, ICloudTransactionFeedItem } from '../../repositories'; import { Maybe } from '../../../typings'; import { getCsprFiatAmount } from '../common'; @@ -18,7 +18,7 @@ export class AuctionDeployDto extends DeployDto implements IAuctionDeploy { constructor( network: Network, activePublicKey: string, - data?: Partial, + data?: Partial, accountInfoMap: Record = {}, ) { super(network, activePublicKey, data, accountInfoMap); @@ -29,10 +29,7 @@ export class AuctionDeployDto extends DeployDto implements IAuctionDeploy { this.amount = getDeployAmount(data?.args); this.decimalAmount = getDecimalTokenBalance(this.amount, this.decimals); this.formattedDecimalAmount = formatTokenBalance(this.amount, this.decimals); - this.fiatAmount = getCsprFiatAmount( - this.amount, - data?.time_transaction_currency_rate ?? data?.rate, - ); + this.fiatAmount = getCsprFiatAmount(this.amount, data?.rate); const fromValidator = getFromValidator(data); const fromValidatorKeyType = deriveKeyType(fromValidator); @@ -76,7 +73,9 @@ export class AuctionDeployDto extends DeployDto implements IAuctionDeploy { readonly fiatAmount: string; } -function getFromValidator(data?: Partial): string | null { +function getFromValidator( + data?: Partial, +): string | null { const entryPoint = getEntryPoint(data); if (entryPoint === 'undelegate' && data?.args?.validator?.cl_type === 'PublicKey') { @@ -88,7 +87,7 @@ function getFromValidator(data?: Partial): string | null { return null; } -function getToValidator(data?: Partial) { +function getToValidator(data?: Partial) { const entryPoint = getEntryPoint(data); if (data?.args?.new_validator) { diff --git a/src/data/dto/deploys/Cep18DeployDto.ts b/src/data/dto/deploys/Cep18DeployDto.ts index f8f1c1a..beea4ce 100644 --- a/src/data/dto/deploys/Cep18DeployDto.ts +++ b/src/data/dto/deploys/Cep18DeployDto.ts @@ -13,7 +13,7 @@ import { isNotEmpty, } from '../../../utils'; import { DeployDto } from './DeployDto'; -import { ExtendedCloudDeploy } from '../../repositories'; +import { ExtendedCloudDeploy, ICloudTransactionFeedItem } from '../../repositories'; import { AccountKeyType, CEP18EntryPointType, @@ -29,7 +29,7 @@ export class Cep18DeployDto extends DeployDto implements ICep18Deploy { constructor( network: Network, activePublicKey: string, - data?: Partial, + data?: Partial, accountInfoMap: Record = {}, ) { super(network, activePublicKey, data, accountInfoMap); @@ -99,7 +99,7 @@ export class Cep18DeployDto extends DeployDto implements ICep18Deploy { } export function getCep18RecipientKeyAndType( - data?: Partial, + data?: Partial, ): Pick { const recipient = guardedDeriveSplitDataFromArguments(data?.args?.recipient, 'Hash'); const recipientAccount = guardedDeriveSplitDataFromArguments(data?.args?.recipient, 'Account'); @@ -135,7 +135,7 @@ export function getCep18RecipientKeyAndType( export function derivePublicKeyFromCep18ActionResults( accountHash: string, - deploy?: Partial, + deploy?: Partial, ) { return deploy?.ft_token_actions ?.reduce((acc, cur) => { diff --git a/src/data/dto/deploys/CsprMarketDeployDto.ts b/src/data/dto/deploys/CsprMarketDeployDto.ts index a5e72dc..16b204c 100644 --- a/src/data/dto/deploys/CsprMarketDeployDto.ts +++ b/src/data/dto/deploys/CsprMarketDeployDto.ts @@ -18,7 +18,7 @@ import { Network, } from '../../../domain'; import { DeployDto } from './DeployDto'; -import { ExtendedCloudDeploy } from '../../repositories'; +import { ExtendedCloudDeploy, ICloudTransactionFeedItem } from '../../repositories'; import { Maybe } from '../../../typings'; import { getAccountInfoFromMap, getCsprFiatAmount, getNftTokenUrlsMap } from '../common'; @@ -26,7 +26,7 @@ export class CsprMarketDeployDto extends DeployDto implements ICasperMarketDeplo constructor( network: Network, activePublicKey: string, - data?: Partial, + data?: Partial, accountInfoMap: Record = {}, ) { super(network, activePublicKey, data, accountInfoMap); @@ -50,10 +50,7 @@ export class CsprMarketDeployDto extends DeployDto implements ICasperMarketDeplo this.amount = getDeployAmount(data?.args); this.decimalAmount = getDecimalTokenBalance(this.amount, CSPR_COIN.decimals); this.formattedDecimalAmount = formatTokenBalance(this.amount, CSPR_COIN.decimals); - this.fiatAmount = getCsprFiatAmount( - this.amount, - data?.time_transaction_currency_rate ?? data?.rate, - ); + this.fiatAmount = getCsprFiatAmount(this.amount, data?.rate); this.iconUrl = data?.contract_package?.icon_url ?? null; } @@ -74,7 +71,7 @@ export class CsprMarketDeployDto extends DeployDto implements ICasperMarketDeplo } export function getOffererFormDeploy( - deploy?: Partial, + deploy?: Partial, ): Pick { const offererHash = guardedDeriveSplitDataFromArguments(deploy?.args?.offerer, 'Account'); diff --git a/src/data/dto/deploys/DeployDto.ts b/src/data/dto/deploys/DeployDto.ts index 2de5945..e79bdb7 100644 --- a/src/data/dto/deploys/DeployDto.ts +++ b/src/data/dto/deploys/DeployDto.ts @@ -18,7 +18,7 @@ import { getNftActionsResult, getTransferActionsResult, } from './ActionResults'; -import { ExtendedCloudDeploy } from '../../repositories'; +import { ExtendedCloudDeploy, ICloudTransactionFeedItem } from '../../repositories'; import { Maybe } from '../../../typings'; import { getCsprFiatAmount } from '../common'; @@ -26,7 +26,7 @@ export class DeployDto implements IDeploy { constructor( network: Network, activePublicKey: string, - data?: Partial, + data?: Partial, accountInfoMap: Record = {}, ) { this.deployHash = data?.deploy_hash ?? ''; @@ -38,16 +38,10 @@ export class DeployDto implements IDeploy { this.timestamp = data?.timestamp ?? ''; this.cost = data?.consumed_gas ?? '0'; this.formattedCost = formatTokenBalance(this.cost, CSPR_COIN.decimals); - this.fiatCost = getCsprFiatAmount( - this.cost, - data?.time_transaction_currency_rate ?? data?.rate, - ); + this.fiatCost = getCsprFiatAmount(this.cost, data?.rate); this.paymentAmount = data?.payment_amount ?? '0'; this.formattedPaymentAmount = formatTokenBalance(this.paymentAmount, CSPR_COIN.decimals); - this.fiatPaymentAmount = getCsprFiatAmount( - this.paymentAmount, - data?.time_transaction_currency_rate ?? data?.rate, - ); + this.fiatPaymentAmount = getCsprFiatAmount(this.paymentAmount, data?.rate); this.contractHash = data?.contract_hash ?? ''; this.contractPackageHash = data?.contract_package_hash ?? ''; this.iconUrl = data?.contract_package?.icon_url ?? null; @@ -97,7 +91,9 @@ export class DeployDto implements IDeploy { readonly cep18ActionsResult: ICep18ActionsResult[]; } -export function getDeployStatus(deploy?: Partial): DeployStatus { +export function getDeployStatus( + deploy?: Partial, +): DeployStatus { const status = deploy?.status as DeployStatus | undefined; if (deploy?.error_message) { diff --git a/src/data/dto/deploys/NativeCsprDeployDto.ts b/src/data/dto/deploys/NativeCsprDeployDto.ts index baa6283..5269a2b 100644 --- a/src/data/dto/deploys/NativeCsprDeployDto.ts +++ b/src/data/dto/deploys/NativeCsprDeployDto.ts @@ -8,7 +8,7 @@ import { } from '../../../domain'; import { derivePublicKeyFromTransfersActionResults, getDeployAmount } from './common'; import { DeployDto } from './DeployDto'; -import { ExtendedCloudDeploy } from '../../repositories'; +import { ExtendedCloudDeploy, ICloudTransactionFeedItem } from '../../repositories'; import { Maybe } from '../../../typings'; import { getAccountInfoFromMap, getCsprFiatAmount } from '../common'; @@ -16,7 +16,7 @@ export class NativeCsprDeployDto extends DeployDto implements INativeCsprDeploy constructor( network: Network, activePublicKey: string, - data?: Partial, + data?: Partial, accountInfoMap: Record = {}, ) { super(network, activePublicKey, data, accountInfoMap); @@ -36,10 +36,7 @@ export class NativeCsprDeployDto extends DeployDto implements INativeCsprDeploy this.formattedDecimalAmount = formatTokenBalance(this.amount, this.decimals); this.entryPoint = null; this.contractName = null; - this.fiatAmount = getCsprFiatAmount( - this.amount, - data?.time_transaction_currency_rate ?? data?.rate, - ); + this.fiatAmount = getCsprFiatAmount(this.amount, data?.rate); } readonly entryPoint: Maybe; @@ -57,7 +54,7 @@ export class NativeCsprDeployDto extends DeployDto implements INativeCsprDeploy } function getNativeTransferRecipientKey( - data?: Partial, + data?: Partial, ): Pick { const recipientKeyType: AccountKeyType = data?.args?.target?.cl_type === 'PublicKey' ? 'publicKey' : 'accountHash'; diff --git a/src/data/dto/deploys/NftDeployDto.ts b/src/data/dto/deploys/NftDeployDto.ts index e4e57a1..f9f1494 100644 --- a/src/data/dto/deploys/NftDeployDto.ts +++ b/src/data/dto/deploys/NftDeployDto.ts @@ -7,7 +7,7 @@ import { guardedDeriveSplitDataFromArguments, } from './common'; import { DeployDto } from './DeployDto'; -import { ExtendedCloudDeploy } from '../../repositories'; +import { ExtendedCloudDeploy, ICloudTransactionFeedItem } from '../../repositories'; import { isKeysEqual } from '../../../utils'; import { AccountKeyType, @@ -23,7 +23,7 @@ export class NftDeployDto extends DeployDto implements INftDeploy { constructor( network: Network, activePublicKey: string, - data?: Partial, + data?: Partial, accountInfoMap: Record = {}, ) { super(network, activePublicKey, data, accountInfoMap); @@ -66,7 +66,7 @@ export class NftDeployDto extends DeployDto implements INftDeploy { } export function getNftRecipientKeys( - data?: Partial, + data?: Partial, ): Pick { const tokenOwner = guardedDeriveSplitDataFromArguments(data?.args?.token_owner, 'Account'); const owner = guardedDeriveSplitDataFromArguments(data?.args?.owner, 'Account'); diff --git a/src/data/dto/deploys/common.ts b/src/data/dto/deploys/common.ts index 1d20ee0..d85d011 100644 --- a/src/data/dto/deploys/common.ts +++ b/src/data/dto/deploys/common.ts @@ -19,11 +19,19 @@ import { Network, } from '../../../domain'; -import { ExtendedCloudDeploy, ExtendedDeployArgsResult, IApiDeployArgs } from '../../repositories'; +import { + ExtendedCloudDeploy, + ExtendedDeployArgsResult, + IApiDeployArgs, + ICloudTransactionFeedItem, +} from '../../repositories'; import { Maybe } from '../../../typings'; import { getHashByType, isCep18Action, isNftAction } from '../common'; -export function getDeployType(network: Network, deploy?: Partial): DeployType { +export function getDeployType( + network: Network, + deploy?: Partial, +): DeployType { const contractTypeId = deploy?.contract_package?.latest_version_contract_type_id || deploy?.contract_package?.contract_type_id; @@ -127,10 +135,13 @@ export const getAccountHashesFromDeployActionResults = (deploy: IDeploy): string }; export const getNftTokensQuantity = ( - data?: Partial, + data?: Partial, excludedEntryPoints: string[] = [], ) => { - if (data?.entry_point?.name && excludedEntryPoints.includes(data?.entry_point?.name)) { + if ( + data?.contract_entrypoint?.name && + excludedEntryPoints.includes(data.contract_entrypoint.name) + ) { return null; } @@ -147,13 +158,13 @@ export const getNftTokensQuantity = ( return null; }; -export function getEntryPoint(data?: Partial) { - return data?.entry_point?.name ?? data?.contract_entrypoint?.name; +export function getEntryPoint(data?: Partial) { + return /*data?.entry_point?.name ??*/ data?.contract_entrypoint?.name; } export function derivePublicKeyFromTransfersActionResults( accountHash: string, - deploy?: Partial, + deploy?: Partial, ) { return deploy?.transfers ?.reduce((acc, cur) => { @@ -167,7 +178,7 @@ export function derivePublicKeyFromTransfersActionResults( export function derivePublicKeyFromNftActionResults( accountHash: string, - deploy?: Partial, + deploy?: Partial, ) { return deploy?.nft_token_actions ?.reduce((acc, cur) => { @@ -269,7 +280,7 @@ export function getCollectionHashFormDeploy( network: Network, contractHash: string, contractPackageHash: string, - deploy?: Partial, + deploy?: Partial, ) { const collection = deploy?.args?.collection; diff --git a/src/data/dto/deploys/index.ts b/src/data/dto/deploys/index.ts index 9127b74..f8e798c 100644 --- a/src/data/dto/deploys/index.ts +++ b/src/data/dto/deploys/index.ts @@ -1,4 +1,4 @@ -import { ExtendedCloudDeploy } from '../../repositories'; +import { ExtendedCloudDeploy, ICloudTransactionFeedItem } from '../../repositories'; import { NativeCsprDeployDto } from './NativeCsprDeployDto'; import { Cep18DeployDto } from './Cep18DeployDto'; import { NftDeployDto } from './NftDeployDto'; @@ -16,7 +16,7 @@ export function processDeploy( activePublicKey: string, network: Network, accountInfoMap: Record, - data?: Partial, + data?: Partial, ): IDeploy { const type = getDeployType(network, data); diff --git a/src/data/repositories/deploys/index.ts b/src/data/repositories/deploys/index.ts index 5ae5c53..a4fc560 100644 --- a/src/data/repositories/deploys/index.ts +++ b/src/data/repositories/deploys/index.ts @@ -17,7 +17,12 @@ import { import type { IHttpDataProvider, IAccountInfoRepository } from '../../../domain'; import { getAccountHashFromPublicKey } from '../../../utils'; import { CsprTransferDeployDto, processDeploy, Cep18TransferDeployDto } from '../../dto'; -import { ExtendedCloudDeploy, ICsprTransferResponse, IErc20TokensTransferResponse } from './types'; +import { + ExtendedCloudDeploy, + ICloudTransactionFeedItem, + ICsprTransferResponse, + IErc20TokensTransferResponse, +} from './types'; import { getAccountHashesFromDeploy, getAccountHashesFromDeployActionResults, @@ -233,6 +238,59 @@ export class DeploysRepository implements IDeploysRepository { } } + async getTransactionsFeed({ + network, + activePublicKey, + page, + limit = DEFAULT_PAGE_LIMIT, + contractPackageHash, + withProxyHeader = true, + }: IGetDeploysParams) { + try { + const resp = await this._httpProvider.get>({ + url: `https://cspr-wallet-api.dev.make.services:443/accounts/${activePublicKey}/feed-transactions`, // TODO: Replace with production API endpoint + params: { + account_identifier: activePublicKey, + page, + page_size: limit, + includes: + 'rate(1),contract_entrypoint,contract_package,transfers,centralized_account_info,account_info,cspr_name,nft_token_actions,ft_token_actions,token_market_data(1)', + ...(contractPackageHash ? { contract_package_hash: contractPackageHash } : {}), + }, + ...(withProxyHeader ? { headers: CSPR_API_PROXY_HEADERS } : {}), + errorType: 'getTransactionsFeed', + }); + + if (!resp) { + return EMPTY_PAGINATED_RESPONSE; + } + + const rawDeploys = resp.data.map(d => processDeploy(activePublicKey, network, {}, d)); + const accountHashes = rawDeploys.map(d => getAccountHashesFromDeploy(d)).flat(); + + await this._accountInfoRepository.getAccountsInfo({ + network, + accountHashes, + }); + + return { + itemCount: resp.item_count, + pageCount: resp.page_count, + pages: resp.pages, + data: resp.data.map(d => + processDeploy( + activePublicKey, + network, + this._accountInfoRepository.accountsInfoMapCache, + d, + ), + ), + }; + } catch (e) { + this._processError(e, 'getTransactionsFeed'); + } + } + private _processError(e: unknown, type: keyof IDeploysRepository): never { if (isDeploysError(e)) { throw e; diff --git a/src/data/repositories/deploys/types.ts b/src/data/repositories/deploys/types.ts index 2d6178d..0b94144 100644 --- a/src/data/repositories/deploys/types.ts +++ b/src/data/repositories/deploys/types.ts @@ -403,3 +403,36 @@ export interface ExtendedDeployContractPackageMetadata { whitelist_mode?: string; owner_reverse_lookup_mode?: string; } + +export interface ICloudTransactionFeedItem { + account_info: null; + args: ExtendedDeployArgsResult; + block_hash: string; + block_height: number; + caller_hash: string; + caller_public_key: string; + centralized_account_info: null; + consumed_gas: string; + contract_entrypoint: ExtendedDeployEntryPointResult; + contract_hash: string; + contract_package: ExtendedDeployContractPackageResult; + contract_package_hash: string; + cost: string; + deploy_hash: string; + entry_point_id: number; + error_message: null | string; + execution_type_id: number; + transfers?: DeployTransferResult[]; + ft_token_actions?: FTActionsResult[]; + nft_token_actions?: NftCloudActionsResult[]; + gas_price_limit: number; + is_standard_payment: boolean; + payment_amount: string; + pricing_mode_id: number; + rate: number; + refund_amount: string; + runtime_type_id: number; + status: string; + timestamp: string; + version_id: 2; +} diff --git a/src/domain/deploys/repository.ts b/src/domain/deploys/repository.ts index 49e51f0..f6f64f6 100644 --- a/src/domain/deploys/repository.ts +++ b/src/domain/deploys/repository.ts @@ -7,6 +7,7 @@ export interface IDeploysRepository { getDeploys(params: IGetDeploysParams): Promise>; getCsprTransferDeploys(params: IGetDeploysParams): Promise>; getCep18TransferDeploys(params: IGetDeploysParams): Promise>; + getTransactionsFeed(params: IGetDeploysParams): Promise>; } export interface IGetSingleDeployParams { From 1ccbfcb004f210353f20cba58f7e74f4c6de5a6d Mon Sep 17 00:00:00 2001 From: Dmytro Vynnyk Date: Thu, 5 Mar 2026 23:32:53 +0100 Subject: [PATCH 16/17] Refactor market data handling by replacing `coingecko_data` and `friendlymarket_data` with `token_market_data` for streamlined fiat calculations and provider determination. --- src/data/dto/common.ts | 17 ++++++++++ src/data/dto/deploys/Cep18DeployDto.ts | 34 ++++++++----------- .../dto/deploys/Cep18transferDeployDto.ts | 34 ++++++++----------- src/data/dto/tokens.ts | 31 ++++++++--------- .../repositories/contractPackage/types.ts | 14 ++++++-- src/data/repositories/deploys/types.ts | 12 +++---- src/data/repositories/tokens/index.ts | 4 +-- src/data/repositories/tokens/types.ts | 9 ++--- src/domain/constants/casperNetwork.ts | 27 +++++++++++++++ src/domain/tokens/entities.ts | 2 +- 10 files changed, 107 insertions(+), 77 deletions(-) diff --git a/src/data/dto/common.ts b/src/data/dto/common.ts index dc9094b..557efc9 100644 --- a/src/data/dto/common.ts +++ b/src/data/dto/common.ts @@ -15,6 +15,7 @@ import { SupportedMarketDataProviders, } from '../../domain'; import { Maybe } from '../../typings'; +import { ITokenMarketData } from '../repositories'; export function getCsprFiatAmount(amount: string | number, rate?: string | number) { const isZeroRate = Number(rate ?? 0) === 0; @@ -95,6 +96,8 @@ export function getMarketDataProviderUrl( latestVersionContractHash?: string | null, ) { switch (marketDataProvider) { + case 'CsprTrade': + return 'https://cspr.trade/'; // TODO link to token page case 'CoinGecko': return coingeckoId ? `https://www.coingecko.com/en/coins/${coingeckoId}` : null; case 'FriendlyMarket': @@ -122,3 +125,17 @@ export function isNftAction(entryPointName: string, contractTypeId?: Maybe a.dex_id - b.dex_id)?.[0]; +} + +export const dexIdToMarketDataProviderMap: Record = { + 1: 'CsprTrade', + 2: 'CoinGecko', + 3: 'FriendlyMarket', +}; diff --git a/src/data/dto/deploys/Cep18DeployDto.ts b/src/data/dto/deploys/Cep18DeployDto.ts index beea4ce..71619d1 100644 --- a/src/data/dto/deploys/Cep18DeployDto.ts +++ b/src/data/dto/deploys/Cep18DeployDto.ts @@ -23,7 +23,12 @@ import { SupportedMarketDataProviders, } from '../../../domain'; import { Maybe } from '../../../typings'; -import { getAccountInfoFromMap, getMarketDataProviderUrl } from '../common'; +import { + dexIdToMarketDataProviderMap, + getAccountInfoFromMap, + getMarketDataProviderUrl, + getPreferredTokenMarketData, +} from '../common'; export class Cep18DeployDto extends DeployDto implements ICep18Deploy { constructor( @@ -51,26 +56,15 @@ export class Cep18DeployDto extends DeployDto implements ICep18Deploy { this.recipientKeyType = this.recipientAccountInfo?.publicKey ? 'publicKey' : recipientKeyType; this.isReceive = isKeysEqual(activePublicKey, this.recipientKey); - this.fiatAmount = getCep18FiatAmount( - this.decimalAmount, - data?.contract_package?.coingecko_data?.price ?? - data?.contract_package?.friendlymarket_data?.price ?? - 0, - false, - ); - this.formattedFiatAmount = getCep18FiatAmount( - this.decimalAmount, - data?.contract_package?.coingecko_data?.price ?? - data?.contract_package?.friendlymarket_data?.price ?? - 0, - true, - ); + const tokenMarketData = getPreferredTokenMarketData(data?.contract_package?.token_market_data); + const fiatRate = tokenMarketData?.latest_rate ?? 0; + + this.fiatAmount = getCep18FiatAmount(this.decimalAmount, fiatRate, false); + this.formattedFiatAmount = getCep18FiatAmount(this.decimalAmount, fiatRate, true); this.fiatCurrency = 'USD'; - this.marketDataProvider = data?.contract_package?.coingecko_data?.price - ? 'CoinGecko' - : data?.contract_package?.friendlymarket_data?.price - ? 'FriendlyMarket' - : null; + this.marketDataProvider = tokenMarketData + ? dexIdToMarketDataProviderMap[tokenMarketData.dex_id] + : null; this.marketDataProviderUrl = getMarketDataProviderUrl( this.marketDataProvider, data?.contract_package?.coingecko_id, diff --git a/src/data/dto/deploys/Cep18transferDeployDto.ts b/src/data/dto/deploys/Cep18transferDeployDto.ts index 9ce61b5..1fc03ce 100644 --- a/src/data/dto/deploys/Cep18transferDeployDto.ts +++ b/src/data/dto/deploys/Cep18transferDeployDto.ts @@ -20,7 +20,12 @@ import { SupportedMarketDataProviders, } from '../../../domain'; -import { getAccountInfoFromMap, getMarketDataProviderUrl } from '../common'; +import { + dexIdToMarketDataProviderMap, + getAccountInfoFromMap, + getMarketDataProviderUrl, + getPreferredTokenMarketData, +} from '../common'; import { getCsprFiatAmount } from '../common'; import { Maybe } from '../../../typings'; import { IErc20TokensTransferResponse } from '../../repositories'; @@ -78,26 +83,15 @@ export class Cep18TransferDeployDto implements ICep18Deploy { this.fiatPaymentAmount = getCsprFiatAmount(this.paymentAmount, data?.deploy?.rate); this.nftActionsResult = []; - this.fiatAmount = getCep18FiatAmount( - this.decimalAmount, - data?.contract_package?.coingecko_data?.price ?? - data?.contract_package?.friendlymarket_data?.price ?? - 0, - false, - ); - this.formattedFiatAmount = getCep18FiatAmount( - this.decimalAmount, - data?.contract_package?.coingecko_data?.price ?? - data?.contract_package?.friendlymarket_data?.price ?? - 0, - true, - ); + const tokenMarketData = getPreferredTokenMarketData(data?.contract_package?.token_market_data); + const fiatRate = tokenMarketData?.latest_rate ?? 0; + + this.fiatAmount = getCep18FiatAmount(this.decimalAmount, fiatRate, false); + this.formattedFiatAmount = getCep18FiatAmount(this.decimalAmount, fiatRate, true); this.fiatCurrency = 'USD'; - this.marketDataProvider = data?.contract_package?.coingecko_data?.price - ? 'CoinGecko' - : data?.contract_package?.friendlymarket_data?.price - ? 'FriendlyMarket' - : null; + this.marketDataProvider = tokenMarketData + ? dexIdToMarketDataProviderMap[tokenMarketData.dex_id] + : null; this.marketDataProviderUrl = getMarketDataProviderUrl( this.marketDataProvider, data?.contract_package?.coingecko_id, diff --git a/src/data/dto/tokens.ts b/src/data/dto/tokens.ts index 3f48b13..380bd58 100644 --- a/src/data/dto/tokens.ts +++ b/src/data/dto/tokens.ts @@ -12,7 +12,11 @@ import { } from '../../domain'; import { ApiToken, IGetCsprBalanceResponse, IGetCurrencyRateResponse } from '../repositories'; import { Maybe } from '../../typings'; -import { getMarketDataProviderUrl } from './common'; +import { + dexIdToMarketDataProviderMap, + getMarketDataProviderUrl, + getPreferredTokenMarketData, +} from './common'; export class TokenDto implements ITokenWithFiatBalance { constructor(network: Network, apiToken?: Partial) { @@ -28,23 +32,16 @@ export class TokenDto implements ITokenWithFiatBalance { this.decimalBalance = getDecimalTokenBalance(this.balance, this.decimals); this.formattedDecimalBalance = formatTokenBalance(this.balance, this.decimals); this.isNative = this.symbol === 'CSPR'; - this.fiatBalance = getCep18FiatAmount( - this.decimalBalance, - apiToken?.coingecko_data?.price ?? apiToken?.friendlymarket_data?.price ?? 0, - false, - ); - this.formattedFiatBalance = getCep18FiatAmount( - this.decimalBalance, - apiToken?.coingecko_data?.price ?? apiToken?.friendlymarket_data?.price ?? 0, - true, - ); - this.fiatPrice = apiToken?.coingecko_data?.price ?? apiToken?.friendlymarket_data?.price ?? 0; + + const tokenMarketData = getPreferredTokenMarketData(apiToken?.token_market_data); + + this.fiatPrice = tokenMarketData?.latest_rate ?? 0; + this.fiatBalance = getCep18FiatAmount(this.decimalBalance, this.fiatPrice, false); + this.formattedFiatBalance = getCep18FiatAmount(this.decimalBalance, this.fiatPrice, true); this.currency = 'USD'; - this.marketDataProvider = apiToken?.coingecko_data?.price - ? 'CoinGecko' - : apiToken?.friendlymarket_data?.price - ? 'FriendlyMarket' - : null; + this.marketDataProvider = tokenMarketData + ? dexIdToMarketDataProviderMap[tokenMarketData.dex_id] + : null; this.marketDataProviderUrl = getMarketDataProviderUrl( this.marketDataProvider, apiToken?.coingecko_id, diff --git a/src/data/repositories/contractPackage/types.ts b/src/data/repositories/contractPackage/types.ts index 1ae1e3d..9df83b0 100644 --- a/src/data/repositories/contractPackage/types.ts +++ b/src/data/repositories/contractPackage/types.ts @@ -1,5 +1,4 @@ import { Maybe } from '../../../typings'; -import { CoingeckoApiData, FriendlymarketApiData } from '../tokens'; export interface IContractPackageCloudResponse { contract_package_hash: string; @@ -29,6 +28,15 @@ export interface IContractPackageCloudResponse { icon_url: Maybe; website_url: Maybe; deploys_number: number; - coingecko_data?: Maybe; - friendlymarket_data?: Maybe; + token_market_data?: ITokenMarketData[] | null; +} + +export interface ITokenMarketData { + dex_id: number; + token_contract_package_hash: string; + currency_id: number; + latest_rate: number; + volume_24h: string; + token_volume_24h: string; + timestamp: string; } diff --git a/src/data/repositories/deploys/types.ts b/src/data/repositories/deploys/types.ts index 0b94144..37a1200 100644 --- a/src/data/repositories/deploys/types.ts +++ b/src/data/repositories/deploys/types.ts @@ -1,5 +1,6 @@ import { Maybe } from '../../../typings'; -import { CoingeckoApiData, ContractPackage, FriendlymarketApiData } from '../tokens'; +import { ContractPackage } from '../tokens'; +import { ITokenMarketData } from '../contractPackage'; export enum TransactorHashType { 'account' = 0, @@ -147,8 +148,7 @@ export interface ExtendedCloudDeploy { transfers?: DeployTransferResult[]; ft_token_actions?: FTActionsResult[]; nft_token_actions?: NftCloudActionsResult[]; - coingecko_data?: Maybe; - friendlymarket_data?: Maybe; + token_market_data?: ITokenMarketData[] | null; } export enum CasperMarketEntryPoint { @@ -291,8 +291,6 @@ export interface IErc20TokensTransferResponse { transform_idx: number; deploy?: ExtendedCloudDeploy; contract_package?: ContractPackage; - coingecko_data?: Maybe; - friendlymarket_data?: Maybe; } export interface IApiDeployArgs { @@ -374,9 +372,9 @@ export interface ExtendedDeployContractPackageResult { coingecko_id?: string | null; friendlymarket_id?: string | null; - coingecko_data?: Maybe; - friendlymarket_data?: Maybe; latest_version_contract_hash?: string | null; + + token_market_data?: ITokenMarketData[] | null; } export interface ExtendedDeployEntryPointResult { diff --git a/src/data/repositories/tokens/index.ts b/src/data/repositories/tokens/index.ts index 0cf48a7..a6dfffc 100644 --- a/src/data/repositories/tokens/index.ts +++ b/src/data/repositories/tokens/index.ts @@ -35,10 +35,10 @@ export class TokensRepository implements ITokensRepository { const accountHash = getAccountHashFromPublicKey(publicKey); const tokensList = await this._httpProvider.get>({ - url: `${this._casperWalletApiUrl[network]}/accounts/${accountHash}/ft-token-ownership`, + url: `https://cspr-wallet-api.dev.make.services:443/accounts/${accountHash}/ft-token-ownership`, // TODO replace with prod API params: { page_size: 100, // TODO pagination? - includes: 'contract_package,friendlymarket_data(1),coingecko_data(1)', + includes: 'contract_package,token_market_data(1)', }, ...(withProxyHeader ? { headers: CSPR_API_PROXY_HEADERS } : {}), errorType: 'getTokens', diff --git a/src/data/repositories/tokens/types.ts b/src/data/repositories/tokens/types.ts index 4848356..c8bde81 100644 --- a/src/data/repositories/tokens/types.ts +++ b/src/data/repositories/tokens/types.ts @@ -1,5 +1,5 @@ import { DataResponse, Network } from '../../../domain'; -import { Maybe } from '../../../typings'; +import { ITokenMarketData } from '../contractPackage'; export interface IGetCsprBalanceResponse { balance: string; @@ -22,8 +22,6 @@ export interface Erc20Token { contract_package_hash: string; owner_hash: string; owner_type: number; - coingecko_data?: Maybe; - friendlymarket_data?: Maybe; contract_package: ContractPackage; } @@ -56,15 +54,12 @@ export interface ContractPackage { contractHash?: string; coingecko_id?: string | null; friendlymarket_id?: string | null; - coingecko_data?: Maybe; - friendlymarket_data?: Maybe; latest_version_contract_hash?: string | null; + token_market_data?: ITokenMarketData[] | null; } export interface ApiToken extends ContractPackage { balance: string; network: Network; contractHash?: string; - coingecko_data?: Maybe; - friendlymarket_data?: Maybe; } diff --git a/src/domain/constants/casperNetwork.ts b/src/domain/constants/casperNetwork.ts index 854547a..594ee24 100644 --- a/src/domain/constants/casperNetwork.ts +++ b/src/domain/constants/casperNetwork.ts @@ -159,6 +159,33 @@ export const AuctionManagerContractInfo: Record = }, }; +export const SystemMintContractInfo: Record = { + mainnet: { + contractHash: '', + contactName: '', + contractPackageHash: '4475016098705466254edd18d267a9dad43e341d4dafadb507d0fe3cf2d4a74b', + contractPackageName: 'Mint', + }, + testnet: { + contractHash: '', + contactName: '', + contractPackageHash: '9824d60dc3a5c44a20b9fd260a412437933835b52fc683d8ae36e4ec2114843e', + contractPackageName: 'Mint', + }, + devnet: { + contractHash: '', + contactName: '', + contractPackageHash: '', + contractPackageName: '', + }, + integration: { + contractHash: '', + contactName: '', + contractPackageHash: '', + contractPackageName: '', + }, +}; + export const CSPRMarketContractInfo: Record = { mainnet: { contractHash: '5adb720d529964437caf75f3df974edffd204fe511b9e359e7dff28f79d12337', diff --git a/src/domain/tokens/entities.ts b/src/domain/tokens/entities.ts index df951f7..2a5a36a 100644 --- a/src/domain/tokens/entities.ts +++ b/src/domain/tokens/entities.ts @@ -28,7 +28,7 @@ export interface ITokenWithFiatBalance extends IToken { readonly marketDataProviderUrl: Maybe; } -export type SupportedMarketDataProviders = 'CoinGecko' | 'FriendlyMarket'; +export type SupportedMarketDataProviders = 'CsprTrade' | 'CoinGecko' | 'FriendlyMarket'; export interface ICsprBalance { readonly publicKey: string; From 41bcc3f07ccad29c20140121b8ae9d6113235d5f Mon Sep 17 00:00:00 2001 From: Dmytro Vynnyk Date: Thu, 5 Mar 2026 23:33:50 +0100 Subject: [PATCH 17/17] Bump version to 1.2.0 in package.json. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6ae1dd4..f9bf4ce 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "CasperWalletCore", - "version": "1.1.5", + "version": "1.2.0", "main": "index.ts", "repository": { "type": "git",