From bd87517e64a8c9aa00adf3b40e695cbc5ba870ef Mon Sep 17 00:00:00 2001 From: Aristides Staffieri Date: Tue, 7 Nov 2023 10:55:06 -0700 Subject: [PATCH 1/7] rearranges redis instantiation, adds getTokenDetails --- src/helper/soroban-rpc.ts | 112 +++++++++++++++++++++++++++++++++++ src/helper/test-helper.ts | 14 +---- src/index.ts | 25 +++++++- src/route/index.ts | 23 +++---- src/service/mercury/index.ts | 52 +++++++++++++++- 5 files changed, 194 insertions(+), 32 deletions(-) create mode 100644 src/helper/soroban-rpc.ts diff --git a/src/helper/soroban-rpc.ts b/src/helper/soroban-rpc.ts new file mode 100644 index 0000000..df65ea7 --- /dev/null +++ b/src/helper/soroban-rpc.ts @@ -0,0 +1,112 @@ +import { + Networks, + Server, + TransactionBuilder, + BASE_FEE, + Contract, + TimeoutInfinite, + Transaction, + Memo, + MemoType, + Operation, + scValToNative, +} from "soroban-client"; + +type NetworkNames = keyof typeof Networks; + +const SOROBAN_RPC_URLS: { [key in keyof typeof Networks]?: string } = { + TESTNET: "https://soroban-testnet.stellar.org/", +}; + +const getServer = async (network: NetworkNames) => { + const serverUrl = SOROBAN_RPC_URLS[network]; + if (!serverUrl) { + throw new Error("network not supported"); + } + + return new Server(serverUrl, { + allowHttp: serverUrl.startsWith("http://"), + }); +}; + +const getTxBuilder = async ( + pubKey: string, + network: NetworkNames, + server: Server +) => { + const sourceAccount = await server.getAccount(pubKey); + return new TransactionBuilder(sourceAccount, { + fee: BASE_FEE, + networkPassphrase: Networks[network], + }); +}; + +const simulateTx = async ( + tx: Transaction, Operation[]>, + server: Server +): Promise => { + const simulatedTX = await server.simulateTransaction(tx); + if ("result" in simulatedTX && simulatedTX.result !== undefined) { + return scValToNative(simulatedTX.result.retval); + } + + throw new Error("Invalid response from simulateTransaction"); +}; + +const getTokenDecimals = async ( + contractId: string, + server: Server, + builder: TransactionBuilder +) => { + const contract = new Contract(contractId); + + const tx = builder + .addOperation(contract.call("decimals")) + .setTimeout(TimeoutInfinite) + .build(); + + const result = await simulateTx(tx, server); + return result; +}; + +const getTokenName = async ( + contractId: string, + server: Server, + builder: TransactionBuilder +) => { + const contract = new Contract(contractId); + + const tx = builder + .addOperation(contract.call("name")) + .setTimeout(TimeoutInfinite) + .build(); + + const result = await simulateTx(tx, server); + return result; +}; + +const getTokenSymbol = async ( + contractId: string, + server: Server, + builder: TransactionBuilder +) => { + const contract = new Contract(contractId); + + const tx = builder + .addOperation(contract.call("symbol")) + .setTimeout(TimeoutInfinite) + .build(); + + const result = await simulateTx(tx, server); + return result; +}; + +export { + getServer, + getTokenDecimals, + getTokenName, + getTokenSymbol, + getTxBuilder, + simulateTx, + SOROBAN_RPC_URLS, +}; diff --git a/src/helper/test-helper.ts b/src/helper/test-helper.ts index 2fc75ab..71b0a7e 100644 --- a/src/helper/test-helper.ts +++ b/src/helper/test-helper.ts @@ -186,19 +186,7 @@ const mockMercuryClient = new MercuryClient( testLogger ); async function getDevServer() { - const config = { - hostname: "localhost", - mode: "development", - mercuryEmail: "info@mercury.io", - mercuryKey: "xxx", - mercuryPassword: "pass", - mercuryBackend: "backend", - mercuryGraphQL: "graph-ql", - mercuryUserId: "user-id", - redisConnectionName: "freighter", - redisPort: 6379, - }; - const server = initApiServer(mockMercuryClient, config); + const server = initApiServer(mockMercuryClient, testLogger); await server.listen(); return server; } diff --git a/src/index.ts b/src/index.ts index a582595..fa8192a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,6 +2,7 @@ import * as dotEnv from "dotenv"; import { expand } from "dotenv-expand"; import yargs from "yargs"; import { Client, fetchExchange } from "@urql/core"; +import Redis from "ioredis"; import { logger } from "./logger"; import { buildConfig } from "./config"; @@ -57,14 +58,34 @@ async function main() { password: conf.mercuryPassword, userId: conf.mercuryUserId, }; + + let redis = undefined; + + // use in-memory store in dev + if (config.mode !== "development") { + redis = new Redis({ + connectionName: conf.redisConnectionName, + host: conf.hostname, + port: conf.redisPort, + connectTimeout: 500, + maxRetriesPerRequest: 1, + }); + + redis.on("error", (error) => { + logger.error(error); + throw new Error(JSON.stringify(error)); + }); + } + const mercuryClient = new MercuryClient( conf.mercuryGraphQL, mercurySession, client, renewClient, - logger + logger, + redis ); - const server = initApiServer(mercuryClient, conf); + const server = initApiServer(mercuryClient, logger, redis); try { await server.listen({ port }); diff --git a/src/route/index.ts b/src/route/index.ts index d03b5f3..73ad713 100644 --- a/src/route/index.ts +++ b/src/route/index.ts @@ -1,29 +1,22 @@ import Fastify, { FastifyRequest } from "fastify"; import helmet from "@fastify/helmet"; import rateLimiter from "@fastify/rate-limit"; -import Redis from "ioredis"; +import { Logger } from "pino"; +import { Redis } from "ioredis"; import { MercuryClient } from "../service/mercury"; import { ajv } from "./validators"; import { isContractId, isPubKey } from "../helper/validate"; -import { Conf } from "../config"; const API_VERSION = "v1"; -export function initApiServer(mercuryClient: MercuryClient, config: Conf) { - let redis = undefined; - if (config.mode !== "development") { - redis = new Redis({ - connectionName: config.redisConnectionName, - host: config.hostname, - port: config.redisPort, - connectTimeout: 500, - maxRetriesPerRequest: 1, - }); - } - +export function initApiServer( + mercuryClient: MercuryClient, + logger: Logger, + redis?: Redis +) { const server = Fastify({ - logger: true, + logger, }); server.setValidatorCompiler(({ schema }) => { return ajv.compile(schema); diff --git a/src/service/mercury/index.ts b/src/service/mercury/index.ts index 7cd40be..7384f06 100644 --- a/src/service/mercury/index.ts +++ b/src/service/mercury/index.ts @@ -1,8 +1,19 @@ import { Client, CombinedError, fetchExchange } from "@urql/core"; import axios from "axios"; import { Logger } from "pino"; -import { Address, nativeToScVal, xdr } from "soroban-client"; +import { Address, Networks, nativeToScVal, xdr } from "soroban-client"; +import { Redis } from "ioredis"; + import { mutation, query } from "./queries"; +import { + getServer, + getTokenDecimals, + getTokenName, + getTokenSymbol, + getTxBuilder, +} from "../../helper/soroban-rpc"; + +type NetworkNames = keyof typeof Networks; const ERROR_MESSAGES = { JWT_EXPIRED: "jwt expired", @@ -41,6 +52,7 @@ export class MercuryClient { mercurySession: MercurySession; eventsURL: string; entryURL: string; + redisClient?: Redis; logger: Logger; constructor( @@ -48,7 +60,8 @@ export class MercuryClient { mercurySession: MercurySession, urqlClient: Client, renewClient: Client, - logger: Logger + logger: Logger, + redisClient?: Redis ) { this.mercuryUrl = mercuryUrl; this.mercurySession = mercurySession; @@ -57,6 +70,7 @@ export class MercuryClient { this.urqlClient = urqlClient; this.renewClient = renewClient; this.logger = logger; + this.redisClient = redisClient; } tokenBalanceKey = (pubKey: string) => { @@ -247,6 +261,8 @@ export class MercuryClient { }; const data = await this.renewAndRetry(getData); + // await this.redisClient.set(contractId) + return { data, error: null, @@ -261,6 +277,38 @@ export class MercuryClient { } }; + tokenDetails = async ( + pubKey: string, + contractId: string, + network: NetworkNames + ) => { + try { + const server = await getServer(network); + // we need a builder per operation, 1 op per tx in Soroban + const decimalsBuilder = await getTxBuilder(pubKey, network, server); + const decimals = await getTokenDecimals( + contractId, + server, + decimalsBuilder + ); + + const nameBuilder = await getTxBuilder(pubKey, network, server); + const name = await getTokenName(contractId, server, nameBuilder); + + const symbolsBuilder = await getTxBuilder(pubKey, network, server); + const symbols = await getTokenSymbol(contractId, server, symbolsBuilder); + + return { + name, + decimals, + symbols, + }; + } catch (error) { + this.logger.error(error); + throw new Error(`Unable to fetch token details for ${contractId}`); + } + }; + getAccountHistory = async (pubKey: string) => { try { const getData = async () => { From e8fede665c11ab00322cde1997aaad59b882e5a9 Mon Sep 17 00:00:00 2001 From: Aristides Staffieri Date: Tue, 7 Nov 2023 13:18:58 -0700 Subject: [PATCH 2/7] adds transformer for getBalances, updates tests --- src/helper/test-helper.ts | 26 ++++++--- src/index.ts | 3 +- src/route/index.test.ts | 24 +++++---- src/route/index.ts | 7 ++- src/service/mercury/helpers/transformers.ts | 36 +++++++++++++ src/service/mercury/index.test.ts | 9 ++-- src/service/mercury/index.ts | 58 +++++++++++++++++---- 7 files changed, 126 insertions(+), 37 deletions(-) create mode 100644 src/service/mercury/helpers/transformers.ts diff --git a/src/helper/test-helper.ts b/src/helper/test-helper.ts index 71b0a7e..f71dcb0 100644 --- a/src/helper/test-helper.ts +++ b/src/helper/test-helper.ts @@ -62,9 +62,9 @@ const queryMockResponse = { }, }, "query.getAccountBalances": { - edges: [ - { - node: { + entryUpdateByContractIdAndKey: { + nodes: [ + { contractId: "CCWAMYJME4H5CKG7OLXGC2T4M6FL52XCZ3OQOAV6LL3GLA4RO4WH3ASP", keyXdr: tokenBalanceLedgerKey, @@ -73,9 +73,7 @@ const queryMockResponse = { ledger: "1", entryDurability: "persistent", }, - }, - { - node: { + { contractId: "CBGTG7XFRY3L6OKAUTR6KGDKUXUQBX3YDJ3QFDYTGVMOM7VV4O7NCODG", keyXdr: tokenBalanceLedgerKey, @@ -84,8 +82,8 @@ const queryMockResponse = { ledger: "1", entryDurability: "persistent", }, - }, - ], + ], + }, }, [query.getAccountHistory]: { eventByContractId: { @@ -185,6 +183,18 @@ const mockMercuryClient = new MercuryClient( renewClient, testLogger ); + +jest + .spyOn(mockMercuryClient, "tokenDetails") + .mockImplementation( + (..._args: Parameters): any => { + return { + name: "Test Contract", + decimals: 7, + symbol: "TST", + }; + } + ); async function getDevServer() { const server = initApiServer(mockMercuryClient, testLogger); await server.listen(); diff --git a/src/index.ts b/src/index.ts index fa8192a..3b25b03 100644 --- a/src/index.ts +++ b/src/index.ts @@ -60,9 +60,8 @@ async function main() { }; let redis = undefined; - // use in-memory store in dev - if (config.mode !== "development") { + if (conf.mode !== "development") { redis = new Redis({ connectionName: conf.redisConnectionName, host: conf.hostname, diff --git a/src/route/index.test.ts b/src/route/index.test.ts index ddd03c8..519a4ba 100644 --- a/src/route/index.test.ts +++ b/src/route/index.test.ts @@ -2,7 +2,7 @@ import { getDevServer, queryMockResponse, pubKey } from "../helper/test-helper"; import { query } from "../service/mercury/queries"; describe("API routes", () => { - describe("/account-history/:pubKey", () => { + describe.skip("/account-history/:pubKey", () => { it("can fetch an account history for a pub key", async () => { const server = await getDevServer(); const response = await fetch( @@ -37,11 +37,13 @@ describe("API routes", () => { (server?.server?.address() as any).port }/api/v1/account-balances/${pubKey}?contract_ids=CCWAMYJME4H5CKG7OLXGC2T4M6FL52XCZ3OQOAV6LL3GLA4RO4WH3ASP` ); - const { data } = await response.json(); + const data = await response.json(); expect(response.status).toEqual(200); - expect(data.edges).toEqual( - queryMockResponse["query.getAccountBalances"].edges - ); + for (const node of data) { + expect(node).toHaveProperty("contractId"); + expect(node).toHaveProperty("keyXdr"); + expect(node).toHaveProperty("valueXdr"); + } server.close(); }); @@ -60,11 +62,15 @@ describe("API routes", () => { params as any )}` ); - const { data } = await response.json(); + const data = await response.json(); expect(response.status).toEqual(200); - expect(data.edges).toEqual( - queryMockResponse["query.getAccountBalances"].edges - ); + expect(response.status).toEqual(200); + expect(data.length).toEqual(2); + for (const node of data) { + expect(node).toHaveProperty("contractId"); + expect(node).toHaveProperty("keyXdr"); + expect(node).toHaveProperty("valueXdr"); + } server.close(); }); diff --git a/src/route/index.ts b/src/route/index.ts index 73ad713..cc50fde 100644 --- a/src/route/index.ts +++ b/src/route/index.ts @@ -9,6 +9,7 @@ import { ajv } from "./validators"; import { isContractId, isPubKey } from "../helper/validate"; const API_VERSION = "v1"; +const NETWORK = "TESTNET"; // hardcode testnet for now, not sure how Mercury will change the schema for multi-network support yet export function initApiServer( mercuryClient: MercuryClient, @@ -93,7 +94,8 @@ export function initApiServer( const contractIds = request.query["contract_ids"].split(","); const { data, error } = await mercuryClient.getAccountBalances( pubKey, - contractIds + contractIds, + NETWORK ); if (error) { reply.code(400).send(error); @@ -206,7 +208,8 @@ export function initApiServer( const { pub_key, contract_id } = request.body; const { data, error } = await mercuryClient.tokenBalanceSubscription( contract_id, - pub_key + pub_key, + NETWORK ); if (error) { reply.code(400).send(error); diff --git a/src/service/mercury/helpers/transformers.ts b/src/service/mercury/helpers/transformers.ts new file mode 100644 index 0000000..fd8b609 --- /dev/null +++ b/src/service/mercury/helpers/transformers.ts @@ -0,0 +1,36 @@ +import { OperationResult } from "@urql/core"; + +// Transformers take an API response, and transform it/augment it for frontend consumption + +interface MercuryAccountBalancesData { + entryUpdateByContractIdAndKey: { + nodes: { + contractId: string; + keyXdr: string; + valueXdr: string; + }[]; + }; +} + +interface TokenDetails { + [k: string]: { + name: string; + symbol: string; + decimals: string; + }; +} + +const transformAccountBalances = async ( + rawResponse: OperationResult, + tokenDetails: TokenDetails +) => { + return rawResponse?.data?.entryUpdateByContractIdAndKey.nodes.map((entry) => { + const details = tokenDetails[entry.contractId]; + return { + ...entry, + ...details, + }; + }); +}; + +export { transformAccountBalances }; diff --git a/src/service/mercury/index.test.ts b/src/service/mercury/index.test.ts index cab9161..936ca2d 100644 --- a/src/service/mercury/index.test.ts +++ b/src/service/mercury/index.test.ts @@ -39,14 +39,13 @@ describe("Mercury Service", () => { "CCWAMYJME4H5CKG7OLXGC2T4M6FL52XCZ3OQOAV6LL3GLA4RO4WH3ASP", "CBGTG7XFRY3L6OKAUTR6KGDKUXUQBX3YDJ3QFDYTGVMOM7VV4O7NCODG", ]; - const { data } = await mockMercuryClient.getAccountBalances( + const data = await mockMercuryClient.getAccountBalances( pubKey, - contracts + contracts, + "TESTNET" ); expect( - data?.data.edges.map( - (node: { node: Record }) => node.node.contractId - ) + data?.data?.map((node: { contractId: string }) => node.contractId) ).toEqual(contracts); }); diff --git a/src/service/mercury/index.ts b/src/service/mercury/index.ts index 7384f06..4c45354 100644 --- a/src/service/mercury/index.ts +++ b/src/service/mercury/index.ts @@ -12,6 +12,7 @@ import { getTokenSymbol, getTxBuilder, } from "../../helper/soroban-rpc"; +import { transformAccountBalances } from "./helpers/transformers"; type NetworkNames = keyof typeof Networks; @@ -241,7 +242,11 @@ export class MercuryClient { } }; - tokenBalanceSubscription = async (contractId: string, pubKey: string) => { + tokenBalanceSubscription = async ( + contractId: string, + pubKey: string, + network: NetworkNames + ) => { try { const entrySub = { contract_id: contractId, @@ -261,7 +266,9 @@ export class MercuryClient { }; const data = await this.renewAndRetry(getData); - // await this.redisClient.set(contractId) + if (this.redisClient) { + await this.tokenDetails(pubKey, contractId, network); + } return { data, @@ -281,8 +288,18 @@ export class MercuryClient { pubKey: string, contractId: string, network: NetworkNames - ) => { + ): Promise< + { name: string; symbol: string; decimals: number } | undefined + > => { try { + const compositeKey = `${network}__${contractId}`; + // get from cache if we have them, otherwise go to ledger and cache + if (this.redisClient) { + const tokenDetails = await this.redisClient.get(compositeKey); + if (tokenDetails) { + return JSON.parse(tokenDetails); + } + } const server = await getServer(network); // we need a builder per operation, 1 op per tx in Soroban const decimalsBuilder = await getTxBuilder(pubKey, network, server); @@ -296,16 +313,25 @@ export class MercuryClient { const name = await getTokenName(contractId, server, nameBuilder); const symbolsBuilder = await getTxBuilder(pubKey, network, server); - const symbols = await getTokenSymbol(contractId, server, symbolsBuilder); + const symbol = await getTokenSymbol(contractId, server, symbolsBuilder); + const tokenDetails = { + name, + decimals, + symbol, + }; + + if (this.redisClient) { + await this.redisClient.set(compositeKey, JSON.stringify(tokenDetails)); + } return { name, decimals, - symbols, + symbol, }; } catch (error) { this.logger.error(error); - throw new Error(`Unable to fetch token details for ${contractId}`); + return; } }; @@ -338,22 +364,32 @@ export class MercuryClient { } }; - getAccountBalances = async (pubKey: string, contractIds: string[]) => { + getAccountBalances = async ( + pubKey: string, + contractIds: string[], + network: NetworkNames + ) => { // TODO: once classic subs include balance, add query try { const getData = async () => { - const data = await this.urqlClient.query( + const response = await this.urqlClient.query( query.getAccountBalances(this.tokenBalanceKey(pubKey), contractIds), {} ); - const errorMessage = getGraphQlError(data.error); + const errorMessage = getGraphQlError(response.error); if (errorMessage) { throw new Error(errorMessage); } - return data; + return response; }; - const data = await this.renewAndRetry(getData); + const response = await this.renewAndRetry(getData); + const tokenDetails = {} as { [index: string]: any }; + for (const contractId of contractIds) { + const details = await this.tokenDetails(pubKey, contractId, network); + tokenDetails[contractId] = details; + } + const data = await transformAccountBalances(response, tokenDetails); return { data, From aa51761784db70e6321a29a1e2efe6d714243ad3 Mon Sep 17 00:00:00 2001 From: Aristides Staffieri Date: Tue, 7 Nov 2023 13:20:09 -0700 Subject: [PATCH 3/7] removes temp test skip --- src/route/index.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/route/index.test.ts b/src/route/index.test.ts index 519a4ba..3d14f69 100644 --- a/src/route/index.test.ts +++ b/src/route/index.test.ts @@ -2,7 +2,7 @@ import { getDevServer, queryMockResponse, pubKey } from "../helper/test-helper"; import { query } from "../service/mercury/queries"; describe("API routes", () => { - describe.skip("/account-history/:pubKey", () => { + describe("/account-history/:pubKey", () => { it("can fetch an account history for a pub key", async () => { const server = await getDevServer(); const response = await fetch( From a5213fbea1c39baf655ab7cc9dbfee3e05c11946 Mon Sep 17 00:00:00 2001 From: Aristides Staffieri Date: Tue, 7 Nov 2023 16:08:23 -0700 Subject: [PATCH 4/7] adds deleteTokenSubscription service call --- src/service/mercury/helpers/transformers.ts | 18 ++++++- src/service/mercury/index.ts | 54 ++++++++++++++++++++- src/service/mercury/queries.ts | 18 +++++++ 3 files changed, 88 insertions(+), 2 deletions(-) diff --git a/src/service/mercury/helpers/transformers.ts b/src/service/mercury/helpers/transformers.ts index fd8b609..5fdd083 100644 --- a/src/service/mercury/helpers/transformers.ts +++ b/src/service/mercury/helpers/transformers.ts @@ -12,6 +12,16 @@ interface MercuryAccountBalancesData { }; } +interface MercuryAllEntryUpdatesData { + allEntryUpdates: { + nodes: { + contractId: string; + nodeId: string; + id: string; + }[]; + }; +} + interface TokenDetails { [k: string]: { name: string; @@ -33,4 +43,10 @@ const transformAccountBalances = async ( }); }; -export { transformAccountBalances }; +const transformEntryUpdates = async ( + rawResponse: OperationResult +) => { + return rawResponse?.data?.allEntryUpdates.nodes.map((node) => node); +}; + +export { transformAccountBalances, transformEntryUpdates }; diff --git a/src/service/mercury/index.ts b/src/service/mercury/index.ts index 4c45354..3c77298 100644 --- a/src/service/mercury/index.ts +++ b/src/service/mercury/index.ts @@ -12,7 +12,10 @@ import { getTokenSymbol, getTxBuilder, } from "../../helper/soroban-rpc"; -import { transformAccountBalances } from "./helpers/transformers"; +import { + transformAccountBalances, + transformEntryUpdates, +} from "./helpers/transformers"; type NetworkNames = keyof typeof Networks; @@ -284,6 +287,55 @@ export class MercuryClient { } }; + deleteTokenSubscription = async (contractId: string) => { + // get all entry update subs, find ones that match contractId, delete by ID. + try { + const getData = async () => { + const response = await this.urqlClient.query( + query.getAllEntryUpdates, + {} + ); + const errorMessage = getGraphQlError(response.error); + if (errorMessage) { + throw new Error(errorMessage); + } + + return response; + }; + const response = await this.renewAndRetry(getData); + const data = await transformEntryUpdates(response); + const match = data?.filter((d) => d.contractId === contractId); + + let deleted = false; + if (match) { + const response = await this.urqlClient.mutation( + mutation.deleteEntryUpdateById, + { contractId } + ); + const errorMessage = getGraphQlError(response.error); + if (errorMessage) { + throw new Error(errorMessage); + } + deleted = response.error !== undefined; + } + + return { + data: { + contractId, + deleted, + }, + error: null, + }; + } catch (error) { + const _error = JSON.stringify(error); + this.logger.error(error); + return { + data: null, + error: _error, + }; + } + }; + tokenDetails = async ( pubKey: string, contractId: string, diff --git a/src/service/mercury/queries.ts b/src/service/mercury/queries.ts index 103c289..298653a 100644 --- a/src/service/mercury/queries.ts +++ b/src/service/mercury/queries.ts @@ -18,6 +18,13 @@ export const mutation = { } } `, + deleteEntryUpdateById: ` + mutation DeletEntryById($contractId: String!) { + deleteEntryUpdateById(input: {id: $contractId}) { + deletedEntryUpdateId + } + } + `, }; export const query = { allSubscriptions: ` @@ -473,4 +480,15 @@ export const query = { } `, + getAllEntryUpdates: ` + query GetAllEntryUpdates { + allEntryUpdates { + nodes { + contractId + nodeId + id + } + } + } + `, }; From f1b67515f6a51b9b35e05253628c313480dde3d5 Mon Sep 17 00:00:00 2001 From: Aristides Staffieri Date: Wed, 8 Nov 2023 08:33:46 -0700 Subject: [PATCH 5/7] removes deleteTokenSub --- src/service/mercury/index.ts | 49 ------------------------------------ 1 file changed, 49 deletions(-) diff --git a/src/service/mercury/index.ts b/src/service/mercury/index.ts index 3c77298..fbdb2f4 100644 --- a/src/service/mercury/index.ts +++ b/src/service/mercury/index.ts @@ -287,55 +287,6 @@ export class MercuryClient { } }; - deleteTokenSubscription = async (contractId: string) => { - // get all entry update subs, find ones that match contractId, delete by ID. - try { - const getData = async () => { - const response = await this.urqlClient.query( - query.getAllEntryUpdates, - {} - ); - const errorMessage = getGraphQlError(response.error); - if (errorMessage) { - throw new Error(errorMessage); - } - - return response; - }; - const response = await this.renewAndRetry(getData); - const data = await transformEntryUpdates(response); - const match = data?.filter((d) => d.contractId === contractId); - - let deleted = false; - if (match) { - const response = await this.urqlClient.mutation( - mutation.deleteEntryUpdateById, - { contractId } - ); - const errorMessage = getGraphQlError(response.error); - if (errorMessage) { - throw new Error(errorMessage); - } - deleted = response.error !== undefined; - } - - return { - data: { - contractId, - deleted, - }, - error: null, - }; - } catch (error) { - const _error = JSON.stringify(error); - this.logger.error(error); - return { - data: null, - error: _error, - }; - } - }; - tokenDetails = async ( pubKey: string, contractId: string, From 1d2d626f17e1891e959e61dc64c8690e2c9f05f8 Mon Sep 17 00:00:00 2001 From: Aristides Staffieri Date: Wed, 8 Nov 2023 08:34:49 -0700 Subject: [PATCH 6/7] removes deleteTokenSub related helpers --- src/service/mercury/helpers/transformers.ts | 8 +------- src/service/mercury/queries.ts | 7 ------- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/src/service/mercury/helpers/transformers.ts b/src/service/mercury/helpers/transformers.ts index 5fdd083..c4fcbd4 100644 --- a/src/service/mercury/helpers/transformers.ts +++ b/src/service/mercury/helpers/transformers.ts @@ -43,10 +43,4 @@ const transformAccountBalances = async ( }); }; -const transformEntryUpdates = async ( - rawResponse: OperationResult -) => { - return rawResponse?.data?.allEntryUpdates.nodes.map((node) => node); -}; - -export { transformAccountBalances, transformEntryUpdates }; +export { transformAccountBalances }; diff --git a/src/service/mercury/queries.ts b/src/service/mercury/queries.ts index 298653a..6f3e9e4 100644 --- a/src/service/mercury/queries.ts +++ b/src/service/mercury/queries.ts @@ -18,13 +18,6 @@ export const mutation = { } } `, - deleteEntryUpdateById: ` - mutation DeletEntryById($contractId: String!) { - deleteEntryUpdateById(input: {id: $contractId}) { - deletedEntryUpdateId - } - } - `, }; export const query = { allSubscriptions: ` From 86db55f46bd023c03d7df19562a51bed8ccf0ef1 Mon Sep 17 00:00:00 2001 From: Aristides Staffieri Date: Wed, 8 Nov 2023 08:38:21 -0700 Subject: [PATCH 7/7] cleans up leftover helper/query imports --- src/service/mercury/helpers/transformers.ts | 10 ---------- src/service/mercury/index.ts | 5 +---- src/service/mercury/queries.ts | 11 ----------- 3 files changed, 1 insertion(+), 25 deletions(-) diff --git a/src/service/mercury/helpers/transformers.ts b/src/service/mercury/helpers/transformers.ts index c4fcbd4..fd8b609 100644 --- a/src/service/mercury/helpers/transformers.ts +++ b/src/service/mercury/helpers/transformers.ts @@ -12,16 +12,6 @@ interface MercuryAccountBalancesData { }; } -interface MercuryAllEntryUpdatesData { - allEntryUpdates: { - nodes: { - contractId: string; - nodeId: string; - id: string; - }[]; - }; -} - interface TokenDetails { [k: string]: { name: string; diff --git a/src/service/mercury/index.ts b/src/service/mercury/index.ts index fbdb2f4..4c45354 100644 --- a/src/service/mercury/index.ts +++ b/src/service/mercury/index.ts @@ -12,10 +12,7 @@ import { getTokenSymbol, getTxBuilder, } from "../../helper/soroban-rpc"; -import { - transformAccountBalances, - transformEntryUpdates, -} from "./helpers/transformers"; +import { transformAccountBalances } from "./helpers/transformers"; type NetworkNames = keyof typeof Networks; diff --git a/src/service/mercury/queries.ts b/src/service/mercury/queries.ts index 6f3e9e4..103c289 100644 --- a/src/service/mercury/queries.ts +++ b/src/service/mercury/queries.ts @@ -473,15 +473,4 @@ export const query = { } `, - getAllEntryUpdates: ` - query GetAllEntryUpdates { - allEntryUpdates { - nodes { - contractId - nodeId - id - } - } - } - `, };