程序員的自我救贖---12.2.2: 虛擬幣交易平臺(區塊鏈) 中 【開發交易所】 12.2.1: 虛擬幣交易平臺(區塊鏈) 上【發行區塊鏈代幣】 【發行區塊鏈代幣】

《前言》html

(一) Winner2.0 框架基礎分析前端

(二)PLSQL報表系統數據庫

(三)SSO單點登陸前端框架

(四) 短信中心與消息中心框架

(五)錢包系統數據庫設計

(六)GPU支付中心ide

(七)權限系統post

(八)監控系統區塊鏈

(九)會員中心網站

(十) APP版本控制系統

(十一)Winner前端框架與RPC接口規範講解

(十二)上層應用案例

(十三)總結

 

 

虛擬幣交易平臺(區塊鏈) 中 【開發交易所】

 

對於,若是沒有看上一篇文章的,建議先看一下上一篇文章瞭解如何發行一個區塊鏈代幣: 12.2.1: 虛擬幣交易平臺(區塊鏈) 上【發行區塊鏈代幣】

 

首先咱們要知道一個概念,雖然區塊鏈是去中心化的,可是交易所倒是中心化的。這也是爲何區塊鏈技術被吹捧的那麼厲害,卻仍是又發生那麼多比特幣、萊特幣被盜事件。

在咱們國家,去年(2017年)9月4號以前是沒有明確的法律法規說不容許作ICO,也沒有明確指出不容許作區塊鏈代幣交易所。 直到去年9月4號七部委聯合發文,比特幣、萊特幣等虛擬幣也應聲降價,以後國內全部交易所基本都關了。

 

這裏我引用一下百度上的解釋:

 

公告指出,代幣發行融資中使用的代幣或「虛擬貨幣」不禁貨幣當局發行,不具備法償性與強制性等貨幣屬性,不具備與貨幣等同的法律地位,不能也不該做爲貨幣在市場上流通使用。

公告中代表:任何組織和我的不得非法從事代幣發行融資活動,各金融機構和非銀行支付機構不得開展與代幣發行融資交易相關的業務。

 

 

咱們要知道,比特幣、萊特幣各類代幣並不等於區塊鏈,因此各國在法律法規對於比特幣和區塊是兩種態度,一方面打壓比特幣、萊特幣這種代幣,一方面又支持區塊鏈技術的發展。

 

這裏我也呼籲一下,但願你們不要去從事ICO非法融資,這種錢說不定有命賺,沒命花。

 

===================================================華麗的分割線=======================================

 

回到正題,咱們知道區塊鏈,是經過記帳來確認交易,而記帳是記載在區塊上。拿比特幣來講每10分鐘纔出一個區塊6個區塊才確認一筆交易,這個過程是很是慢的。

因此雖然叫"比特幣" 它卻沒有像咱們平時網銀轉帳那樣的及時性。 這就衍生出了交易所,而交易所是中心化的,也就是服務端的數據庫操做。

 

(如今有人研究去中心化的交易所,可是目前尚未很好解決各類區塊鏈之間轉帳,因此去中心化的交易所目前尚未落地)

 

說道這裏就好作,網站這種東西,咱們平時真的是作太多了。說作網站,確定先從數據庫提及,由於咱們的項目基於Winner2.0 框架,因此這裏咱們會省去不少環節,好比用戶,權限等。不清楚的就看我前面的博客吧。

 

 

 

 

 

 

 

 

 

 ==========================================華麗的分割線==============================================================

 

最重要的就以上五張表了,咱們來簡單分析一下這五張表, 咱們先看看前端的UI界面圖:

 

 

 

 

 這樣就一目瞭然知道各個表是幹什麼用的:

 

 

數字貨幣表:存儲當前平臺能夠交易的數字代幣,就是左上角的「比特幣」,「萊特幣」

貨幣動態表:保存該數字代幣的價格浮動信息,好比比特幣的今日最高價,價格走勢圖。

委託交易表:簡單來講就是咱們的掛單信息表,像「個人掛單」,還有右側的委託信息,都在張表。

