最初由杰夫·斯科特写
全栈开发人员习惯于同时在后端和前端工作。使用区块链作为后端存在的问题是,它们的设置通常很复杂,与之交互也更复杂。这会降低存储和用户交互之间的简单交互。
DApp(去中心化的应用程序)是一个与区块链交互的应用程序。目前,最常见的web应用是具有以下基本交互功能的web应用:
发送交易
得到交易状态
从智能合同获取当前状态
在开发期间,**简化这个过程,这样我就不必每次都等待区块链来处理我的事务。我只是想获得一些状态来渲染路线,以打乱布局。我还想在不模拟数据的情况下设计用户与区块链在不同路径上的交互。
在本文中,我将设置一个简单的Python web服务器,它将按照我的智能契约处理模拟事务。这将允许我使用现代的RESTful API模式轻松创建智能契约的前端。
我们需要什么?
Lamden的主节点已经通过API服务于公共区块链。如果我们希望合约服务器模仿区块链,这是一个很好的起点。
MasterNode API有许多与块、随机数和事务散列相关的路由。但我们的合同网络服务器不需要太多的努力或共识,所以我们不需要这些。
我们只关心让我们查看和更改状态的端点,所以我将列表与这5个端点配对。
POST /
提交交易记录
GET /平
确保我们的服务器正在响应
GET /合同
看看我们区块链上所有合同的名称
获取/合同/ AMPL lt;Contract;
有关我们的区块链智能合同的具体信息:
代码
的方法
状态变量
获取/合同/ AMPL lt;Contract;/ AMPL lt;Variablegt;
获取变量的当前状态
设置
接下来,我们需要安装Sanic服务器,它将是我们的Python Web服务器。
1 pip3installsanic
创建服务器
创建一个新的服务器目录和一个名为contracting_serer.py的文件。
首先,**SANIC快速启动代码,确保我们可以启动简单服务器。
将其粘贴到contracting_serer.py中。
1 #服务器/ contracting_serer。2 fromsanicimportsanic py, response, 3,4, app = Sanic (” contractingserer “) 5 6 @app路由(“/ping “) 7异步处理(请求):8 returnresponse。on ({‘ status’: ‘online’}) 910 if剩余域名__ = ‘剩余域名__ ‘:11 app运行(主机= ‘ 0.0.0.0 ‘,端口= 3737)
然后从项目目录中运行
1 python3test / contracting_serer。Py
您应该会得到这个输出,表明您的Web服务器处于活动状态并在端口3737上侦听。
1 11:37:30 [2020-06-01-0400] [8137] Goin ‘Fast @ http://0.0.0.0:37372 11:37:30 [2020-06-01-0400] [8137]
我们还将测试API的ping端点是否工作。打开Internet浏览器并导航到http://localhost:3737/ping。您将得到一个ON状态对象,指示服务器在线!
完美的是,我们现在可以添加一些端点来返回关于契约环境的信息。
GET /合同
此端点将返回当前提交给客户机的所有契约。
默认情况下,契约包只包含一个契约(提交契约)。所以我们需要添加我们的合同来理解合同。您可以通过添加契约客户并调用上一教程测试中的方法来实现这一点。
1 #服务器/ contracting_serer。2来自于心理强直,3来自于心理收缩。使用open (‘ my_token ‘)代码= f。r ead() 9。客户端提交(代码,名称= ‘my_token’) 1011 app = Sanic (1213 @app)路由”contractingserer”) (“/ping “) 14…
现在,当智能契约服务器启动时,它将默认添加我们的智能契约。
客户端。get_contracts()将返回加载到契约客户端的所有智能契约的列表。
通过添加以下代码来创建端点,以提供调用客户机的结果。get_contracts ()。
1 #服务器/ contracting_serer。2 p y……on ({‘status’:’online’}) 4 5#GetallContractsinState(listofnames) [email protected](“/contract “) 7AsyncDeFiget_Contracts (Request): 8个contract = client。get_contretreturnresponse ()on({}“合同”:合同)1011 if__name__ = =“__main__”: 12…
通过打开终端重新启动Web服务器,按Control + C停止服务器,然后使用PYTHon3 Tests /contracting_serer.py启动它。从现在开始,本教程将简单地称为ldQuo;重新启动Web服务器。
如果您在这里遇到错误,请检查MongoDB是否已安装并启动。
浏览到我们的新端点http://localhost:3737/contracts,现在您将在网络上看到我们的my_token智能契约。
获取/合同/ AMPL lt;Contract;
我们可以使用这个端点来获取关于契约的元数据。这对于调试我们自己的智能契约或显示有关它们的动态信息非常有用。
我们需要AST包来遍历代码,因此在contracting_serer.py的顶部添加导入。
1 #服务器/ contracting_serer。Py2fromsanicimportSanic response3importast45fromcontracting。Db。Encoderimportencode6fromcontracting。ClientimportContractingClient7……
现在为这个新的路由添加代码并重新启动服务器。
1 #服务器/ contracting_serer。2 p y……3 returnresponse。on ({‘ contract ‘: contract}), 4,5 @app。路线(“/合同/ AMPL lt;Contract;“7) 6 # Getthesourcecodeofaspecificcontract asyncDeFiget_contract (request, contract): 8 # usETHeclientraw_drierthrtthecontractcoDeFiromthedb 9 contract_code = client。Raw_drier。Get_contract (contract) 1011 funcs = 13散列= 12个变量= [][][]1415 # ParsETHecodeintoawalkabletree16tree = ast parse (contract_code) 1718 # Parseoutallfunctions19function_DeFis = [n Forninast。遍历(树)ifisinstance (n, ast. FunctionDef)] 20 forDeFinitioninfunction_DeFis: 21 func_name = DeFinition。Name22kwargs = [arg。ArgforarginDeFinition。arg游戏。args] 2324不起作用。Append ({‘ name ‘: func_name,’ argument S: kwargs}) 2526 # parseoutallDeFinedstateariablesandhashes27assigned = [nforninast]如果你的树被赋值了,那么你的树被赋值了。Value) = = ast. Call: 30 ifassign。价值。函数。Id = =’ Var Iable ‘: 31个变量。附加(分配目标[0]。Id. Lstrip(‘(‘))。32 elifassign价值。函数。Id = =’哈希’:33个哈希值。追加(分配。目标[0]。Id. Lstrip (‘ (‘)) 3435 # ReturnallInformation36returnresponse。on({37个’ name ‘: contract, 38个’ code ‘: contract_code, 39个’ mETHods’: funcs, 40个’ariables’: the ariables, 41个’ hash ‘: hashes42}, 4344 if摔打姓名__状态= 200)= = “摔打姓名__”:45…
浏览到我们的新端点http://localhost:3737/contact/my_token,您将看到关于智能契约的所有元数据。
让我们看看!
第一种方法;Seed”是构造函数方法。智能契约在提交后对其进行重命名,因此不能再次调用它。
第二种方法是我们的transport mETHod,我们可以看到它需要两个参数,AMOUNT和RECEIVER。
智能契约没有状态变量,但有状态哈希“S”
获取/合同/ AMPL lt;Variablegt;
如果能够查询S散列的状态以获得我们的余额,将会很有帮助。我们已经在测试文件中完成了此操作,因此将其变为动态的,并从新端点提供它,以便稍后在网络应用程序中使用。
我们需要将encode函数从收缩转换为正确格式化值。
将import语句添加到contracting_serer.py的顶部。
1 #服务器/ contracting_serer。Py23fromsanicimportSanic response4importast56fromcontracting。Db。Encoderimportencode7fromcontracting。ClientimportContractingClient8client = ContractingClient(9)…
现在为这个新的路由添加代码,并重新启动服务器。
1 #服务器/ contracting_serer。2 p y……3 # Returnthecurrentstateofaariable 4 @app。路线(“/合同/ AMPL lt;Contract;/ AMPL lt;Variablegt;“) 5 asyncDeFiget_ariable(请求,契约,变量):6 # checkifcontrtexists。如果没有,则返回turnerror 7 contract_code =客户端。Raw_drier。Get_contract 8 ifcontract_codeisnone (contract): 9返回响应。on ({‘ error ‘:’ {} doesnotexist format (contract)}, status = 404) 10 # Parsekeyfromrequestobject11key = request。args。get ()ifkeyisnotnone: 13 key = key。split (‘, ‘) 1415 # CreatETHekeycontractingwi llusETHrtthealue16k = client。Raw_drier。Make_key (contract = contract, ariable = ariable, args = key) 1718 # Getalue19alue = clientRaw_drier。Get (k) 2021 # if the ariableorthealuedidn ‘texistsreturnNone22i*eis None: 23 returnresponse。on ({‘ alue ‘: None}, status = 404), 2425 # Iftherewasaalue returnitformatted26returnresponse。on ({‘ alue: the alue}, status = 200, dumps = encode) 27…
此端点需要比前一个端点更多的信息。
变量:要查询的状态变量(单个或散列)
键:查询时提供散列的键
为了提供此信息,我们将URL参数化
存储状态的变量
Key—要为其分配值的键的名称
本地主机:3737 / contract /my_token/S?关键=我
浏览到我们的新端点http://localhost:3737/contact/my_token /S?钥匙=我来得到我自己在平衡。
更改为不存在的键。如及其他;You”,将返回空值,因为该值在状态中不存在。
POST /
到目前为止,我们的API状态良好。现在我们需要做的就是接受一个事务到我们的网络中。
在真实的区块链上,事务结果不是即时的,因为它需要排队等待节点处理。当您提交一个事务时,区块链用一个收据(称为事务散列)响应,然后您可以使用它来查找事务是否成功。
我们的合同网络服务器不需要做这些。我们不需要阻碍或一致意见,所以我们可以简单地写我们的价值声明。这有助于快速发展。
为这个新的路由添加代码并重新启动服务器。
1 #服务器/ contracting_serer。2 p y……3 #如果有价值,returnitformat 4 returnresponse。on ({‘ alue: the alue}, status = 200, dumps = encode) 5 @app6 asyncDeFisubmit_transaction (request): 7 # 8 contract_name Gettransactiondetails = request。on。9 mETHod_name = request。on。get ()’mETHod’ 10 kwargs =请求。on。发送者=请求。on。get ()“发件人”1213 # setthesender14客户端签名者= # sender1516 Getreferencetocontract17contract =客户端。Get_contr Act (1819 # returnerrorofcontractnotexist20ifcontract_nameisnone contract_name): 21 returnresponse。on ({‘ error ‘:’ {} doesnotexist format (contract)}, status = 404), 2223 # GetreferencetothecontractmETHodtobecal Led24mETHod = getattr (contract, mETHod_name) 2526 # CallmETHodwithsuppliedargumentsandreturnstatus27try: 28 mETHod (* * kwargs) 29 returnresponse。on({状态:0})30 exceptexceptionaserr: 31 returnresponse。on({“圣前提”:1、“错误”:犯错})32 if__name__ = =“__main__”: 33……
要实现这个端点,我们需要创建一个HTTP POST请求。最简单的方法是使用下面所示的curl语句。调用我们的方法需要以下信息:
发送者:对。这就是CTX。来电通知我们的智能合同。
2. 合同:我们要查找的智能合同的名称。
3.方法:我们将要查找的智能契约的名称。
Args:传递给方法的参数。
Curl – XPOST – 1 d ‘{2“发件人”:“我”,“合同”:3“my_token”4“方法”:“转移”,5“参数”:“{/“/”数量:10 / “接收机/:” / ” / “}” 6}’ – -我的http://localhost: 3737 /
当然,您可以使用您选择的任何程序来测试API,如Postman或Paw。只需使用正文ON并将请求发送到http:// localhost: 3737/,就应该返回此响应。
{1,2及其他;Status”:3}
如果尝试发送太多代币,将返回断言错误。
1{2“status”:1,3“error”:“transferamount超过saailabletokenbalance 4}”
然后,我们可以使用前面创建的变量端点来检查状态是否已更改
这是我们刚刚创建的整个开发服务器代码。
1 #服务器/ contracting_serer。Py 2 3来自于强直,反应4 5 6来自于强直。Db。Encoderimportencode 7 fromcontracting。在这里输入my_token (‘ my_token ‘)。Py) asf: 11代码= f。r ead(12)病人。提交(代码,名称= ‘my_token’) 13 14 app = Sanic (” contractingserer “) 15 # 16 make urETHesererisonline 17 @app路由(“/ping “) 18 asyncDeFiping (request): on ({‘status’:’online’}) 20 21#GetallContractsinState(listofnames) [email protected](“/contract “) 23ASYNcDeFiget_Contracts (request): 24个contract = client。get_contretreturnresponse ()on ({‘ contract ‘: contract}) 26和27 @app。路线(“/合同/ AMPL lt;Contract;“28 # 29 asyncDeFiget_contract Getthesourcecodeofaspecificcontract)(请求,合同):30 # 31 contract_code usETHeclientraw_drierthrtthecontractcoDeFiromthedb = client。Raw_drier。Get_contract 32 33 # 34 ifcontract_codeisnone Returnanerrorresponseifthecodedoesnotexist (contract): 35 returnresponse。on({“错误”:“(合同)},{}doesnotexist格式状态= 404)36 37 func 38 39散列变量= = =[][][]40和41 # ParsETHecodeintoawalkabletree = 42 ast树。解析(contract_code) 43 44 # 45 function_DeFis Parseoutallfunctions = [nforninast。[46 forDeFinitioninfunction_DeFis: 47 func_name = DeFinition。名称=ArgforarginDeFinition。arg游戏。现在已经有50个了。49附加({‘ name ‘: func_name,’ the arguments: kwargs}) 52 # 51 parseoutallDeFinedstateariablesandhash 53赋值= [nforninast]。如果你的树被赋值了,那么你的树被赋值了。Value) = = ast. Call: 56 ifassign。价值。函数。Id = = ‘Variable’: 57个变量。追加(分配。目标[0]。Id. Lstrip(‘(‘))。58 elifassign价值。函数。Id = = ‘Hash’: Append(分配。目标[0]。Id. Lstrip(“__”))60 61#ReturnallInformation 62Returnresponse。on (63’name: Contract, 64’code:contract_code, 65’mETHods: Funcs, 66’ariables:ariables, 67 ‘hash: 68} hashes, status = 200) 69 70 # Returnthecurrentstateofaariable 71 @app路线(“/合同/ AMPL lt;Contract;/ AMPL lt;Variablegt;“asyncDeFiget_ariable(请求,契约,变量):如果不是,则返回turnerror 74 contract_code =客户端。Raw_drier。Get_contract 75 ifcontract_codeisnone (contract): 76返回响应。on ({‘ error ‘:’ {} doesnotexist format (contract)}, status = 404), 77 # Parsekeyfromrequestobject 78 key = request。args。get ()79 ifkeyisnotnone: 80 key = key。creatETHekeycontractingwilluse好过thealue k =客户端。Raw_drier。Make_key (contract = contract, ariable = ariable, args = key)Raw_drier。得到87 (k) 88 #如果可变标准值不存在,返回0 89如果alueisnone: 90返回响应。on ({‘ alue ‘: None},状态= 404)91 92 #如果有值返回格式化了93 returnresponse。on({的值:值},状态= 200,转储=编码)94 95 @app。asyncDeFisubmit_transaction (request): # 97 Gettransactiondetails contract_name = 98 request。on。Get (” contract “) 99on。get ()’mETHod’ 100 kwargs =请求on。Get (‘ the args) 101发件人=请求。on。Get (‘ sender ‘) 102103 # Setthesender104client。签名者= # sender105106 Getreferencetocontract107contract = client。Get_contract (contract_name) 108109 # Returnerrorofcontractdoesnotexist110ifcontract_nameisNone: 111 returnresponse。on ({‘ error ‘:’ {} doesnotexist format (contract)}, status = 404), 112113 # Getreferencetothecontra CtmETHodtobecalled114mETHod = getattr (contract, mETHod_name) 115116 # CallmETHodwithsuppliedargumentsandreturnstatus117try: 118方法(* * kwargs) 119 returnresponse。on({状态:0})120 exceptexceptionaserr: 121 r Eturnresponse。on({“status”:1,“error”:STR (err)}) 122123124 if剩余域名__ =“剩余域名__”:125应用程序运行(主机=“0.0.0.0”,端口= 3737)
文章标题:区块链研究实验室|使用Python创建智能合同区块链后端服务器应用程序
文章链接:https://www.btchangqing.cn/33950.html
更新时间:2020年06月08日
本站大部分内容均收集于网络,若内容若侵犯到您的权益,请联系我们,我们将第一时间处理。