<commit_before>import { Schema, Document, model, DocumentQuery } from "mongoose";
import { CoinModel, ICoinModel } from "./coin";
import { TransformOptions } from "../types/TransformOptions";
import { partition } from "../utils/partition";
import { IWalletModel } from "./wallet";
import { TransactionModel } from "./transaction";
import { TransformableModel } from "../types/TransformableModel";
import { LoggifyObject } from "../decorators/Loggify";


interface IWalletAddress {
  wallet: Schema.Types.ObjectId;
  address: string;
  chain: string;
  network: string;
}

export type IWalletAddressQuery = { [key in keyof IWalletAddress]?: any } &
  DocumentQuery<IWalletAddress, Document>;

type IWalletAddressDoc = IWalletAddress & Document;
type IWalletAddressDocModel = IWalletAddressDoc & TransformableModel<IWalletAddressDoc>;

export type UpdateCoinsParams = {
  wallet: IWalletModel;
  addresses: string[];
};

interface IWalletAddressModel extends IWalletAddressDocModel {
  updateCoins: (params: UpdateCoinsParams) => Promise<any>;
  getUpdateCoinsObj: (params: UpdateCoinsParams) => any;
}

const WalletAddressSchema = new Schema({
  wallet: Schema.Types.ObjectId,
  address: String,
  chain: String,
  network: String
});

WalletAddressSchema.index({ address: 1, wallet: 1 });

WalletAddressSchema.statics._apiTransform = function (
  walletAddress: { address: string },
  options: TransformOptions
) {
  let transform = {
    address: walletAddress.address
  };
  if (options && options.object) {
    return transform;
  }
  return JSON.stringify(transform);
};

WalletAddressSchema.statics.getUpdateCoinsObj = function (
  params: UpdateCoinsParams
) {
  const { wallet, addresses } = params;
  const { chain, network } = wallet;

  let walletUpdates = addresses.map((address: string) => {
    return {
      updateOne: {
        filter: { wallet: wallet._id, address: address },
        update: { wallet: wallet._id, address: address, chain, network },
        upsert: true
      }
    };
  });

  let coinUpdates = addresses.map((address: string) => {
    return {
      updateMany: {
        filter: { chain, network, address },
        update: {
          $addToSet: { wallets: wallet._id }
        }
      }
    };
  });

  return {
    walletUpdates,
    coinUpdates
  };
}

WalletAddressSchema.statics.updateCoins = async function (
  params: { walletUpdates: any, coinUpdates: any } & UpdateCoinsParams
) {
  const { walletUpdates, coinUpdates, wallet } = params;
  const { chain, network } = wallet;

  let walletUpdateBatches = partition(walletUpdates, 500);
  let coinUpdateBatches = partition(coinUpdates, 500);

  return new Promise(async resolve => {
    await Promise.all(
      walletUpdateBatches.map(walletUpdateBatch => {
        return WalletAddressModel.collection.bulkWrite(walletUpdateBatch, { ordered: false });
      })
    );

    await Promise.all(
      coinUpdateBatches.map(coinUpdateBatch => {
        return CoinModel.collection.bulkWrite(coinUpdateBatch, {
          ordered: false
        });
      })<commit_msg>Fixing issue with updateCoins<commit_after>import { Schema, Document, model, DocumentQuery } from "mongoose";
import { CoinModel, ICoinModel } from "./coin";
import { TransformOptions } from "../types/TransformOptions";
import { partition } from "../utils/partition";
import { IWalletModel } from "./wallet";
import { TransactionModel } from "./transaction";
import { TransformableModel } from "../types/TransformableModel";
import { LoggifyObject } from "../decorators/Loggify";


interface IWalletAddress {
  wallet: Schema.Types.ObjectId;
  address: string;
  chain: string;
  network: string;
}

export type IWalletAddressQuery = { [key in keyof IWalletAddress]?: any } &
  DocumentQuery<IWalletAddress, Document>;

type IWalletAddressDoc = IWalletAddress & Document;
type IWalletAddressDocModel = IWalletAddressDoc & TransformableModel<IWalletAddressDoc>;

export type UpdateCoinsParams = {
  wallet: IWalletModel;
  addresses: string[];
};

interface IWalletAddressModel extends IWalletAddressDocModel {
  updateCoins: (params: UpdateCoinsParams) => Promise<any>;
  getUpdateCoinsObj: (params: UpdateCoinsParams) => any;
}

const WalletAddressSchema = new Schema({
  wallet: Schema.Types.ObjectId,
  address: String,
  chain: String,
  network: String
});

WalletAddressSchema.index({ address: 1, wallet: 1 });

WalletAddressSchema.statics._apiTransform = function (
  walletAddress: { address: string },
  options: TransformOptions
) {
  let transform = {
    address: walletAddress.address
  };
  if (options && options.object) {
    return transform;
  }
  return JSON.stringify(transform);
};

WalletAddressSchema.statics.getUpdateCoinsObj = function (
  params: UpdateCoinsParams
) {
  const { wallet, addresses } = params;
  const { chain, network } = wallet;

  let walletUpdates = addresses.map((address: string) => {
    return {
      updateOne: {
        filter: { wallet: wallet._id, address: address },
        update: { wallet: wallet._id, address: address, chain, network },
        upsert: true
      }
    };
  });

  let coinUpdates = addresses.map((address: string) => {
    return {
      updateMany: {
        filter: { chain, network, address },
        update: {
          $addToSet: { wallets: wallet._id }
        }
      }
    };
  });

  return {
    walletUpdates,
    coinUpdates
  };
}

WalletAddressSchema.statics.updateCoins = async function (
  params: UpdateCoinsParams
) {
  const { wallet } = params;
  const updates = WalletAddressModel.getUpdateCoinsObj(params);
  const { walletUpdates, coinUpdates } = updates;
  const { chain, network } = wallet;

  let walletUpdateBatches = partition(walletUpdates, 500);
  let coinUpdateBatches = partition(coinUpdates, 500);

  return new Promise(async resolve => {
    await Promise.all(
      walletUpdateBatches.map(walletUpdateBatch => {
        return WalletAddressModel.collection.bulkWrite(walletUpdateBatch, { ordered: false });
      })
    );

    await Promise.all(
      coinUpdateBatches.map(coinUpdateBatch => {
        return CoinModel.collection.bulkWrite(coinUpdateBatch, {
          ordered: false
        });
      })
{'fraction_non_alphanumeric': 0.1145445720757159, 'fraction_numerical': 0.0025885779000161787, 'mean_word_length': 3.7444359171143513, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1783680', 'n_tokens_mistral': 1800, 'n_tokens_neox': 1815, 'n_words': 426}