撮合信息表:撮合簡單來講就是好比有人出10塊賣,有人出100塊買,自己價格是不對應的,可是咱們認定出100塊的人更願意出10塊買,因此咱們促成他們交易。

                     最終他們會在撮合機制下,以10塊的價格達成交易。 而撮合信息表本質來講就是「成交信息表」,好比左側的成交記錄。

 

 

 

==========================================================華麗的分割線================================================

 

因爲上一篇文章 【發行區塊鏈代幣】 這篇文章不少人說我實在寫的太長了。

 

因此今天這一篇咱們直接簡單粗暴一點。看完了數據庫核心的四張表,我來看看核心的代碼。

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Winner.Balance.Facade;
using Winner.Balance.GlobalCurrency;
using Winner.DCTS.DataAccess;
using Winner.DCTS.Entities;
using Winner.DCTS.Entities.enums;
using Winner.Framework.Core.Facade;
using Winner.Framework.Utils;

namespace Winner.DCTS.Facade
{
    public class MatchTransfer : FacadeBase
    {
        private eBankTransaction EBankTransaction { get; set; }
        private Tdct_Match daMatch { get; set; }

        public bool DoTransfer(Tdct_Match match)
        {
            daMatch = match;
            
            //開啓事務
            BeginTransaction();

            //關聯事務
            EBankTransaction = Transfer.GeteBankTransaction(); 

            //出售者把幣轉到購買者
            if (!SellToBuy())
            {
                Rollback(); //回滾事務

                UpdateFail(this.PromptInfo.MessageStack); 
                return false;
            }
            //購買者把錢轉到出售者 + 手續費
            if (!BuyToSell())
            {
                Rollback();
                UpdateFail(this.PromptInfo.MessageStack);
                return false;
            }
            daMatch.TransferId = this.EBankTransaction;

            //撮合成功時修改撮合信息表狀態
            if (!UpdateSuccess())
            {
                Rollback();
                return false;
            }

            //解除代幣以及人名幣鎖定
            if (!UnFreeze())
            {
                Rollback();
                return false;
            }

           //同步代幣動態交易信息
            if (!SyncDynamice())
            {
                Rollback();
                return false;
            }
            Commit();
            return true;
        }

        //出售者把幣轉到購買者
        private bool SellToBuy()
        {
            BeginTransaction();
            Currency currency = new Currency(CurrencyType.RMB, daMatch.BuyCount);
            UserPurse sellPurse = UserPurseProvider.Get(daMatch.SellUserId, daMatch.SellCurrency);
            UserPurse buyPurse = UserPurseProvider.Get(daMatch.BuyUserId, daMatch.SellCurrency);
            Transfer transfer = new Transfer(EBankTransaction);
            transfer.ReferenceTransactionFrom(this.Transaction);
            //若是買和賣都是同一我的則須要用轉到系統用戶再轉入
            if (daMatch.SellUserId == daMatch.BuyUserId)
            {
                //系統用戶錢包
                UserPurse transitPurse = UserPurseProvider.Get(AppConfig.TransitUserId, daMatch.SellCurrency);
                if (!transfer.DoTransferAndUnFreeze(sellPurse, transitPurse, currency, (int)TransferReson.出售者轉入購買者, "出售貨幣中轉出帳", daMatch.SellFreezeId, "購買貨幣中轉入帳"))
                {
                    Rollback();
                    Alert("出售者轉中轉錢包失敗!", transfer.PromptInfo);
                    return false;
                }
                if (!transfer.DoTransfer(transitPurse, buyPurse, currency, (int)TransferReson.出售者轉入購買者, "出售貨幣中轉出帳", "購買貨幣中轉入帳"))
                {
                    Rollback();
                    Alert("中轉者轉購買者失敗!", transfer.PromptInfo);
                    return false;
                }
            }
            else
            {
                if (!transfer.DoTransferAndUnFreeze(sellPurse, buyPurse, currency, (int)TransferReson.出售者轉入購買者, "出售貨幣出帳", daMatch.SellFreezeId, "購買貨幣入帳"))
                {
                    Rollback();
                    Alert("出售者轉購買者失敗!", transfer.PromptInfo);
                    return false;
                }
            }
            Commit();
            return true;
        }


