@gibs/bridge-indexer
v1.20.0
Published
Reads a Gibs Finance bridge indexer: transfer archive, delivery receipts, and live crossing status.
Maintainers
Readme
@gibs/bridge-indexer
Reads a Gibs Finance bridge indexer. It gives you the transfer archive, delivery receipts, and live crossing status. It only reads. It never signs or broadcasts.
Endpoint
The package reads https://next-indexer.gibs.finance by default. This is the owner's choice "for now". The next indexer follows the current schema.
Importing the package has no side effects. The package creates its GraphQL client on first use.
To read another indexer, call setIndexerEndpoint before the first query:
import { setIndexerEndpoint, indexerEndpoint, DEFAULT_INDEXER_ENDPOINT } from '@gibs/bridge-indexer'
setIndexerEndpoint('http://localhost:42069/graphql')
indexerEndpoint() // the address now in forceThe indexer serves GraphQL at / and at /graphql. It serves GET /version with the indexer package version, the Ponder schema name, and the git commit when the deploy sets GIT_SHA. The indexer no longer serves raw SQL.
Production https://indexer.gibs.finance may lag the schema in this package. If a query fails there with an unknown field, point the package at the next indexer.
One transfer's status in one call
fetchTransferStatus takes the transaction that started a transfer, as { chainId, txHash }. It returns:
state: one state fromdocs/transfer-states.md.transferStateNamesholds that document's own words for each one.claimable: true when the crossing is signed and not yet executed, so anybody can release it. This is true in both ready states, because an attached delivery service can still never come.destinationTxHash: the transaction that settled the destination side, once the indexer has one.aggregatorStatus: the aggregator's own answer, for a route that starts off an aggregator.
import { fetchTransferStatus } from '@gibs/bridge-indexer'
const status = await fetchTransferStatus(
{ chainId: 42161, txHash },
{
aggregator: { provider: 'relay', requestId, apiKey: myRelayApiKey },
signal: controller.signal,
},
)Every option is optional: fetch, endpoint (defaults to indexerEndpoint()), signal, aggregator, aggregatorFinalLeg and originClient. With an originClient (a viem PublicClient on the origin chain), the answer can tell sent from confirmed-not-final. Without one, a transaction the indexer has not recorded yet is unknown.
The function works around every defect below.
Read the record a claim needs
fetchTransferStatus says that a transfer is claimable. It does not return the signatures a claim carries, so the status stays small. fetchClaimRecords reads those. Pass the transaction that started the transfer, or one request's message hash. It returns every request the transaction started, oldest first, and an empty list when the indexer has none yet.
import { buildClaimTransaction } from '@gibs/bridge-sdk/claims'
import { fetchClaimRecords } from '@gibs/bridge-indexer'
const records = await fetchClaimRecords({ source: { chainId: 369, txHash } })
const plans = records.map((request) => buildClaimTransaction({ request, via: { kind: 'direct' } }))Each record is a ClaimableUserRequest with its messageHash, so it goes to buildClaimTransaction as it is. The call makes no RPC read and writes no log.
Known defects in the production data
A batched re-index will fix these. Until it runs, work around them.
- Five relations are always
null. Do not read them:AMBBridge.validatorContractOmnibridge.ambBridgeOmnibridge.validatorContractUserRequest.destinationAMBBridgeUserRequest.destinationOmnibridge
- The joins between a request and its
CompletionorDeliverywork in one direction only. QueryCompletionorDeliverybymessageHashinstead of expecting the join on the request. - A message for a native pathway records the ERC-20 omnibridge, not the native one.
- Read
delivered(a boolean on the request). Do not readdelivery. Thedeliveryrelation can benullfor a request that landed. - Hex filters are lowercase. A checksummed address in a
whereclause matches nothing. Lowercase every address and hash first.
Units of fee fields
FeeUpdate.feeis a rate. It is a fraction scaled by 1e18.10n ** 18nmeans 100 percent. The amount isamount * fee / 10n ** 18n.UserRequest.feeAmountis the fee the omnibridge took. It is in base units of the origin token.nullmeans no fee log was seen, which in practice means the fee was zero.- Read
feeAmountfor the fee actually taken.feeUpdate.feeis the rate that was configured at the time. That is a different fact. BigIntfields arrive as decimal strings.Numericfields arrive as a number or a string.
Schema snapshot and codegen
schema.graphql is a committed snapshot of the indexer schema. src/graphql.ts is generated from it. Codegen never contacts a live host.
| Script | What it does |
| --- | --- |
| yarn codegen | Regenerates src/graphql.ts from schema.graphql. Offline. |
| yarn schema:update | Introspects the live next indexer and rewrites schema.graphql. |
| yarn schema:check | Exits 1 when the live schema differs from the snapshot. Not run in continuous integration. Run it by hand before a release. |
To follow a schema change, run yarn schema:update, then yarn codegen, then the tests. A test fails when the snapshot and the generated types disagree. A schema change cannot ship without regenerating.
schema:update and schema:check accept an address as a second word, for example node scripts/schema-snapshot.mjs check https://indexer.gibs.finance/graphql.
License
ISC. See LICENSE.
