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

    Variable utilaWalletViewConst

    utilaWalletView: PgViewWithSelection<
        "utila_wallet",
        false,
        {
            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";
                },
            >;
            vaultId: 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";
                },
            >;
            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 exactly the (vault_id, wallet_id) pair two of the three arms below already store as columns. Only backoffice_wallet still digs into data jsonb, because that is where it keeps its Utila reference.

    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 20260831143800_utila_transaction_sync.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.