        //購買者把錢轉到出售者 + 手續費
        private bool BuyToSell()
        {
            BeginTransaction();
            Currency currency = new Currency(CurrencyType.RMB, daMatch.Amount);
            UserPurse buyPurse = UserPurseProvider.Get(daMatch.BuyUserId, daMatch.BuyCurrency);
            UserPurse sellPurse = UserPurseProvider.Get(daMatch.SellUserId, daMatch.BuyCurrency);
            //收取手續費

            Transfer transfer = new Transfer(EBankTransaction);
            transfer.ReferenceTransactionFrom(this.Transaction);
            //若是買和賣都是同一我的則須要用轉到系統用戶再轉入
            if (daMatch.BuyUserId == daMatch.SellUserId)
            {
                UserPurse transitPurse = UserPurseProvider.Get(AppConfig.TransitUserId, daMatch.BuyCurrency);
                if (!transfer.DoTransferAndUnFreeze(buyPurse, transitPurse, currency, (int)TransferReson.購買者轉入出售者, "購買貨幣中轉付款", daMatch.BuyFreezeId, "出售貨幣中轉入帳"))
                {
                    Rollback();
                    Alert("購買者轉中轉者失敗!", transfer.PromptInfo);
                    return false;
                }
                if (!transfer.DoTransfer(transitPurse, sellPurse, currency, (int)TransferReson.購買者轉入出售者, "購買貨幣中轉付款", "出售貨幣中轉入帳"))
                {
                    Rollback();
                    Alert("中轉者轉出售者失敗!", transfer.PromptInfo);
                    return false;
                }
            }
            else
            {
                if (!transfer.DoTransferAndUnFreeze(buyPurse, sellPurse, currency, (int)TransferReson.購買者轉入出售者, "購買貨幣付款", daMatch.BuyFreezeId, "出售貨幣入帳"))
                {
                    Rollback();
                    Alert("購買者轉出售者失敗!", transfer.PromptInfo);
                    return false;
                }
            }

            if (daMatch.Fee <= 0)
            {
                Commit();
                return true;
            }
            UserPurse feePurse = UserPurseProvider.Get(AppConfig.SystemUserId, daMatch.BuyCurrency);
            Currency feeCurrency = new Currency(feePurse.CurrencyType, daMatch.Fee);
            if (!transfer.DoTransfer(sellPurse, feePurse, feeCurrency, (int)TransferReson.收取出售者手續費, "收取出售者手續費"))
            {
                Rollback();
                Alert("收取出售者手續費失敗!", transfer.PromptInfo);
                return false;
            }
            Commit();
            return true;
        }

        //修改撮合成功信息
        private bool UpdateSuccess()
        {
            daMatch.ReferenceTransactionFrom(this.Transaction);
            if (!daMatch.UpdateTransferSuccess(daMatch.MatchId, daMatch.TransferId.Value))
            {
                Alert("修改撮合歷史成功時發現失敗", daMatch.PromptInfo);
                return false;
            }
            return true;
        }


        //修改撮合失敗信息
        private bool UpdateFail(string remarks)
        {
            Tdct_Match match = new Tdct_Match();
            if (!daMatch.UpdateTransferFail(daMatch.MatchId, remarks))
            {
                Alert("修改撮合歷史成功時發現失敗", daMatch.PromptInfo);
                return false;
            }
            return true;
        }


        //解除掛單的代幣鎖定
        public bool UnFreeze()
        {
            Tdct_EntrustCollection daEntrustColl = new Tdct_EntrustCollection();
            daEntrustColl.ReferenceTransactionFrom(this.Transaction);
            daEntrustColl.ListWaitRevokeRedundant(daMatch.SellEntrust, daMatch.BuyEntrust);
            Log.Info("解凍冗餘[{0}筆]:", daEntrustColl.Count);
            if (daEntrustColl.Count <= 0)
            {
                return true;
            }
            foreach (Tdct_Entrust item in daEntrustColl)
            {
                Log.Info("[{0}]解凍就緒", item.Id);
                decimal amount = item.EAmount - item.TAmount;
                Currency currency = new Currency(CurrencyType.RMB, amount);
                Log.Info("[{0}]委託剩餘解凍{1}金額", item.Id, amount);
                UserPurse userPurse = UserPurseProvider.Get(item.UserId, item.TCurrency);
                userPurse.ReferenceTransactionFrom(this.Transaction);
                if (!userPurse.UnFreeze(item.FreezeId, currency))
                {
                    Alert(userPurse.PromptInfo);
                    Log.Info("[{0}]解凍失敗:{1}", item.Id, userPurse.PromptInfo.MessageStack);
                    return false;
                }
                Log.Info("[{0}]解凍成功", item.Id);
            }
            return true;
        }


