* feat: unhardcode contract addresses * fix: linting and tests * feat: switch contract usage in token app to use unhardcoded addresses * chore: remove other usage of hard coded contract addresses * feat: convert contracts to classes, update claim contract to fix circular dependency * feat: add hard coded contract addresses to contracts page * fix: misc tidy up * chore: rename ethers big num conversion func * fix: remove pending transactions modal * chore: add single toBigNum function that can accept number string or EthersBignNumber * chore: delete unused tranche helpers and decimals functions from smart contracts lib * feat: add faucetable token class * fix: reset tx state after early exit from approve tx * feat: re add transaction modal using zustand store * fix: loader colors for eth wallet * fix: pass ethereum config to gurantee existence before tx execution * add docker image for building explorer * add arg * env file changes * add docker file to build env file * add requirement for env file in explorer * fix env file syntax * containers functional * default to testnet * make env flag logic consistent in all places * pre populate env file * ensure working for all projects * address PR comment * generalising env for token * invert config dependency from ui toolkit * fix: merge issues * docs: running containers documentation * style: lint * fix: env varibales not being added properly * chore: fix merge issues * chore: fix docker file to support new exectutors * chore: set address on all contracts as a property * feat: pull token from contract rather than relying on env var * chore: fix typing * chore: remove duplicated prop * chore: don't use chainId * style: lint * style: lint * Merge branch 'master' into feat/dockerize-frontends * Merge remote-tracking branch 'origin/master' into feat/dockerize-frontends * test: revert changes to explorer e2e file * fix: creating client without base causing token to error * test: fix tests erroring in before hook due to file not being found * chore: remove node env from configurable flags Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
175 lines
4.9 KiB
TypeScript
175 lines
4.9 KiB
TypeScript
import type { FieldFunctionOptions, Reference } from '@apollo/client';
|
|
import { ApolloClient, from, HttpLink, InMemoryCache } from '@apollo/client';
|
|
import { onError } from '@apollo/client/link/error';
|
|
import { RetryLink } from '@apollo/client/link/retry';
|
|
import sortBy from 'lodash/sortBy';
|
|
import uniqBy from 'lodash/uniqBy';
|
|
|
|
import { BigNumber } from './bignumber';
|
|
import { addDecimal } from './decimals';
|
|
import { deterministicShuffle } from './deterministic-shuffle';
|
|
|
|
// Create seed in memory. Validator list order will remain the same
|
|
// until the page is refreshed.
|
|
const VALIDATOR_RANDOMISER_SEED = (
|
|
Math.floor(Math.random() * 1000) + 1
|
|
).toString();
|
|
|
|
export function createClient(base?: string) {
|
|
if (!base) {
|
|
throw new Error('Base must be passed into createClient!');
|
|
}
|
|
const formatUintToNumber = (amount: string, decimals = 18) =>
|
|
addDecimal(new BigNumber(amount), decimals).toString();
|
|
|
|
const createReadField = (fieldName: string) => ({
|
|
[`${fieldName}Formatted`]: {
|
|
read(_: string, options: FieldFunctionOptions) {
|
|
const amount = options.readField(fieldName) as string;
|
|
return amount ? formatUintToNumber(amount) : '0';
|
|
},
|
|
},
|
|
});
|
|
|
|
const cache = new InMemoryCache({
|
|
typePolicies: {
|
|
Query: {
|
|
fields: {
|
|
nodes: {
|
|
// Merge function to make the validator list random but remain consistent
|
|
// as the user navigates around the site. If the user refreshes the list
|
|
// will be randomised.
|
|
merge: (existing = [], incoming) => {
|
|
// uniqBy will take the first of any matches
|
|
const uniq = uniqBy([...incoming, ...existing], 'id');
|
|
// sort result so that the input is consistent
|
|
const sorted = sortBy(uniq, 'id');
|
|
// randomise based on seed string
|
|
const random = deterministicShuffle(
|
|
VALIDATOR_RANDOMISER_SEED,
|
|
sorted
|
|
);
|
|
return random;
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Account: {
|
|
keyFields: false,
|
|
fields: {
|
|
balanceFormatted: {
|
|
read(_: string, options: FieldFunctionOptions) {
|
|
const balance = options.readField('balance');
|
|
const asset = options.readField('asset');
|
|
const decimals = options.readField(
|
|
'decimals',
|
|
asset as Reference
|
|
);
|
|
if (typeof balance !== 'string') return '0';
|
|
if (typeof decimals !== 'number') return '0';
|
|
return balance && decimals
|
|
? formatUintToNumber(balance, decimals)
|
|
: '0';
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Delegation: {
|
|
keyFields: false,
|
|
// Only get full updates
|
|
merge(_, incoming) {
|
|
return incoming;
|
|
},
|
|
fields: {
|
|
...createReadField('amount'),
|
|
},
|
|
},
|
|
Reward: {
|
|
keyFields: false,
|
|
fields: {
|
|
...createReadField('amount'),
|
|
},
|
|
},
|
|
RewardPerAssetDetail: {
|
|
keyFields: false,
|
|
fields: {
|
|
...createReadField('totalAmount'),
|
|
},
|
|
},
|
|
Node: {
|
|
keyFields: false,
|
|
fields: {
|
|
...createReadField('pendingStake'),
|
|
...createReadField('stakedByOperator'),
|
|
...createReadField('stakedByDelegates'),
|
|
...createReadField('stakedTotal'),
|
|
},
|
|
},
|
|
NodeData: {
|
|
merge: (existing = {}, incoming) => {
|
|
return { ...existing, ...incoming };
|
|
},
|
|
fields: {
|
|
...createReadField('stakedTotal'),
|
|
},
|
|
},
|
|
Party: {
|
|
fields: {
|
|
stake: {
|
|
merge(existing, incoming) {
|
|
return {
|
|
...existing,
|
|
...incoming,
|
|
};
|
|
},
|
|
read(stake) {
|
|
if (stake) {
|
|
return {
|
|
...stake,
|
|
currentStakeAvailableFormatted: formatUintToNumber(
|
|
stake.currentStakeAvailable
|
|
),
|
|
};
|
|
}
|
|
return stake;
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Withdrawal: {
|
|
fields: {
|
|
pendingOnForeignChain: {
|
|
read: (isPending = false) => isPending,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
const retryLink = new RetryLink({
|
|
delay: {
|
|
initial: 300,
|
|
max: 10000,
|
|
jitter: true,
|
|
},
|
|
});
|
|
|
|
const httpLink = new HttpLink({
|
|
uri: base,
|
|
credentials: 'same-origin',
|
|
});
|
|
|
|
const errorLink = onError(({ graphQLErrors, networkError }) => {
|
|
// eslint-disable-next-line no-console
|
|
console.log(graphQLErrors);
|
|
// eslint-disable-next-line no-console
|
|
console.log(networkError);
|
|
});
|
|
|
|
return new ApolloClient({
|
|
connectToDevTools: process.env['NODE_ENV'] === 'development',
|
|
link: from([errorLink, retryLink, httpLink]),
|
|
cache,
|
|
});
|
|
}
|