<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      區塊鏈錢包開發,第三周總結 (貨幣精度計算 超大數運算)

      這周主要做了 ETH錢包:(1)錢包列表展示錢包價值(2)在錢包內發起一個Transation交易 (3)獲取交易詳情

      當前熱錢包部分, 對于以上三個功能最大的需求功能,最大阻礙是精度問題和超大數的的基本運算

      一.錢包價值展示

      參考imToken, imToken主做ETH錢包三年多,相當專業,有太多的地方值得我們學習。

      首頁部分頭部是錢包內主幣和代幣換算成實體貨幣數量的總價值,列表部分是當前錢包內主幣和選中代幣集合,展示了幣的圖標、名稱、數量、兌換成實體貨幣價值。

      關鍵是數量這里:
      ETH 有很多單位,基本使用統計如下:

      單位Unit 以最小單位Wei為基準的進制(Wei  數量) 使用頻率
      Wei 1           wei 經常
      KWei 10 * 3    wei  
      MWei 10 * 6    wei  
      GWei 10 * 9    wei 經常
      microether 10 * 12  wei  
      milliether 10 * 15  wei  
      ether 10 * 18  wei 經常

       

       

       

       

       

       

      二 需要運算的地方:

      發起一筆轉賬時的進制轉換,和gas 費用。

        Gas limit 是用戶愿意為執行某個操作或確認交易支付的最大Gas量(最少21,000) 單位個(即對應的是ETH的個數)

        計算 花費應該   gas fee = Gas Limit * Gas Price

        這個是給礦工的傭金

        第一步就是把gas price 從Gwei 轉為 ETH 再 * limit

        Gas Limit*Gas Price

       eg:  1Gwei≈0.00000002 ETH,所以傭金最少為0.00000002*21000=0.00042ETH

       

       

      (1)用戶輸入轉賬ETH個數 單位:ether    

      和服務端約定上傳一律用最小單位,這里需要做一次進制轉換  即:1 ether = 10 * 18 wei

      如果交易稍大就會超過 iOS 中精度了,更別提運算了。因為有Web3 ,提供 BigDecimal方案處理超大數的精度處理,iOS 這邊,完全可以自己寫超大數的加減乘除,也可以選擇一些成熟的第三 ,這里我使用了一個框架web3swift

             web3swift,完全支持在iOS 客戶端上實施冷錢包,并發起交易的整個過程 通過  Infura 節點(測試/主網)。具體參考(1)上介紹

            所以,上一篇文章,我使用trust keystore 能完成創建錢包,導入錢包,校驗錢包的操作。今天換成web3swift,主要是符合我的需求和持續化的迭代設計。

           至此,超大數,精度浮點數運算 進制轉換使用swift 框架 web3swift來解決

          使用舉例:

      //
      //  FIREnterUnitManager.swift
      //  AkeyWallet
      //
      //  Created by HF on 2018/7/14.
      //  Copyright ? 2018年 Fir.im. All rights reserved.
      //
      
      import Foundation
      import BigInt
      import web3swift
      
      @objc public class FIREnterUnitManager:NSObject {
       
          //從ETH 轉換為 Wei
          public static func getWeiBigStringFrom(ethString:String) throws -> String {
              let eth = Web3.Utils.parseToBigUInt(ethString, units: .eth);//當前是eth
              if (nil == eth) {
                  return ""
              } else {
                  let balString =  Web3.Utils.formatToEthereumUnits(eth!, toUnits: .wei, decimals: 0)
                  return balString!
              }
          }
          //從wei 到 eth
          public static func getETHFrom(weiString:String) throws -> String {
              let weiBig = BigUInt(weiString);
              let balString =  Web3.Utils.formatToEthereumUnits(weiBig!, toUnits: .eth, decimals: 8)
              return balString!;
          }//從當前進制到wei
          public static func getWeiFromUnit(unitString:String,decimal:Int) throws -> String {
              let balance = Web3.Utils.parseToBigUInt(unitString, decimals: decimal)
              let balString =  Web3.Utils.formatToEthereumUnits(balance!, toUnits: .wei, decimals: 8)
              return balString!;
          }//wei乘法
          public static func getMultiWei(wei1:String,wei2:String) throws -> String {
              let weiBig1 = BigUInt(wei1);
              let weiBig2 = BigUInt(wei2);
              let wei = weiBig1! * weiBig2!;
              let balString =  Web3.Utils.formatToEthereumUnits(wei, toUnits: .wei, decimals: 8)
              return balString!;
          }
          //wei加法
          public func getSumWei(wei1:String,wei2:String) throws -> String {
              let weiBig1 = BigUInt(wei1);
              let weiBig2 = BigUInt(wei2);
              let wei = weiBig1! + weiBig2!;
              let balString =  Web3.Utils.formatToEthereumUnits(wei, toUnits: .wei, decimals: 8)
              return balString!;
          }}

      (2)有一些非超大數,比如一些顯示,虛擬幣、實體幣,求和,匯率計算什么的,也可以選擇上面的方法算,但是我的風格是按需處理,不是超大數,就是正常的金融數據運算,自己寫了一個工具類。

            正常的浮點經度進行金融數據運算,會丟精度。蘋果針對浮點型計算時存在精度計算誤差的問題,提供NSDecimalNumber的計算類

            參考(2),自己完善一下邊界處理

            NSDecimalNumber 有 NSRoundingMode 類型,我使用四舍五入類型 NSRoundPlain ,請參考者按需處理

      //
      //  NSDecimalNumber+FIRDeimalTool.h
      //  AkeyWallet
      //
      //  Created by HF on 2018/7/15.
      //  Copyright ? 2018年 Fir.im. All rights reserved.
      //
      
      #import <Foundation/Foundation.h>
      
      typedef NS_ENUM(NSInteger, calculationType) {
          Add,
          Subtract,
          Multiply,
          Divide
      };
      
      @interface NSDecimalNumber (FIRDeimalTool)
      
      //自定義加減乘除
      +(NSDecimalNumber *)aDecimalNumberWithStringOrNumberOrDecimalNumber:(id)stringOrNumber1 type:(calculationType)type anotherDecimalNumberWithStringOrNumberOrDecimalNumber:(id)stringOrNumber2 andDecimalNumberHandler:(NSDecimalNumberHandler *)handler;
      
      //小數比較
      +(NSComparisonResult)aDecimalNumberWithStringOrNumberOrDecimalNumber:(id)stringOrNumber1 compareAnotherDecimalNumberWithStringOrNumberOrDecimalNumber:(id)stringOrNumber2;
      
      /**
       小數位數保留
      
       @param str1 小數
       @param scale 保留位數
       @return 結果
       */
      +(NSString *)stringWithDecimalNumber:(NSDecimalNumber *)str1 scale:(NSInteger)scale;
      
      extern NSComparisonResult StrNumCompare(id str1,id str2);
      
      extern NSDecimalNumber *handlerDecimalNumber(id strOrNum,NSRoundingMode mode,int scale);
      
      
      extern NSComparisonResult FIRCompare(id strOrNum1,id strOrNum2);
      
      //加減乘除
      extern NSDecimalNumber *FIRAdd(id strOrNum1,id strOrNum2);
      extern NSDecimalNumber *FIRSub(id strOrNum1,id strOrNum2);
      extern NSDecimalNumber *FIRMul(id strOrNum1,id strOrNum2);
      extern NSDecimalNumber *FIRDiv(id strOrNum1,id strOrNum2);
      //比大小
      extern NSDecimalNumber *FIRMin(id strOrNum1,id strOrNum2);
      extern NSDecimalNumber *FIRMax(id strOrNum1,id strOrNum2);
      //定義運算結果小數取舍模態
      extern NSDecimalNumber *FIRAdd_handler(id strOrNum1,id strOrNum2,NSRoundingMode mode,int scale);
      extern NSDecimalNumber *FIRSub_handler(id strOrNum1,id strOrNum2,NSRoundingMode mode,int scale);
      extern NSDecimalNumber *FIRMul_handler(id strOrNum1,id strOrNum2,NSRoundingMode mode,int scale);
      extern NSDecimalNumber *FIRDiv_handler(id strOrNum1,id strOrNum2,NSRoundingMode mode,int scale);
      extern NSDecimalNumber *FIRMin_handler(id strOrNum1,id strOrNum2,NSRoundingMode mode,int scale);
      extern NSDecimalNumber *FIRMax_handler(id strOrNum1,id strOrNum2,NSRoundingMode mode,int scale);
      /**
       字符串小數舍去末尾0
       
       @param stringOrNumber 字符串小數/Number/decimalNumer
       @return 舍去末尾0
       */
      +(NSString *)getStringDecimalWithoutEndZero:(id)stringOrNumber;
      
      @end
      //
      //  NSDecimalNumber+FIRDeimalTool.m
      //  AkeyWallet
      //
      //  Created by HF on 2018/7/15.
      //  Copyright ? 2018年 Fir.im. All rights reserved.
      //
      
      #import "NSDecimalNumber+FIRDeimalTool.h"
      
      @implementation NSDecimalNumber (FIRDeimalTool)
      
      +(NSDecimalNumber *)aDecimalNumberWithStringOrNumberOrDecimalNumber:(id)stringOrNumber1 type:(calculationType)type anotherDecimalNumberWithStringOrNumberOrDecimalNumber:(id)stringOrNumber2 andDecimalNumberHandler:(NSDecimalNumberHandler *)handler{
          if (!stringOrNumber2 || !stringOrNumber1) {
              NSAssert(NO, @"輸入正確類型");
              return nil;
          }
          NSDecimalNumber *one;
          NSDecimalNumber *another;
          NSDecimalNumber *returnNum;
          if ([stringOrNumber1 isKindOfClass:[NSString class]]) {
              one = [NSDecimalNumber decimalNumberWithString:stringOrNumber1];
          }else if([stringOrNumber1 isKindOfClass:[NSDecimalNumber class]]){
              one = stringOrNumber1;
          }else if ([stringOrNumber1 isKindOfClass:[NSNumber class]]){
              one = [NSDecimalNumber decimalNumberWithDecimal:[stringOrNumber1 decimalValue]];
          }else{
              NSAssert(NO, @"輸入正確類型");
              return nil;
          }
          
          if ([stringOrNumber2 isKindOfClass:[NSString class]]) {
              another = [NSDecimalNumber decimalNumberWithString:stringOrNumber2];
          }else if([stringOrNumber2 isKindOfClass:[NSDecimalNumber class]]){
              another = stringOrNumber2;
          }else if ([stringOrNumber2 isKindOfClass:[NSNumber class]]){
              another = [NSDecimalNumber decimalNumberWithDecimal:[stringOrNumber2 decimalValue]];
          }else{
              NSAssert(NO, @"輸入正確類型");
              return nil;
          }
          //排除NaN
          if (isnan(one.doubleValue) || isinf(one.doubleValue)) one = [NSDecimalNumber decimalNumberWithString:@"0"];
          if (isnan(another.doubleValue) || isinf(another.doubleValue)) another = [NSDecimalNumber decimalNumberWithString:@"0"];
          //
          if (type == Add) {
              returnNum = [one decimalNumberByAdding:another];
          }else if (type == Subtract){
              returnNum  = [one decimalNumberBySubtracting:another];
          }else if (type == Multiply){
              returnNum = [one decimalNumberByMultiplyingBy:another];
          }else if (type == Divide){
              
              if ([NSDecimalNumber aDecimalNumberWithStringOrNumberOrDecimalNumber:another compareAnotherDecimalNumberWithStringOrNumberOrDecimalNumber:@(0)] == 0) {
                  returnNum = nil;
              }else
                  returnNum = [one decimalNumberByDividingBy:another];
          }else{
              returnNum = nil;
          }
          if (returnNum) {
              if (handler) {
                  return [returnNum decimalNumberByRoundingAccordingToBehavior:handler];
              }else{
                  return returnNum;
              }
          }else{
              NSAssert(NO, @"輸入正確類型");
              return nil;
          }
      }
      
      +(NSComparisonResult)aDecimalNumberWithStringOrNumberOrDecimalNumber:(id)stringOrNumber1 compareAnotherDecimalNumberWithStringOrNumberOrDecimalNumber:(id)stringOrNumber2{
          if (!stringOrNumber2 || !stringOrNumber1) {
              NSAssert(NO, @"輸入正確類型");
              return -404;
          }
          NSDecimalNumber *one;
          NSDecimalNumber *another;
          if ([stringOrNumber1 isKindOfClass:[NSString class]]) {
              one = [NSDecimalNumber decimalNumberWithString:stringOrNumber1];
          }else if([stringOrNumber1 isKindOfClass:[NSDecimalNumber class]]){
              one = stringOrNumber1;
          }else if ([stringOrNumber1 isKindOfClass:[NSNumber class]]){
              one = [NSDecimalNumber decimalNumberWithDecimal:[stringOrNumber1 decimalValue]];
          }else{
              NSAssert(NO, @"輸入正確類型");
              return -404;
          }
          
          if ([stringOrNumber2 isKindOfClass:[NSString class]]) {
              another = [NSDecimalNumber decimalNumberWithString:stringOrNumber2];
          }else if([stringOrNumber2 isKindOfClass:[NSDecimalNumber class]]){
              another = stringOrNumber2;
          }else if ([stringOrNumber2 isKindOfClass:[NSNumber class]]){
              another = [NSDecimalNumber decimalNumberWithDecimal:[stringOrNumber2 decimalValue]];
          }else{
              NSAssert(NO, @"輸入正確類型");
              return -404;
          }
          //排除NaN
          if (isnan(one.doubleValue) || isinf(one.doubleValue)) one = [NSDecimalNumber decimalNumberWithString:@"0"];
          if (isnan(another.doubleValue) || isinf(another.doubleValue)) another = [NSDecimalNumber decimalNumberWithString:@"0"];
          //
          return [one compare:another];
      }
      
      +(NSString *)stringWithDecimalNumber:(NSDecimalNumber *)str1 scale:(NSInteger)scale{
          if (!str1) {
              return @"";
          }
          NSString *str = [NSString stringWithFormat:@"%@",str1];
          if (str && str.length) {
              if ([str rangeOfString:@"."].length == 1) {//有小數點
                  NSArray *arr = [str componentsSeparatedByString:@"."];
                  if (scale > 0) {
                      NSInteger count = [arr[1] length];
                      for (NSInteger i = count; i<scale; i++) {
                          str = [str stringByAppendingString:@"0"];
                      }
                      return str;
                  }else{
                      return arr[0];
                  }
              }else{//沒有小數點
                  if ([str rangeOfString:@"."].length) {
                      return @"";
                  }
                  if (scale > 0) {
                      str = [str stringByAppendingString:@"."];
                      for (int i = 0; i<scale; i++) {
                          str = [str stringByAppendingString:@"0"];
                      }
                      return str;
                  }else{
                      return str;
                  }
              }
          }else{
              return @"";
          }
      }
      
      NSComparisonResult StrNumCompare(id str1,id str2){
          return [NSDecimalNumber aDecimalNumberWithStringOrNumberOrDecimalNumber:str1 compareAnotherDecimalNumberWithStringOrNumberOrDecimalNumber:str2];
      }
      
      NSDecimalNumber *handlerDecimalNumber(id strOrNum,NSRoundingMode mode,int scale){
          if (!strOrNum || strOrNum == nil) {
              NSLog(@"輸入正確類型");
              return nil;
          }else{
              NSDecimalNumber *one;
              if ([strOrNum isKindOfClass:[NSString class]]) {
                  one = [NSDecimalNumber decimalNumberWithString:strOrNum];
              }else if([strOrNum isKindOfClass:[NSDecimalNumber class]]){
                  one = strOrNum;
              }else if ([strOrNum isKindOfClass:[NSNumber class]]){
                  one = [NSDecimalNumber decimalNumberWithDecimal:[strOrNum decimalValue]];
              }else{
                  NSLog(@"輸入正確的類型");
                  return nil;
              }
              //排除NaN
              if (isnan(one.doubleValue) || isinf(one.doubleValue)) one = [NSDecimalNumber decimalNumberWithString:@"0"];
              //
              NSDecimalNumberHandler *handler = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:mode scale:scale raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:NO];
              return  [one decimalNumberByRoundingAccordingToBehavior:handler];
          }
      }
      
      
      NSDecimalNumber *FIRAdd(id strOrNum1,id strOrNum2){
          return [NSDecimalNumber aDecimalNumberWithStringOrNumberOrDecimalNumber:strOrNum1 type:Add anotherDecimalNumberWithStringOrNumberOrDecimalNumber:strOrNum2 andDecimalNumberHandler:nil];
      }
      
      NSDecimalNumber *FIRSub(id strOrNum1,id strOrNum2){
          return [NSDecimalNumber aDecimalNumberWithStringOrNumberOrDecimalNumber:strOrNum1 type:Subtract anotherDecimalNumberWithStringOrNumberOrDecimalNumber:strOrNum2 andDecimalNumberHandler:nil];
      }
      NSDecimalNumber *FIRMul(id strOrNum1,id strOrNum2){
          return [NSDecimalNumber aDecimalNumberWithStringOrNumberOrDecimalNumber:strOrNum1 type:Multiply anotherDecimalNumberWithStringOrNumberOrDecimalNumber:strOrNum2 andDecimalNumberHandler:nil];
      }
      
      NSDecimalNumber *FIRDiv(id strOrNum1,id strOrNum2){
          return [NSDecimalNumber aDecimalNumberWithStringOrNumberOrDecimalNumber:strOrNum1 type:Divide anotherDecimalNumberWithStringOrNumberOrDecimalNumber:strOrNum2 andDecimalNumberHandler:nil];
      }
      
      NSComparisonResult FIRCompare(id strOrNum1,id strOrNum2){
          return [NSDecimalNumber aDecimalNumberWithStringOrNumberOrDecimalNumber:strOrNum1 compareAnotherDecimalNumberWithStringOrNumberOrDecimalNumber:strOrNum2];
      }
      
      NSDecimalNumber *FIRMin(id strOrNum1,id strOrNum2){
          return FIRCompare(strOrNum1, strOrNum2) > 0 ? strOrNum2 : strOrNum1;
      }
      NSDecimalNumber *FIRMax(id strOrNum1,id strOrNum2){
          return FIRCompare(strOrNum1, strOrNum2) > 0 ? strOrNum1 : strOrNum2;
      }
      NSDecimalNumber *FIRAdd_handler(id strOrNum1,id strOrNum2,NSRoundingMode mode,int scale){
          return handlerDecimalNumber(FIRAdd(strOrNum1, strOrNum2), mode, scale);
      }
      NSDecimalNumber *FIRSub_handler(id strOrNum1,id strOrNum2,NSRoundingMode mode,int scale){
          return handlerDecimalNumber(FIRSub(strOrNum1, strOrNum2), mode, scale);
      }
      NSDecimalNumber *FIRMul_handler(id strOrNum1,id strOrNum2,NSRoundingMode mode,int scale){
          return handlerDecimalNumber(FIRMul(strOrNum1, strOrNum2), mode, scale);
      }
      NSDecimalNumber *FIRDiv_handler(id strOrNum1,id strOrNum2,NSRoundingMode mode,int scale){
          return handlerDecimalNumber(FIRDiv(strOrNum1, strOrNum2), mode, scale);
      }
      
      
      NSDecimalNumber *FIRMin_handler(id strOrNum1,id strOrNum2,NSRoundingMode mode,int scale){
          return handlerDecimalNumber(FIRMin(strOrNum1, strOrNum2), mode, scale);
      }
      NSDecimalNumber *FIRMax_handler(id strOrNum1,id strOrNum2,NSRoundingMode mode,int scale){
          return handlerDecimalNumber(FIRMax(strOrNum1, strOrNum2), mode, scale);
      }
      
      +(NSString *)getStringDecimalWithoutEndZero:(id)stringOrNumber
      {
          NSDecimalNumber *num = FIRAdd(stringOrNumber, @"0");
          return [NSString stringWithFormat:@"%@",num];
      }
      
      @end

       

       

      參考:

      (1) https://github.com/BANKEX/web3swift

      (2)https://github.com/CodeJCSON/NSDecimalNumber 

       

       

       

      待續

      posted on 2018-07-17 23:20  ACM_Someone like you  閱讀(880)  評論(0)    收藏  舉報

      導航

      主站蜘蛛池模板: 尤物视频色版在线观看| 日韩黄色av一区二区三区| 亚洲AV午夜电影在线观看| 中文字幕热久久久久久久| 美女胸18下看禁止免费视频| 尤物yw193无码点击进入| 老少配老妇老熟女中文普通话| 亚洲综合网国产精品一区| 亚洲欧美综合精品成| 国产精品乱码一区二区三| 久久精品a亚洲国产v高清不卡| 二连浩特市| 久久婷婷五月综合色丁香花| 亚洲欧美日韩成人综合一区| 免费无码一区无码东京热| 国产女人在线视频| 亚洲综合区激情国产精品| 亚洲欧美在线看片AI| 99久久99这里只有免费费精品| 亚洲av色夜色精品一区| 国产精品区一二三四久久| 国产欧美日韩高清在线不卡| 丰满无码人妻热妇无码区| 亚洲永久一区二区三区在线| 亚洲欧美偷国产日韩| 在线无码中文字幕一区| 年日韩激情国产自偷亚洲| 国产亚洲精品VA片在线播放| 精品亚洲国产成人| 熟女人妻精品一区二区视频| 国模一区二区三区私拍视频| 国产a在视频线精品视频下载| 亚洲男女羞羞无遮挡久久丫 | 欧洲无码一区二区三区在线观看| 精品午夜福利无人区乱码| 色狠狠色婷婷丁香五月| av深夜免费在线观看| 日韩有码中文字幕国产| 国产a在亚洲线播放| 国产精品二区中文字幕| 日韩av一区二区三区不卡|