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

    Variable utilaWalletViewConst

    utilaWalletView: PgViewWithSelection<
        {
            existing: false;
            isAlias: false;
            name: "utila_wallet";
            schema: "b2b";
            selectedFields: {
                customerId: PgBuildColumn<
                    "utila_wallet",
                    PgIntegerBuilder,
                    {
                        data: number;
                        dataType: "number int32";
                        driverParam: string
                        | number;
                        enumValues: undefined;
                        generated: undefined;
                        hasDefault: false;
                        hasRuntimeDefault: false;
                        identity: undefined;
                        isAutoincrement: false;
                        isPrimaryKey: false;
                        name: string;
                        notNull: false;
                        tableName: "utila_wallet";
                    },
                >;
                kind: PgBuildColumn<
                    "utila_wallet",
                    SetNotNull<PgTextBuilder<[string, ...string[]]>>,
                    {
                        data: string;
                        dataType: "string";
                        driverParam: string;
                        enumValues: undefined;
                        generated: undefined;
                        hasDefault: false;
                        hasRuntimeDefault: false;
                        identity: undefined;
                        isAutoincrement: false;
                        isPrimaryKey: false;
                        name: string;
                        notNull: true;
                        tableName: "utila_wallet";
                    },
                >;
                utilaVaultId: PgBuildColumn<
                    "utila_wallet",
                    SetNotNull<PgIntegerBuilder>,
                    {
                        data: number;
                        dataType: "number int32";
                        driverParam: string | number;
                        enumValues: undefined;
                        generated: undefined;
                        hasDefault: false;
                        hasRuntimeDefault: false;
                        identity: undefined;
                        isAutoincrement: false;
                        isPrimaryKey: false;
                        name: string;
                        notNull: true;
                        tableName: "utila_wallet";
                    },
                >;
                walletId: PgBuildColumn<
                    "utila_wallet",
                    SetNotNull<PgTextBuilder<[string, ...string[]]>>,
                    {
                        data: string;
                        dataType: "string";
                        driverParam: string;
                        enumValues: undefined;
                        generated: undefined;
                        hasDefault: false;
                        hasRuntimeDefault: false;
                        identity: undefined;
                        isAutoincrement: false;
                        isPrimaryKey: false;
                        name: string;
                        notNull: true;
                        tableName: "utila_wallet";
                    },
                >;
            };
        },
    > = ...

    Every Utila wallet CFX knows about, across the three registries that hold one, keyed the way utila_wallet_transaction keys a wallet.

    This is what resolves utila_wallet_transaction.customer_id at ingest: a transfer address carries an infoRef into referencedAddressesInfo, which yields a vaults/{v}/wallets/{w} resource name, and splitting that once (§ 4.12) gives a vault and a wallet id. The vault resolves to utila_vault.id through its utila_id, and every arm below stores that as utila_vault_id. Only backoffice_wallet still reads its wallet id out of data jsonb.

    A wallet absent from all three arms is not an error. Vault-level polling stores rows for wallets CFX does not recognize with customer_id NULL — including wallets created before this sync existed — mirroring solana_account_transaction, which leaves attribution NULL for any address no ledger account owns.

    dbmate owns the DDL: the body below is mirrored by 20261017011916_promoted_columns_view_readers.sql and the .as(sql…) here never runs. securityInvoker is required, not decoration — all three underlying tables have RLS enabled, and without it the view would run with the owner's row visibility and silently bypass the querying role's policies.

    See docs/proposals/UTILA_TRANSACTION_SYNC.md § 3.7.