List view
Our wallet backend data model seems to be inefficient and not follow best practices for database design. We should take a look at our indexer tables and make changes accordingly before we release wallet backend to production
No due date•2/13 issues closedWe want to store balances in wallet backend in the PostgresQL tables. This includes storing trustline, native and SAC balances. This would also require a refactor to move away from Redis which we use as an account token cache right now.
Overdue by 16 day(s)•Due by January 31, 2026•4/4 issues closedThe wallet backend needs to support account balances for different types of tokens: classic trustlines, SAC, SEP-41 and SEP-50
Overdue by 1 month(s)•Due by December 31, 2025•16/16 issues closedIts extremely important that the wallet backend process ledgers faster than they close. Failing to do so, even briefly, will result in negative impacts to downstream application's services. We have this problem with Horizon today, and while the wallet backend aims to index less data than Horizon does, it does this by introducing additional filtering complexity that may negatively impact performance. Its data model also requires additional filter conditions that Horizon only has available by configuration, not default. The wallet backend needs a comprehensive performance testing framework to ensure changes to not cause performance regressions. Stellar block times will only get shorter.
No due date•2/2 issues closedMost indexers in the industry to day are actually platforms for creating indexes. Meaning, they offer some foundational data model that can be used by third-party developers to derive more abstract or purpose-built data models that can be queried. Some approaches such as The Graph and Subquery allow developers to write JavaScript code to parse and process the foundational or raw data indexed by the platform so it can be write to a managed database. Others such as Goldsky allow developers to write SQL queries that are executed once per ledger ingested by the platform. These queries select data from the foundational tables and write to application-specific tables. The wallet backend is currently not a platform. Its data model and API cannot be extended unless developers contribute directly to the project's source code. Ideally, developers would have a path forward for extension that is similarly accessible to writing JavaScript or SQL. It remains unclear if this is viable or if the design of such a system would be acceptable from a product perspective, but further research should be done to come to conclusions.
No due dateIn addition to indexing the current USD value of tokens and the account's total USD balance, we should also index the token's prices over different periods of time such as all time, 1 year, 3 months, 1 month, 1 week, and 1 day. This will enable wallets to display token price graphs to users which is a common experience in financial applications.
No due dateToday, the wallet backend indexes transactions that sponsor reserves for registered accounts. However, it does not index the increases and decreases of an account's reserves, which is used to derive the account's available XLM balance. We should update our indexing to replace "sponsorship" state changes with "reserve" state changes that index a larger set of changes. Namely, we should index changes to reserves regardless of whether an account sponsored the reserve. Once this is implemented, it can be used to calculate the "available" balance for registered account's current XLM balance.
No due dateThe wallet backend is a pull-only service, so clients must poll the API to get its data and become aware of changes to their users' accounts' state. We should consider supporting a push method, so clients can be notified of changes to registered accounts without polling. HTTPS webhooks are one common approach, but websockets are also common and better-suited for client-side applications without backends. Given that the API is also GraphQL, and therefore API response schemas are flexible and defined by the client, it is unclear what the schema of HTTPS or websocket callbacks should be, or if we should try to define an approach for the client to specify their preferred schema and criteria for receiving a message.
No due dateThe wallet backend will soon index registered account's SEP41-compatible token balances (including SACs), and SEP-50 balances are also planned. However, USD prices for these tokens are absent from the wallet backend. Prices for tokens is almost as necessary for wallets as token balances are, so it may be worth adding token prices to the wallet backend as well. Token metadata, such as total supply and or information about the issuer, may not make sense to be in-scope for the wallet backend, given that the wallet backend is an account indexer first and foremost and not a token indexer. Metadata for tokens may be worth implementing in the Freighter backend v2 though, so it can serve our token details view within Freighter. Token prices is already implemented in Freighter backend v1, but it uses Horizon's orderbook API. We need to get off Horizon, so one approach is to pull out its orderbook package so we can source pricing data directly within the wallet backend. Another approach is to observe trades that execute in order to estimate current market price, which is what Horizon's trade aggregations endpoints provide. Regardless, current USD token prices for registered accounts' balances should be something supported within the wallet backend.
No due dateToday the criteria used to determine if a contract invocation should be indexed is as follows: if the contract is a SAC or a SEP41-compatible contract token and involves a registered account, it is indexed. If the contract is not a SAC or SEP41-compatible contract token, then it is only indexed if a registered account authorized the invocation. This is done because we cannot determine whether a transaction that invokes an unknown contract is relevant to a user with 100% accuracy, so we default to using a criteria that ensures 100% of the transactions we index are relevant. This of course makes it possible to leave out transactions that are relevant to registered accounts but are not authorized by any registered accounts. We can choose to make a different approach configurable, although the existing behavior should remain the default, because the alternative requires the client to implement filtering which they may not do initially upon integrating. Instead of only using authorizations in our criteria, we can use the function's arguments, the transaction's footprint, and the events emitted, to search for references to registered accounts and index it as an `UNSUPPORTED` transaction if it does. This will result in a more complete set of transactions, although it still will not be 100% accurate because transactions that are relevant to a registered account may not reference the account's address in any way. To support these cases we need to have first-class support for the contract.
No due dateToday the wallet backend only indexes SEP-41 tokens. We should add support for SEP-50 NFTs as well. This includes both historical state (so transactions, operations, and state changes) as well as current state, similar to SEP-41 tokens, so clients can query for the collectibles an account currently has.
No due dateThere are two types of data indexed in the wallet backend, "raw" data like transactions and operations, and "abstractions" like state changes, which are derived from our raw data. Today, we index "raw" data and "abstractions" for stellar classic operations. For contract invocations, unless they are invocations of Stellar asset contracts (SACs), we only index the "raw" data. We also only index this raw transaction data when a registered account authorized the transaction. For example, if a registered account is the destination of a `transfer` invocation for USDC (an SAC) we will index the "raw" data and the "abstractions". If the account is the source of a `transfer` invocation for a contract token (non-SAC), then we will index the "raw" data because our account had to authorize the transfer. If the account is the destination of a `transfer` invocation for a contract token (non-SAC), we will not index the "raw" data at all because the destination doesn't need to authorize the transaction. The reason we don't index "abstractions" for unknown contracts and only index "raw" data for unknown contracts if they're authorized by a registered account is because we cannot determine if they comply with a known protocol or SEP with 100% accuracy, so today we don't even try to that determination. We could implement the inspection of contracts invoked to determine if they look like they comply with a SEP or known protocol, such as SEP-41 or SEP-50, and if they do, ingest their "raw" data and "abstractions". However, any approach we take will not be 100% accurate, which could result in poor user experience. The possible impacts could be inaccurate items in history, inaccurate balance calculations, inaccurate total USD value calculations, and failed transactions when trying to send or swap these tokens. We may need a way for clients to indicate to the backend which contracts to ignore if we do this, so the wallet backend can update its history and current state data retroactively.
No due dateCatchup is the process of ingesting historical data starting from the last successfully ingested ledger regardless of how long ago the most recent ledger was ingested. Catchup is necessary to properly recover from periods of downtime. Right now, if the wallet backend is down for longer than RPC's retention window, we will have gaps and will be unable to catch up. Backfilling is the process of ingesting historical data from ledgers that were closed prior to being instructed to begin ingesting data. In the context of the wallet backend, we need to backfill a newly registered account's data. For example, an account that was created two years ago is registered with the wallet backend. Today, we begin ingesting data for that account starting from the time it was registered. The two years worth of data for the account prior to registration is not ingested. Data migrations are necessary when the wallet backend adds support for indexing additional SEPs or protocols, or simply changes its data model to better indexing what is already supported. For example, today we do not index SEP-50 collectibles, but that doesn't mean our registered accounts are not interacting SEP-50 collectibles. When we add support for SEP-50 collectibles, we need to backfill our registered account's interactions with SEP-50 collectibles in addition to supporting the interactions they have after we add support.
No due date•4/4 issues closedDefine deploy pipelines and deploy the wallet backend in all three environments (dev, staging, prod). Setup sentry alerts, granfana dashboards, and any other observability or monitoring infra necessary. Release strategy should be defined and documented.
Overdue by 1 month(s)•Due by December 31, 2025•15/16 issues closedThis project adds the minimum feature set necessary for supporting Meridian Pay
Overdue by 1 month(s)•Due by December 31, 2025•15/15 issues closed