        //同步代幣動態信息
        private bool SyncDynamice()
        {
            Tdct_Daily_Dynamics daDynamice = new Tdct_Daily_Dynamics();
            daDynamice.ReferenceTransactionFrom(this.Transaction);
            if (daDynamice.SelectByDate(daMatch.SellCurrency, daMatch.BuyCurrency))
            {
                if (!daDynamice.UpdateNewSycn(daDynamice.Id, daMatch.Price, daMatch.BuyCount))
                {
                    Alert("同步每日動態失敗");
                    return false;
                }
                return true;
            }
            daDynamice.BuyCurrencyId = daMatch.BuyCurrency;
            daDynamice.SellCurrencyId = daMatch.SellCurrency;
            daDynamice.LastTime = DateTime.Now;
            daDynamice.MaxPrice = daMatch.Price;
            daDynamice.MinPrice = daMatch.Price;
            daDynamice.NewPrice = daMatch.Price;
            daDynamice.StartPrice = daMatch.Price;
            daDynamice.TCount = daMatch.BuyCount;
            if (!daDynamice.Insert())
            {
                Alert("保存每日動態數據失敗!", daDynamice.PromptInfo);
                return false;
            }
            return true;
        }
    }
}

 



上面的代碼我基本上都加了註釋,基本上能理解撮合交易的概念,配合我提供的這段代碼以及數據庫設計,就對於開發代幣交易所的基本沒有問題。

前端有個價格是實時動態的,若是技術水平還的話能夠作個實時推送,若是以爲麻煩就作個定時器3秒輪訓一次也能夠。

 

======================================================華麗的分割線=======================================================

 

再多說幾句,區塊鏈之因此那麼火熱是在於它的技術性特,好比"去中心化"  能夠幫助人們解除中心存儲的信任問題,「UXTO」機制能夠保證每一筆錢都能查的清清楚楚,「不可修改」 的特性能夠保證數據的惟一性和一致性。

自己比特幣,只是在咱們每一個爲何要去同步區塊?同步區塊以及挖礦(記帳)我有什麼好處?這時就給予了比特幣的獎勵!俗氣一點說,比特幣就是這個用途,固然咱們能夠高尚去說他解決了 「貨幣超發」,「通貨膨脹」,「中心化不可信任」等問題。

 

如今國家基本上是不讓作交易所了,因此去年末全部交易所也紛紛清退,關停了。這也讓咱們更清晰的去看待「區塊鏈」技術,而不是隻有「炒幣」。

 

不能否認的是,確定還有不少幣的交易所在見不得光的運做着,我以爲就是早期在比特幣和ICO來臨的時候,沒有圈到錢,而且有着一種「不甘心」的心態在執着。

若是隻是去發一個沒有技術含量的「空氣幣」 而後藉着區塊鏈的名頭「割韭菜」,這其實就涉嫌"非法吸取公衆存款"的罪名。錢不會憑空產生,也不會憑空消失,有人賺錢就註定有人在虧錢。

 

「空氣幣」自己不具有任何價值,只有將區塊鏈技術應用到生活,區塊鏈對應的代幣纔有價值。

 

就寫到這吧,下一篇文章我將會回到「以太坊」的區塊鏈技術,講解如何將「.net」 技術以及C# 這們技術語言與「以太坊」區塊鏈相結合。(C# 在移動互聯網時代沒落,但願在區塊鏈的風口上能再次崛起!)

 

若是你以爲這篇文章對你有幫助,請捐助:

 

                                                                                                               

 

 

有興趣一塊兒探討Winner2.0框架的能夠加咱們QQ羣:261083244。或者掃描左側二維碼加羣。

相關文章
相關標籤/搜索