Skip to content

Commit

Permalink
fix(blockchain-link): cache SOL token metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
marekrjpolak committed Apr 22, 2024
1 parent 172fa22 commit 3850101
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 21 deletions.
6 changes: 3 additions & 3 deletions packages/blockchain-link-utils/src/solana.ts
Original file line number Diff line number Diff line change
Expand Up @@ -544,12 +544,12 @@ export const getTokens = (
return effects;
};

export const transformTransaction = async (
export const transformTransaction = (
tx: SolanaValidParsedTxWithMeta,
accountAddress: string,
tokenAccountsInfos: SolanaTokenAccountInfo[],
): Promise<Transaction> => {
const tokenDetailByMint = await getTokenMetadata();
tokenDetailByMint: TokenDetailByMint = {},
): Transaction => {
const nativeEffects = getNativeEffects(tx);

const tokens = getTokens(tx, accountAddress, tokenDetailByMint, tokenAccountsInfos);
Expand Down
4 changes: 2 additions & 2 deletions packages/blockchain-link-utils/src/tests/solana.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@ describe('solana/utils', () => {

describe('transformTransaction', () => {
fixtures.transformTransaction.forEach(({ description, input, expectedOutput }) => {
it(description, async () => {
const result = await transformTransaction(
it(description, () => {
const result = transformTransaction(
input.transaction as SolanaValidParsedTxWithMeta,
input.accountAddress,
input.tokenAccountsInfos,
Expand Down
57 changes: 41 additions & 16 deletions packages/blockchain-link/src/workers/solana/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import type {
SolanaValidParsedTxWithMeta,
ParsedTransactionWithMeta,
SolanaTokenAccountInfo,
TokenDetailByMint,
} from '@trezor/blockchain-link-types/src/solana';
import type * as MessageTypes from '@trezor/blockchain-link-types/src/messages';
import { CustomError } from '@trezor/blockchain-link-types/src/constants/errors';
Expand All @@ -27,7 +28,9 @@ import { confirmTransactionWithResubmit } from './transactionConfirmation';

export type SolanaAPI = Connection;

type Context = ContextType<SolanaAPI>;
type Context = ContextType<SolanaAPI> & {
getTokenMetadata: () => Promise<TokenDetailByMint>;
};
type Request<T> = T & Context;

type SignatureWithSlot = {
Expand Down Expand Up @@ -128,19 +131,19 @@ const getAccountInfo = async (request: Request<MessageTypes.GetAccountInfo>) =>
) => {
const transactionsPage = await fetchTransactionPage(api, txIds);

return (
await Promise.all(
transactionsPage
.filter(isValidTransaction)
.map(tx =>
solanaUtils.transformTransaction(
tx,
payload.descriptor,
tokenAccountsInfos,
),
),
const tokenMetadata = await request.getTokenMetadata();

return transactionsPage
.filter(isValidTransaction)
.map(tx =>
solanaUtils.transformTransaction(
tx,
payload.descriptor,
tokenAccountsInfos,
tokenMetadata,
),
)
).filter((tx): tx is Transaction => !!tx);
.filter((tx): tx is Transaction => !!tx);
};

const tokenAccounts = await api.getParsedTokenAccountsByOwner(publicKey, {
Expand Down Expand Up @@ -179,7 +182,7 @@ const getAccountInfo = async (request: Request<MessageTypes.GetAccountInfo>) =>
// Fetch token info only if the account owns tokens
let tokens: TokenInfo[] = [];
if (tokenAccounts.value.length > 0) {
const tokenMetadata = await solanaUtils.getTokenMetadata();
const tokenMetadata = await request.getTokenMetadata();

tokens = transformTokenInfo(tokenAccounts.value, tokenMetadata);
}
Expand Down Expand Up @@ -349,7 +352,7 @@ const findTokenAccountOwner = (
);

const subscribeAccounts = async (
{ connect, state, post }: Context,
{ connect, state, post, getTokenMetadata }: Context,
accounts: SubscriptionAccountInfo[],
) => {
const api = await connect();
Expand Down Expand Up @@ -385,7 +388,8 @@ const subscribeAccounts = async (
return;
}

const tx = await solanaUtils.transformTransaction(lastTx, a.descriptor, []);
const tokenMetadata = await getTokenMetadata();
const tx = solanaUtils.transformTransaction(lastTx, a.descriptor, [], tokenMetadata);

// For token accounts we need to emit an event with the owner account's descriptor
// since we don't store token accounts in the user's accounts.
Expand Down Expand Up @@ -502,6 +506,26 @@ class SolanaWorker extends BaseWorker<SolanaAPI> {
return !!api;
}

private tokenPromise?: Promise<TokenDetailByMint>;

getTokenMetadata(): Promise<TokenDetailByMint> {
if (!this.tokenPromise)
this.tokenPromise = solanaUtils
.getTokenMetadata()
.then(tokens => {
this.tokenPromise = Promise.resolve(tokens);

return tokens;
})
.catch(err => {
this.tokenPromise = undefined;

return Promise.reject(err);
});

return this.tokenPromise;
}

tryConnect(url: string): Promise<SolanaAPI> {
const api = new Connection(url, { wsEndpoint: url.replace('https', 'wss') });
this.post({ id: -1, type: RESPONSES.CONNECTED });
Expand All @@ -519,6 +543,7 @@ class SolanaWorker extends BaseWorker<SolanaAPI> {
connect: () => this.connect(),
post: (data: Response) => this.post(data),
state: this.state,
getTokenMetadata: this.getTokenMetadata.bind(this),
};

const response = await onRequest(request);
Expand Down

0 comments on commit 3850101

Please sign in to comment.