Skip to content

Commit

Permalink
feat: handle indexer errors
Browse files Browse the repository at this point in the history
  • Loading branch information
iGroza committed Mar 19, 2024
1 parent 0799b6c commit bce2e23
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 70 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"@haqq/provider-mnemonic-react-native": "0.0.14",
"@haqq/provider-sss-react-native": "0.0.14",
"@haqq/provider-web3-utils": "0.0.14",
"@haqq/shared-react-native": "0.0.9",
"@haqq/shared-react-native": "0.0.11",
"@invertase/react-native-apple-authentication": "2.2.2",
"@keystonehq/bc-ur-registry-eth": "0.7.7",
"@keystonehq/ur-decoder": "0.12.2",
Expand Down
5 changes: 4 additions & 1 deletion src/helpers/whitelist.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {jsonrpcRequest} from '@haqq/shared-react-native';
import {JSONRPCError, jsonrpcRequest} from '@haqq/shared-react-native';

import {app} from '@app/contexts';
import {DEBUG_VARS} from '@app/debug-vars';
Expand Down Expand Up @@ -149,6 +149,9 @@ export class Whitelist {

return response;
} catch (err) {
if (err instanceof JSONRPCError) {
Logger.captureException(err, 'Whitelist:verifyAddress', err.meta);
}
logger.error('verifyAddress', err);

if (responseFromCache) {
Expand Down
178 changes: 115 additions & 63 deletions src/services/indexer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {jsonrpcRequest} from '@haqq/shared-react-native';
import {JSONRPCError, jsonrpcRequest} from '@haqq/shared-react-native';
import _ from 'lodash';

import {app} from '@app/contexts';
import {AddressUtils} from '@app/helpers/address-utils';
Expand All @@ -16,6 +17,8 @@ import {
RatesResponse,
} from '@app/types';

import {RemoteConfig} from './remote-config';

export type IndexerUpdatesResponse = {
addresses: IContract[];
balance: IndexerBalance;
Expand All @@ -35,6 +38,8 @@ export type IndexerUpdatesResponse = {
rates: RatesResponse;
};

const logger = Logger.create('IndexerService');

export class Indexer {
static instance = new Indexer();

Expand All @@ -45,24 +50,48 @@ export class Indexer {
'content-type': 'application/json;charset=UTF-8',
};

captureException = logger.captureException;

constructor() {
this.init();
}

async init() {
await RemoteConfig.awaitForInitialization();
this.captureException = _.throttle(
logger.captureException,
RemoteConfig.safeGet('indexer_sentry_capture_exeption_throttle_ms'),
{
leading: true,
},
);
}

async updates(
accounts: string[],
lastUpdated: Date | undefined,
selectedCurrency?: string,
): Promise<IndexerUpdatesResponse> {
if (!app.provider.indexer) {
throw new Error('Indexer is not configured');
try {
if (!app.provider.indexer) {
throw new Error('Indexer is not configured');
}

const updated = lastUpdated || new Date(0);

const result: IndexerUpdatesResponse = await jsonrpcRequest(
app.provider.indexer,
'updates',
[accounts, updated, selectedCurrency].filter(Boolean),
);

return result;
} catch (err) {
if (err instanceof JSONRPCError) {
this.captureException(err, 'Indexer:updates', err.meta);
}
throw err;
}

const updated = lastUpdated || new Date(0);

const result: IndexerUpdatesResponse = await jsonrpcRequest(
app.provider.indexer,
'updates',
[accounts, updated, selectedCurrency].filter(Boolean),
);

return result;
}

async getContractName(address: string): Promise<string> {
Expand All @@ -71,68 +100,91 @@ export class Indexer {
}

async getContractNames(addresses: string[]): Promise<ContractNameMap> {
if (!app.provider.indexer) {
throw new Error('Indexer is not configured');
try {
if (!app.provider.indexer) {
throw new Error('Indexer is not configured');
}

if (addresses.length === 0) {
return Promise.reject('Empty addresses');
}

const response = await jsonrpcRequest<
{name: string; id: string; symbol: string}[]
>(app.provider.indexer, 'addresses', [
addresses.map(AddressUtils.toHaqq),
]);

const map = addresses.reduce((acc, item) => {
const responseExist = Array.isArray(response) && response.length > 0;
const newValue = responseExist
? response.find(infoItem => infoItem.id === AddressUtils.toHaqq(item))
: null;

acc[item] = {
name: newValue?.name ?? getText(I18N.transactionContractDefaultName),
symbol: newValue?.symbol || '',
};
return acc;
}, {} as ContractNameMap);

return map;
} catch (err) {
if (err instanceof JSONRPCError) {
this.captureException(err, 'Indexer:getContractNames', err.meta);
}
throw err;
}

if (addresses.length === 0) {
return Promise.reject('Empty addresses');
}

const response = await jsonrpcRequest<
{name: string; id: string; symbol: string}[]
>(app.provider.indexer, 'addresses', [addresses.map(AddressUtils.toHaqq)]);

const map = addresses.reduce((acc, item) => {
const responseExist = Array.isArray(response) && response.length > 0;
const newValue = responseExist
? response.find(infoItem => infoItem.id === AddressUtils.toHaqq(item))
: null;

acc[item] = {
name: newValue?.name ?? getText(I18N.transactionContractDefaultName),
symbol: newValue?.symbol || '',
};
return acc;
}, {} as ContractNameMap);

return map;
}

async getBalances(accounts: string[]): Promise<Record<string, string>> {
if (!app.provider.indexer) {
throw new Error('Indexer is not configured');
try {
if (!app.provider.indexer) {
throw new Error('Indexer is not configured');
}

const response = await jsonrpcRequest<IndexerUpdatesResponse>(
app.provider.indexer,
'balances',
[accounts],
);
return response.balance || {};
} catch (err) {
if (err instanceof JSONRPCError) {
this.captureException(err, 'Indexer:getBalances', err.meta);
}
throw err;
}

const response = await jsonrpcRequest<IndexerUpdatesResponse>(
app.provider.indexer,
'balances',
[accounts],
);
return response.balance || {};
}

async getTransactions(
accounts: string[],
latestBlock: string = 'latest',
providerId = app.providerId,
): Promise<IndexerTransaction[]> {
const provider = Provider.getById(providerId);

if (!provider?.indexer) {
throw new Error('Indexer is not configured');
}

if (!accounts.length) {
return [];
try {
const provider = Provider.getById(providerId);

if (!provider?.indexer) {
throw new Error('Indexer is not configured');
}

if (!accounts.length) {
return [];
}

const haqqAddresses = accounts.filter(a => !!a).map(AddressUtils.toHaqq);
const response = await jsonrpcRequest<IndexerTransactionResponse>(
provider.indexer,
'transactions',
[haqqAddresses, latestBlock],
);
return response?.txs || {};
} catch (err) {
if (err instanceof JSONRPCError) {
this.captureException(err, 'Indexer:getTransactions', err.meta);
}
throw err;
}

const haqqAddresses = accounts.filter(a => !!a).map(AddressUtils.toHaqq);
const response = await jsonrpcRequest<IndexerTransactionResponse>(
provider.indexer,
'transactions',
[haqqAddresses, latestBlock],
);
return response?.txs || {};
}
}
1 change: 1 addition & 0 deletions src/services/remote-config/remote-config-default-values.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,4 +149,5 @@ export const REMOTE_CONFIG_DEFAULT_VALUES: Required<RemoteConfigTypes> = {
},
tx_timestamp_headers: true,
enable_eth_commission_multiplier: false,
indexer_sentry_capture_exeption_throttle_ms: 2 * 60 * 1000, // 2 min,
};
1 change: 1 addition & 0 deletions src/services/remote-config/remote-config-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,5 @@ export type RemoteConfigTypes = RemoteConfigBalanceTypes &
web3_browser_bookmarks: Omit<Link, 'subtitle' | 'id'>[];
welcome_screen: keyof RootStackParamList;
tx_timestamp_headers: boolean;
indexer_sentry_capture_exeption_throttle_ms: number;
};
10 changes: 5 additions & 5 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2466,9 +2466,9 @@ __metadata:
languageName: node
linkType: hard

"@haqq/shared-react-native@npm:0.0.9":
version: 0.0.9
resolution: "@haqq/shared-react-native@npm:0.0.9"
"@haqq/shared-react-native@npm:0.0.11":
version: 0.0.11
resolution: "@haqq/shared-react-native@npm:0.0.11"
dependencies:
base-64: ^1.0.0
bn.js: 5.2.1
Expand All @@ -2479,7 +2479,7 @@ __metadata:
"@haqq/provider-web3-utils": 0.0.10
react: "*"
react-native: "*"
checksum: 9a2d52ce97a9291a30cb11324cc68c9af427a04ddf1def9c018ff6c94a28694d9aa07c8c1d2296dcfdc2df85fb187c70391759d0340466ed534ba5824c8d9014
checksum: 636c7c7b684fb369cfc718c9f15b38dcfa9665d1539913005c5edfaa3e4681fc0193d3efba7ce2ed0a4219eea035c2cc33771d0ab68bfb99f22348f4046c48a5
languageName: node
linkType: hard

Expand Down Expand Up @@ -10205,7 +10205,7 @@ __metadata:
"@haqq/provider-mnemonic-react-native": 0.0.14
"@haqq/provider-sss-react-native": 0.0.14
"@haqq/provider-web3-utils": 0.0.14
"@haqq/shared-react-native": 0.0.9
"@haqq/shared-react-native": 0.0.11
"@invertase/react-native-apple-authentication": 2.2.2
"@keystonehq/bc-ur-registry-eth": 0.7.7
"@keystonehq/ur-decoder": 0.12.2
Expand Down

0 comments on commit bce2e23

Please sign in to comment.