@cfxlabsinc/b2b-services
    Preparing search index...

    Cross-customer admin access to ledger accounts.

    Extends LedgerAccountCache, so this read shares the ledger-account-search namespace — and therefore the membership-tag vocabulary — with the customer surface. That replaces the mutual cross-construction the two services used to do, in which each built a detached ServiceCache over the other's namespace purely to bust it.

    The inherited invalidateCache({ customerIds }) is the seam the Helius on-chain balance webhook calls, so admin pickers invalidate whenever the consumer dashboard does — including on balance changes.

    Hierarchy (View Summary)

    Index
    cache: ServiceCache<CachedSearchPage<LedgerAccountSearchItem>>
    db: B2bDatabase
    withoutBalanceCache: ServiceCache<
        CachedSearchPage<LedgerAccountSearchItemWithoutBalance>,
    >

    Balance-free pages: their own key space, reached by the same namespace tags.

    instance: (...args: []) => LedgerAccountAdminService = ...

    The process default: built from each dependency's own instance().

    • Get the given ledger account (admin, cross-customer)

      Parameters

      • args: { id: string }

      Returns Promise<
          {
              ok: true;
              value: | {
                  address: Address;
                  balance: BigNumber;
                  createdAt: Date;
                  id: string;
                  name: string;
                  notes?: string;
                  paymentInstrumentId?: string;
                  permissions: "ALL"
                  | "ADMIN";
                  referenceId?: string;
                  tokenAccounts: Partial<Record<"MOVEUSD", { address: Address }>>;
                  updatedAt: Date;
                  visibility: "PRIVATE" | "PUBLIC";
              } & {
                  customerId: string;
                  customerName: string;
                  customerOrganizationId: string;
                  entityDisplayName: string;
                  entityId: string;
                  entityReferenceId: string
                  | null;
                  entityType: "IDENTITY" | "ORGANIZATION";
                  rawName: string | null;
              }
              | null;
          },
      >

    • Clear each customer's membership tag and each record tag wherever cached, and always this namespace's collection tag. keys are exact deletes in this instance's key space: the only bust a null client honours.

      Parameters

      • __namedParameters: {
            customerIds: readonly string[];
            keys?: readonly CacheKey[];
            records?: readonly string[];
        }

      Returns Promise<void>

    • Search ledger accounts across customers (cross-customer admin search). Read-through cached in the shared LedgerAccountCache namespace.

      Parameters

      • args: LedgerAccountSearchFilters & {
            addresses?: Address[];
            bankIds?: string[];
            blockTime?: Date;
            createdAt?: DbTimestampCriteria;
            customerIds?: string[];
            entityIds?: string[];
            ids?: string[];
            orderBy?: (
                | DbOrderByCriterion<
                    Omit<
                        PgTableWithColumns<
                            {
                                columns: {
                                    address: PgBuildColumn<(...), (...), (...)>;
                                    createdAt: PgBuildColumn<(...), (...), (...)>;
                                    customerExternalId: PgBuildColumn<(...), (...), (...)>;
                                    customerId: PgBuildColumn<(...), (...), (...)>;
                                    data: PgBuildColumn<(...), (...), (...)>;
                                    externalId: PgBuildColumn<(...), (...), (...)>;
                                    id: PgBuildColumn<(...), (...), (...)>;
                                    identityExternalId: PgBuildColumn<(...), (...), (...)>;
                                    identityId: PgBuildColumn<(...), (...), (...)>;
                                    name: PgBuildColumn<(...), (...), (...)>;
                                    organizationExternalId: PgBuildColumn<(...), (...), (...)>;
                                    organizationId: PgBuildColumn<(...), (...), (...)>;
                                    permissions: PgBuildColumn<(...), (...), (...)>;
                                    referenceId: PgBuildColumn<(...), (...), (...)>;
                                    searchDocument: PgBuildColumn<(...), (...), (...)>;
                                    solanaWalletId: PgBuildColumn<(...), (...), (...)>;
                                    updatedAt: PgBuildColumn<(...), (...), (...)>;
                                    visibility: PgBuildColumn<(...), (...), (...)>;
                                    walletExternalId: PgBuildColumn<(...), (...), (...)>;
                                    walletId: PgBuildColumn<(...), (...), (...)>;
                                    walletSecretId: PgBuildColumn<(...), (...), (...)>;
                                };
                                dialect: "pg";
                                isAlias: false;
                                name: "ledger_account";
                                schema: "b2b";
                            },
                        >,
                        "enableRLS",
                    >,
                    "createdAt",
                >
                | { direction: "ASC"
                | "DESC"; field: "balance" }
            )[];
            page?: number;
            pageSize?: number;
            q?: string;
            walletAddresses?: string[];
            walletIds?: string[];
        } & { withoutBalance: true }
        • Optionaladdresses?: Address[]
        • OptionalbankIds?: string[]

          Accounts tied to any of these banks by an active deposit bank memo, an active virtual account or a transaction at the bank; any one is enough. Omitted spans every bank; an empty list matches nothing.

        • OptionalblockTime?: Date

          Value each account's balance as of this instant — the most recent on-chain post-balance at or before it — instead of the current balance. A balance-valuation modifier, not a row filter; omit for the latest balance.

        • OptionalcreatedAt?: DbTimestampCriteria
        • OptionalcustomerIds?: string[]
        • OptionalentityIds?: string[]
        • Optionalids?: string[]
        • OptionalorderBy?: (
              | DbOrderByCriterion<
                  Omit<
                      PgTableWithColumns<
                          {
                              columns: {
                                  address: PgBuildColumn<(...), (...), (...)>;
                                  createdAt: PgBuildColumn<(...), (...), (...)>;
                                  customerExternalId: PgBuildColumn<(...), (...), (...)>;
                                  customerId: PgBuildColumn<(...), (...), (...)>;
                                  data: PgBuildColumn<(...), (...), (...)>;
                                  externalId: PgBuildColumn<(...), (...), (...)>;
                                  id: PgBuildColumn<(...), (...), (...)>;
                                  identityExternalId: PgBuildColumn<(...), (...), (...)>;
                                  identityId: PgBuildColumn<(...), (...), (...)>;
                                  name: PgBuildColumn<(...), (...), (...)>;
                                  organizationExternalId: PgBuildColumn<(...), (...), (...)>;
                                  organizationId: PgBuildColumn<(...), (...), (...)>;
                                  permissions: PgBuildColumn<(...), (...), (...)>;
                                  referenceId: PgBuildColumn<(...), (...), (...)>;
                                  searchDocument: PgBuildColumn<(...), (...), (...)>;
                                  solanaWalletId: PgBuildColumn<(...), (...), (...)>;
                                  updatedAt: PgBuildColumn<(...), (...), (...)>;
                                  visibility: PgBuildColumn<(...), (...), (...)>;
                                  walletExternalId: PgBuildColumn<(...), (...), (...)>;
                                  walletId: PgBuildColumn<(...), (...), (...)>;
                                  walletSecretId: PgBuildColumn<(...), (...), (...)>;
                              };
                              dialect: "pg";
                              isAlias: false;
                              name: "ledger_account";
                              schema: "b2b";
                          },
                      >,
                      "enableRLS",
                  >,
                  "createdAt",
              >
              | { direction: "ASC"
              | "DESC"; field: "balance" }
          )[]
        • Optionalpage?: number

          Defaults to 1

        • OptionalpageSize?: number

          Defaults to 100

        • Optionalq?: string

          Case-insensitive substring match on account name or entity name. Whitespace-only values are a no-op.

        • OptionalwalletAddresses?: string[]

          Accounts whose wallet holds any of these addresses, on any chain.

        • OptionalwalletIds?: string[]

          Accounts on any of these wallets (wal_…).

        • withoutBalance: true

          Rows carry no balance, and none is computed for them. A balance sort or filter still runs it.

      • Optionaloptions: StatementOptions

      Returns Promise<{ ok: true; value: CachedSearchPage }>

    • Search ledger accounts across customers (cross-customer admin search). Read-through cached in the shared LedgerAccountCache namespace.

      Parameters

      • args: LedgerAccountSearchFilters & {
            addresses?: Address[];
            bankIds?: string[];
            blockTime?: Date;
            createdAt?: DbTimestampCriteria;
            customerIds?: string[];
            entityIds?: string[];
            ids?: string[];
            orderBy?: (
                | DbOrderByCriterion<
                    Omit<
                        PgTableWithColumns<
                            {
                                columns: {
                                    address: PgBuildColumn<(...), (...), (...)>;
                                    createdAt: PgBuildColumn<(...), (...), (...)>;
                                    customerExternalId: PgBuildColumn<(...), (...), (...)>;
                                    customerId: PgBuildColumn<(...), (...), (...)>;
                                    data: PgBuildColumn<(...), (...), (...)>;
                                    externalId: PgBuildColumn<(...), (...), (...)>;
                                    id: PgBuildColumn<(...), (...), (...)>;
                                    identityExternalId: PgBuildColumn<(...), (...), (...)>;
                                    identityId: PgBuildColumn<(...), (...), (...)>;
                                    name: PgBuildColumn<(...), (...), (...)>;
                                    organizationExternalId: PgBuildColumn<(...), (...), (...)>;
                                    organizationId: PgBuildColumn<(...), (...), (...)>;
                                    permissions: PgBuildColumn<(...), (...), (...)>;
                                    referenceId: PgBuildColumn<(...), (...), (...)>;
                                    searchDocument: PgBuildColumn<(...), (...), (...)>;
                                    solanaWalletId: PgBuildColumn<(...), (...), (...)>;
                                    updatedAt: PgBuildColumn<(...), (...), (...)>;
                                    visibility: PgBuildColumn<(...), (...), (...)>;
                                    walletExternalId: PgBuildColumn<(...), (...), (...)>;
                                    walletId: PgBuildColumn<(...), (...), (...)>;
                                    walletSecretId: PgBuildColumn<(...), (...), (...)>;
                                };
                                dialect: "pg";
                                isAlias: false;
                                name: "ledger_account";
                                schema: "b2b";
                            },
                        >,
                        "enableRLS",
                    >,
                    "createdAt",
                >
                | { direction: "ASC"
                | "DESC"; field: "balance" }
            )[];
            page?: number;
            pageSize?: number;
            q?: string;
            walletAddresses?: string[];
            walletIds?: string[];
        } & { withoutBalance?: undefined }
        • Optionaladdresses?: Address[]
        • OptionalbankIds?: string[]

          Accounts tied to any of these banks by an active deposit bank memo, an active virtual account or a transaction at the bank; any one is enough. Omitted spans every bank; an empty list matches nothing.

        • OptionalblockTime?: Date

          Value each account's balance as of this instant — the most recent on-chain post-balance at or before it — instead of the current balance. A balance-valuation modifier, not a row filter; omit for the latest balance.

        • OptionalcreatedAt?: DbTimestampCriteria
        • OptionalcustomerIds?: string[]
        • OptionalentityIds?: string[]
        • Optionalids?: string[]
        • OptionalorderBy?: (
              | DbOrderByCriterion<
                  Omit<
                      PgTableWithColumns<
                          {
                              columns: {
                                  address: PgBuildColumn<(...), (...), (...)>;
                                  createdAt: PgBuildColumn<(...), (...), (...)>;
                                  customerExternalId: PgBuildColumn<(...), (...), (...)>;
                                  customerId: PgBuildColumn<(...), (...), (...)>;
                                  data: PgBuildColumn<(...), (...), (...)>;
                                  externalId: PgBuildColumn<(...), (...), (...)>;
                                  id: PgBuildColumn<(...), (...), (...)>;
                                  identityExternalId: PgBuildColumn<(...), (...), (...)>;
                                  identityId: PgBuildColumn<(...), (...), (...)>;
                                  name: PgBuildColumn<(...), (...), (...)>;
                                  organizationExternalId: PgBuildColumn<(...), (...), (...)>;
                                  organizationId: PgBuildColumn<(...), (...), (...)>;
                                  permissions: PgBuildColumn<(...), (...), (...)>;
                                  referenceId: PgBuildColumn<(...), (...), (...)>;
                                  searchDocument: PgBuildColumn<(...), (...), (...)>;
                                  solanaWalletId: PgBuildColumn<(...), (...), (...)>;
                                  updatedAt: PgBuildColumn<(...), (...), (...)>;
                                  visibility: PgBuildColumn<(...), (...), (...)>;
                                  walletExternalId: PgBuildColumn<(...), (...), (...)>;
                                  walletId: PgBuildColumn<(...), (...), (...)>;
                                  walletSecretId: PgBuildColumn<(...), (...), (...)>;
                              };
                              dialect: "pg";
                              isAlias: false;
                              name: "ledger_account";
                              schema: "b2b";
                          },
                      >,
                      "enableRLS",
                  >,
                  "createdAt",
              >
              | { direction: "ASC"
              | "DESC"; field: "balance" }
          )[]
        • Optionalpage?: number

          Defaults to 1

        • OptionalpageSize?: number

          Defaults to 100

        • Optionalq?: string

          Case-insensitive substring match on account name or entity name. Whitespace-only values are a no-op.

        • OptionalwalletAddresses?: string[]

          Accounts whose wallet holds any of these addresses, on any chain.

        • OptionalwalletIds?: string[]

          Accounts on any of these wallets (wal_…).

        • OptionalwithoutBalance?: undefined
      • Optionaloptions: StatementOptions

      Returns Promise<{ ok: true; value: CachedSearchPage }>

    • Parameters

      • __namedParameters: LedgerAccountSearchFilters & {
            addresses?: Address[];
            bankIds?: string[];
            blockTime?: Date;
            createdAt?: DbTimestampCriteria;
            customerIds?: string[];
            entityIds?: string[];
            ids?: string[];
            orderBy?: (
                | DbOrderByCriterion<
                    Omit<
                        PgTableWithColumns<
                            {
                                columns: {
                                    address: PgBuildColumn<(...), (...), (...)>;
                                    createdAt: PgBuildColumn<(...), (...), (...)>;
                                    customerExternalId: PgBuildColumn<(...), (...), (...)>;
                                    customerId: PgBuildColumn<(...), (...), (...)>;
                                    data: PgBuildColumn<(...), (...), (...)>;
                                    externalId: PgBuildColumn<(...), (...), (...)>;
                                    id: PgBuildColumn<(...), (...), (...)>;
                                    identityExternalId: PgBuildColumn<(...), (...), (...)>;
                                    identityId: PgBuildColumn<(...), (...), (...)>;
                                    name: PgBuildColumn<(...), (...), (...)>;
                                    organizationExternalId: PgBuildColumn<(...), (...), (...)>;
                                    organizationId: PgBuildColumn<(...), (...), (...)>;
                                    permissions: PgBuildColumn<(...), (...), (...)>;
                                    referenceId: PgBuildColumn<(...), (...), (...)>;
                                    searchDocument: PgBuildColumn<(...), (...), (...)>;
                                    solanaWalletId: PgBuildColumn<(...), (...), (...)>;
                                    updatedAt: PgBuildColumn<(...), (...), (...)>;
                                    visibility: PgBuildColumn<(...), (...), (...)>;
                                    walletExternalId: PgBuildColumn<(...), (...), (...)>;
                                    walletId: PgBuildColumn<(...), (...), (...)>;
                                    walletSecretId: PgBuildColumn<(...), (...), (...)>;
                                };
                                dialect: "pg";
                                isAlias: false;
                                name: "ledger_account";
                                schema: "b2b";
                            },
                        >,
                        "enableRLS",
                    >,
                    "createdAt",
                >
                | { direction: "ASC"
                | "DESC"; field: "balance" }
            )[];
            page?: number;
            pageSize?: number;
            q?: string;
            walletAddresses?: string[];
            walletIds?: string[];
        } & { withoutBalance?: undefined }
        • Optionaladdresses?: Address[]
        • OptionalbankIds?: string[]

          Accounts tied to any of these banks by an active deposit bank memo, an active virtual account or a transaction at the bank; any one is enough. Omitted spans every bank; an empty list matches nothing.

        • OptionalblockTime?: Date

          Value each account's balance as of this instant — the most recent on-chain post-balance at or before it — instead of the current balance. A balance-valuation modifier, not a row filter; omit for the latest balance.

        • OptionalcreatedAt?: DbTimestampCriteria
        • OptionalcustomerIds?: string[]
        • OptionalentityIds?: string[]
        • Optionalids?: string[]
        • OptionalorderBy?: (
              | DbOrderByCriterion<
                  Omit<
                      PgTableWithColumns<
                          {
                              columns: {
                                  address: PgBuildColumn<(...), (...), (...)>;
                                  createdAt: PgBuildColumn<(...), (...), (...)>;
                                  customerExternalId: PgBuildColumn<(...), (...), (...)>;
                                  customerId: PgBuildColumn<(...), (...), (...)>;
                                  data: PgBuildColumn<(...), (...), (...)>;
                                  externalId: PgBuildColumn<(...), (...), (...)>;
                                  id: PgBuildColumn<(...), (...), (...)>;
                                  identityExternalId: PgBuildColumn<(...), (...), (...)>;
                                  identityId: PgBuildColumn<(...), (...), (...)>;
                                  name: PgBuildColumn<(...), (...), (...)>;
                                  organizationExternalId: PgBuildColumn<(...), (...), (...)>;
                                  organizationId: PgBuildColumn<(...), (...), (...)>;
                                  permissions: PgBuildColumn<(...), (...), (...)>;
                                  referenceId: PgBuildColumn<(...), (...), (...)>;
                                  searchDocument: PgBuildColumn<(...), (...), (...)>;
                                  solanaWalletId: PgBuildColumn<(...), (...), (...)>;
                                  updatedAt: PgBuildColumn<(...), (...), (...)>;
                                  visibility: PgBuildColumn<(...), (...), (...)>;
                                  walletExternalId: PgBuildColumn<(...), (...), (...)>;
                                  walletId: PgBuildColumn<(...), (...), (...)>;
                                  walletSecretId: PgBuildColumn<(...), (...), (...)>;
                              };
                              dialect: "pg";
                              isAlias: false;
                              name: "ledger_account";
                              schema: "b2b";
                          },
                      >,
                      "enableRLS",
                  >,
                  "createdAt",
              >
              | { direction: "ASC"
              | "DESC"; field: "balance" }
          )[]
        • Optionalpage?: number

          Defaults to 1

        • OptionalpageSize?: number

          Defaults to 100

        • Optionalq?: string

          Case-insensitive substring match on account name or entity name. Whitespace-only values are a no-op.

        • OptionalwalletAddresses?: string[]

          Accounts whose wallet holds any of these addresses, on any chain.

        • OptionalwalletIds?: string[]

          Accounts on any of these wallets (wal_…).

        • OptionalwithoutBalance?: undefined

      Returns Promise<
          {
              ok: true;
              value: {
                  hasNext: boolean;
                  items: {
                      mintfxAddress: string
                      | null;
                      owner: string | null;
                      tokenAccounts: string[];
                  }[];
              };
          },
      >

    • Tags for a page: the scope its query searched (each customer's membership tag, else the collection tag), so an empty page is bustable too, plus the records it projects and the fields that chose or ordered its rows.

      Parameters

      • __namedParameters: {
            customerIds: readonly string[] | undefined;
            fields?: readonly string[];
            records?: readonly string[];
        }

      Returns string[]

    • Edit an account's operator-owned properties: its name, who may debit it, whether other CFX customers can discover it, and the internal note.

      name and notes are nullable on purpose — both are genuinely absent for most accounts, and a field an operator can set but never unset is a trap. null name clears the column back to the Account • • • • 1234 display fallback; null notes drops the key out of the data jsonb rather than storing an empty string, so "has a note" stays a question with one answer.

      customerId is an optional ownership assertion, not a lookup key: pass it to make the write a no-op unless the account belongs to that customer.

      Parameters

      • __namedParameters: {
            customerId?: string;
            data: {
                name?: string | null;
                notes?: string | null;
                permissions?: "ALL" | "ADMIN";
                visibility?: "PRIVATE" | "PUBLIC";
            };
            id: string;
        }

      Returns Promise<
          | {
              ok: true;
              value: {
                  address: Address;
                  balance: BigNumber;
                  createdAt: Date;
                  id: string;
                  name: string;
                  notes?: string;
                  paymentInstrumentId?: string;
                  permissions: "ALL"
                  | "ADMIN";
                  referenceId?: string;
                  tokenAccounts: Partial<Record<"MOVEUSD", { address: Address }>>;
                  updatedAt: Date;
                  visibility: "PRIVATE" | "PUBLIC";
              } & {
                  customerId: string;
                  customerName: string;
                  customerOrganizationId: string;
                  entityDisplayName: string;
                  entityId: string;
                  entityReferenceId: string
                  | null;
                  entityType: "IDENTITY" | "ORGANIZATION";
                  rawName: string | null;
              };
          }
          | { error: ServiceError; ok: false },
      >