Repository: CryptoBlades/cryptoblades
File: frontend/src/store/store.ts (TypeScript)

Code before:
    },
    async getAccountWeapons({state}) {
      if(!state.defaultAccount) return;
      const numberOfWeapons = parseInt(await state.contracts().Weapons!.methods.balanceOf(state.defaultAccount).call(defaultCallOptions(state)), 10);
      return await Promise.all(
        [...Array(numberOfWeapons).keys()]
          .map(async (_, i) => Number(await state.contracts().Weapons!.methods.tokenOfOwnerByIndex(state.defaultAccount!, i).call(defaultCallOptions(state))))
      );
    },
    async setupCharacterRenames({ dispatch }) {
      const ownedCharacterIds = await dispatch('getAccountCharacters');
      const ownedGarrisonCharacterIds = await dispatch('getAccountGarrisonCharacters');
      ownedCharacterIds.push(...ownedGarrisonCharacterIds);

      for (const charId of ownedCharacterIds) {
        dispatch('fetchCharacterRename', charId);
      }
    },
    async setupCharactersWithIdsRenames({ dispatch }, characterIds: string[]) {
      for (const charId of characterIds) {
        dispatch('fetchCharacterRename', charId);
      }
    },
    async fetchCharacterRename({ state, commit }, characterId: number) {
      const renameString = await state.contracts().CharacterRenameTagConsumables!.methods
        .getCharacterRename(characterId)
        .call(defaultCallOptions(state));
      if(renameString !== '' && state.characterRenames[characterId] !== renameString){
        commit('updateCharacterRename', { characterId, renameString });
      }
    },
    async setupCharacterCosmetics({ dispatch }) {
      const ownedCharacterIds = await dispatch('getAccountCharacters');
      const ownedGarrisonCharacterIds = await dispatch('getAccountGarrisonCharacters');
      ownedCharacterIds.push(...ownedGarrisonCharacterIds);

      for (const charId of ownedCharacterIds) {
        dispatch('fetchCharacterCosmetic', charId);
      }
    },
    async fetchCharacterCosmetic({ state, commit }, characterId: number) {
      const characterCosmetic = await state.contracts().CharacterCosmetics!.methods
        .getCharacterCosmetic(characterId)
        .call(defaultCallOptions(state));
      if(state.characterCosmetics[characterId] !== characterCosmetic){
        commit('updateCharacterCosmetic', { characterId, characterCosmetic });
      }
    },
    async mintCharacter({ state, dispatch }, approveMintSlippage: boolean) {
      if(!state.defaultAccount) return;
      const slippageMultiplier = approveMintSlippage ? 1.05 : 1;

Review comment (bug):
This will need updating to handle the pay first, pop second nature of the flow. Would like to note we will need some visual feedback for the player to know they have a weapon waiting if for whatever reason the payment succeeds but they cancel/fail the claim. This is made more complicated by the fact that the seeds are separated out by amounts. Not sure what's the best approach there. Calling hasSeed 10 times may be a little slow for the RPC to respond, but including that behavior in the solidity function will add to size. I don't have a preference.

Worth mentioning this behavior will have to be updated in the bazaar repo too. (but at least there it's 1 shield at a time)

Code after:
      await approveFee(
        state.contracts().CryptoBlades!,
        state.contracts().SkillToken,
        state.defaultAccount,
        state.skillRewards,
        defaultCallOptions(state),
        defaultCallOptions(state),
        cryptoBladesMethods => cryptoBladesMethods.getMintCharacterFee(),
        { feeMultiplier: slippageMultiplier, allowInGameOnlyFunds: false }
      );

      await state.contracts().CryptoBlades!.methods.mintCharacter().send(defaultCallOptions(state));

      await Promise.all([
        dispatch('combat/fetchFightRewardSkill'),
        dispatch('combat/fetchFightRewardXp'),
        dispatch('setupCharacterStaminas')
      ]);
    },

    async hasWeaponsToClaim({ state }) {
      const {CryptoBlades} = state.contracts();
      if (!CryptoBlades || !state.defaultAccount) return;

      const USERVAR_CLAIM_WEAPON_DATA = await CryptoBlades.methods.USERVAR_CLAIM_WEAPON_DATA().call(defaultCallOptions(state));

      return !!+await CryptoBlades.methods.userVars(state.defaultAccount, USERVAR_CLAIM_WEAPON_DATA).call(defaultCallOptions(state));
    },

    async quantityOfWeaponsToClaim({ state }) {
      const {CryptoBlades} = state.contracts();
      if (!CryptoBlades || !state.defaultAccount) return;

      const USERVAR_CLAIM_WEAPON_DATA = await CryptoBlades.methods.USERVAR_CLAIM_WEAPON_DATA().call(defaultCallOptions(state));

      const claimWeaponData = +await CryptoBlades.methods.userVars(state.defaultAccount, USERVAR_CLAIM_WEAPON_DATA).call(defaultCallOptions(state));
      return Number(BigInt(claimWeaponData) >> BigInt(32));
    },

    async claimWeapons({ state, dispatch }) {
      const {CryptoBlades} = state.contracts();
      if (!CryptoBlades || !state.defaultAccount) return;

      await CryptoBlades.methods.mintWeapon().send({from: state.defaultAccount, gasPrice: getGasPrice()});

      await Promise.all([
        dispatch('fetchSkillBalance'),
        dispatch('combat/fetchFightRewardSkill'),
        dispatch('updateWeaponIds'),
        dispatch('setupWeaponDurabilities'),
        dispatch('specialWeaponsManager/fetchShardsSupply')