区块链100讲:从宠物商店案例看DAPP架构和WEB3.JS交互接口

Solidity实现智能合约——宠物进食系统(二) Solidity实现智能合约——宠物进食系统(二) 在上一节当中我们实现了创建宠物的功能,接下来将继续完善功能,让我们的宠物可以进食。 为了存储宠物的所有权,我们会使用到两个映射:一个记录宠物拥有者的地址,另一个记录某地址所拥有宠物的数量。 创建一个叫做 AnimalToOwner 的映射。其键是一个uint(我们将根据它的 id 存储和查找宠物),值为 address。映射属性为public。 创建一个名为 ownerAnimalCount的映射,其中键是 address,值是 uint。 mappin 阅读详情

image

1

文章摘要

【本文目标】
了解ETH生态下DAPP去中心化应用程序的框架和交互流程,了解WEB3.JS的作用和接口函数。

【前置条件】
完成了《技术小白如何开发一个DAPP区块链应用(以宠物商店为例)》(https://www.jianshu.com/p/9844d97ef1d0)或 开发实战|3步教你在以太坊上开一家宠物店(附流程+代码)的学习实践,对智能合约了解。

【技术收获】
1). DAPP架构
2). ETH节点框架
3).宠物商店的APP.js文件的业务处理流程图和函数介绍
4).web3.js接口

2

以太坊节点和DAPP框架

2.1 以太坊节点架构

image

以太坊节点架构图

以太坊是一种区块链的实现。在以太坊网络中,众多的节点彼此连接,构成了以太坊网络。

以太坊节点软件提供两个核心功能:数据存储、合约代码执行。

在每个以太坊全节点中,都保存有完整的区块链数据。以太坊不仅将交易数据保存在链上,编译后 的合约代码同样也保存在链上。以太坊全节点中,同时还提供了一个虚拟机来执行合约代码。

交易数据

以太坊中每笔交易都存储在区块链上。当你部署合约时,一次部署就是一笔交易。当你为候选者投票时,一次投票 又是另一笔交易。所有的这些交易都是公开的,每个人都可以看到并进行验证。这个数据永远也无法篡改。

为了确保网络中的所有节点都有着同一份数据拷贝,并且没有向数据库中写入任何无效数据,以太坊 目前使用工作量证明 (POW:Proof Of Work)算法来保证网络安全,即通过矿工挖矿(Mining)来达成共识(Consensus)—— 将数据同步到所有节点。

工作量证明不是达成共识的唯一算法,挖矿也不是区块链的唯一选择。现在,我们只需要了解,共识是指各节点 的数据实现了一致,POW只是众多用于建立共识的算法中的一种,这种算法需要通过矿工的挖矿来实现非可信环境下的 可信交易。共识是目的,POW是手段。

合约代码

以太坊不仅仅在链上存储交易数据,它还可以在链上存储合约代码。

在数据库层面,区块链的作用就是存储交易数据。那么给候选者投票、或者检索投票结果的逻辑放在哪儿呢? 在以太坊的世界里,你可以使用Solidity语言来编写业务逻辑/应用代码(也就是合约:Contract), 然后将合约代码编译为以太坊字节码,并将字节码部署到区块链上:

image

编写合约代码也可以使用其他的语言,不过 Solidity是到目前为止最流行的选择。

以太坊虚拟机

以太坊区块链不仅存储数据和代码,每个节点中还包含一个虚拟机(EVM:Ethereum Virtual Machine)来执行 合约代码 —— 听起来就像计算机操作系统。

事实上,这一点是以太坊区别于比特币(Bitcoin)的最核心的一点:虚拟机的存在使区块链迈入了2.0 时代,也让区块链第一次成为应用开发者友好的平台。

2.2 DAPP架构

下图给出了基于以太坊的去中心化应用架构:

image

DAPP架构图

每个客户端(浏览器)都是与各自的节点应用实例进行交互,而不是向 一个中心化的服务器请求服务。

在一个理想的去中心化环境中,每个想要跟DApp交互的人,都需要在他们的计算机或手机上面运行 一个的完整区块链节点 —— 简言之,每个人都运行一个全节点。这意味着,在能够真正使用一个 去中心化应用之前,用户不得不下载整个区块链。

不过我们并非生活在一个乌托邦里,期待每个用户都先运行一个全节点,然后再使用你的应用是不现实的。 但是去中心化背后的核心思想,就是不依赖于中心化的服务器。所以,区块链社区已经出现了 一些解决方案,例如提供公共区块链节点的Infura, 以及浏览器插件Metamask等。通过这些方案, 你就不需要花费大量的硬盘、内存和时间去下载并运行完整的区块链节点,同时也可以利用去中心化 的优点。

Web3.js是以太坊官方的Javascript API,可以帮助智能合约开发者使用HTTP或者IPC与本地的或者远程的以太坊节点交互。实际上就是一个库的集合,主要包括下面几个库:

  • web3-eth用来与以太坊区块链和智能合约交互

  • web3-shh用来控制whisper协议与p2p通信以及广播

  • web3-bzz用来与swarm协议交互

  • web3-utils包含了一些Dapp开发有用的功能

Web3与geth通信使用的是 JSON-RPC ,这是一种轻量级的RPC(Remote Procedure Call)协议,整个通信的模型可以抽象为下图。

image

WEB3位置图

3

以宠物商店为例WEB3.JS代码

《技术小白如何开发一个DAPP区块链应用(以宠物商店为例)》(https://www.jianshu.com/p/9844d97ef1d0)或 开发实战|3步教你在以太坊上开一家宠物店(附流程+代码)这篇文章详细介绍了一个宠物商店DAPP的案例。本节重点分析引用WEB3.JS相关接口代码。

3.1 加注释的app.js代码

App = {

  web3Provider: null,

  contracts: {},

  init: function() {

    /*加载宠物名字,图片,年龄,位置等信息*/

    // Load pets.

    $.getJSON('../pets.json', function(data) {

      var petsRow = $('#petsRow');

      var petTemplate = $('#petTemplate');

      for (i = 0; i < data.length; i ++) {

        petTemplate.find('.panel-title').text(data[i].name);       

 petTemplate.find('img').attr('src', data[i].picture);        

petTemplate.find('.pet-breed').text(data[i].breed);       

 petTemplate.find('.pet-age').text(data[i].age); 

       petTemplate.find('.pet-location').text(data[i].location);        

petTemplate.find('.btn-adopt').attr('data-id', data[i].id);       

 petsRow.append(petTemplate.html());

      }

    });

    return App.initWeb3();

  },

  initWeb3: function() {

    /*如果web3事先被定义,则使用当前web3实例的钱包对象。例如remix下JavaScript VM创建的虚拟钱包(有4个含100个 ETH的账户);

      或者MetaMask链接后的账户钱包;或者mist钱包*/

    if (typeof web3 !== 'undefined') {

      App.web3Provider = web3.currentProvider; 

   } else {

      // If no injected web3 instance is detected, fall back to Ganache

      /*如果web3不存在,则启动本地启动的Ganache钱包。[前提:要启动好本地的Ganache环境哦,否则会创建不成功]*/

      App.web3Provider = new Web3.providers.HttpProvider('http://localhost:7545');

    }

    /*创建Web3实例,入口参数为刚才配置的App.web3Provider*/

    web3 = new Web3(App.web3Provider);

    /*调用初始化合约函数*/

    return App.initContract();

  },

  initContract: function() { 

   /*参考 http://www.w3school.com.cn/jquery/ajax_getjson.asp 获取getJSON到的方法*/ 

   $.getJSON('Adoption.json', function(data) { 

     // Get the necessary contract artifact file and instantiate it with truffle-contract

      var AdoptionArtifact = data;

      App.contracts.Adoption = TruffleContract(AdoptionArtifact);  

        // 设置当前合约的web3Provider钱包提供者 

     App.contracts.Adoption.setProvider(App.web3Provider);  

        // 使用我们的合约去提取和标识已领养的宠物 

     return App.markAdopted();

    }); 

       /*返回绑定事件*/ 

   return App.bindEvents(); 

 }, 

 /*点击含有'.btn-adopt'类的click事件会触发handleAdopt(处理领养)的函数*/ 

 bindEvents: function() { 

   $(document).on('click', '.btn-adopt', App.handleAdopt); 

 },

 /*如果该宠物已被领养,则文字显示为"Success",按钮不可点击*/

  markAdopted: function(adopters, account) 

{

    var adoptionInstance;   

 App.contracts.Adoption.deployed().then(function(instance)

 {

      adoptionInstance = instance;

          return adoptionInstance.getAdopters.call();

    }).then(function(adopters) {

      for (i = 0; i < adopters.length; i++) { 

       /*如果领养者的地址不是为0,则设置按钮字体和状态,*/ 

       if (adopters[i] !== '0x0000000000000000000000000000000000000000') { 

         $('.panel-pet').eq(i).find('button').text('Success').attr('disabled', true); 

       }

      }

    }).catch(function(err) {

      console.log(err.message); 

   });

  },  

handleAdopt: function(event) {

    event.preventDefault(); 

       /*parseInt() 函数可解析一个字符串,并返回一个整数。*/ 

   var petId = parseInt($(event.target).data('id')); 

   var adoptionInstance; 

       /*获取当前ETH钱包的账号*/ 

   web3.eth.getAccounts(function(error, accounts) {

      if (error) {

        console.log(error);

      }

         /*取第一个钱包账号*/ 

     var account = accounts[0]; 

        /*ES6的then函数调用,链式调用*/   

   App.contracts.Adoption.deployed().then(function(instance) {

        adoptionInstance = instance; 

       // 通过发送账户执行adopt领养函数的交易的返回值

        // 此处没有搞懂,智能合约Adoption.adopt只有一个入参,此处为什么增加了第二个{from: account}参数呢?

        //TINY熊认为,把它当做语法就可以, 要么提前设置默认账号, 要么调用时指定 

       return adoptionInstance.adopt(petId, {from: account}); 

     }).then(function(result) { 

       /*标识领养状态*/ 

       return App.markAdopted(); 

       /*输出错误*/ 

     }).catch(function(err) { 

       console.log(err.message);

      });

    });

  }};

/*窗口加载即调用App.init函数*/

$(function() {

  $(window).load(function() {

    App.init(); 

 });

});

3.2 app.js调用WEB3流程分析

image

app.js调用WEB3流程图

4

Web3 JavaScript app API 参考

Web3的官网文档给出了详细的接口文档和说明。

4.1 web3

web3对象提供了所有方法。

示例:

//初始化过程

var Web3 = require('web3');

if (typeof web3 !== 'undefined') { 

 web3 = new Web3(web3.currentProvider);

} else {

  // set the provider you want from Web3.providers

  web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));

}

web3.version.api

web3.version.api

返回值:

String - 以太坊js的api版本

示例:

//省略初始化过程

var version = web3.version.api;

console.log(version);

$ node test.js

0.18.2

web3.version.node

同步方式:

web3.verison.node

异步方式:

web3.version.getNode(callback(error, result){ ... })

返回值:

String - 客户端或节点的版本信息

示例:

//省略初始化过程

var version = web3.version.node;

console.log(version);

$ node test.js
EthereumJS TestRPC/v3.0.3/ethereum-js

web3.version.network

同步方式:

web3.version.network

异步方式:

web3.version.getNetwork(callback(error, result){ ... })

返回值:

String - 网络协议版本

示例:

//省略初始化过程

var version = web3.version.network;

console.log(version);

$ node test.js

1488546587563

web3.version.ethereum

同步方式:

web3.version.ethereum

异步方式:

web3.version.getEthereum(callback(error, result){ ... })

返回值:

String - 以太坊的协议版本

示例:

//省略初始化过程

var version = web3.version.ethereum;

console.log(version);

$ node test.js

60

**注意:**EthereumJS testRPC客户端不支持这个命令,报错Error: Error: RPC method eth_protocolVersion not supported.

web3.version.whisper

同步方式:

web3.version.whisper

异步方式:

web3.version.getWhisper(callback(error, result){ ... })

返回值:

String - whisper协议的版本

示例:

//省略初始化过程

var version = web3.version.whisper;

console.log(version);

$ node test.js

20

注意:EthereumJS testRPC客户端不支持这个命令,报错Error: Error: RPC method shh_version not supported.

web3.isConnected

web3.isConnected

可以用来检查到节点的连接是否存在(connection to node exist)。

参数:

无

返回值:

Boolean

示例:

//省略初始化过程

var connected = web3.isConnected();

if(!connected){

  console.log("node not connected!");

}else{

  console.log("node connected");

}

web3.setProvider

web3.setProvider

设置Provider

参数:

无

返回值:

undefined

示例:

web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545'));

web3.currentProvider

web3.currentProvider

如果已经设置了Provider,则返回当前的Provider。这个方法可以用来检查在使用mist浏览器等情况下已经设置过Provider,避免重复设置的情况。

返回值:

Object - null 或 已经设置的Provider。

示例:

if(!web3.currentProvider)
   web3.setProvider(new web3.providers.HttpProvider("http://localhost:8545"));

web3.reset

web3.reset

用来重置web3的状态。重置除了manager以外的其它所有东西。卸载filter,停止状态轮询。

参数:

Boolean - 如果设置为true,将会卸载所有的filter,但会保留web3.eth.isSyncing()的状态轮询。

返回值:

undefined

示例:

//省略初始化过程

console.log("reseting ... ");

web3.reset();

console.log("is connected:" + web3.isConnected());

$ node test.js

reseting ...

is connected:true

web3.sha3

web3.sha3(string, options)

参数:

  • String - 传入的需要使用Keccak-256 SHA3算法进行哈希运算的字符串。

  • Object - 可选项设置。如果要解析的是hex格式的十六进制字符串。需要设置encoding为hex。因为JS中会默认忽略0x。

返回值:

String - 使用Keccak-256 SHA3算法哈希过的结果。

示例:

//省略初始化过程

var hash = web3.sha3("Some string to be hashed");

console.log(hash); 

var hashOfHash = web3.sha3(hash, {encoding: 'hex'});

console.log(hashOfHash);

web3.toHex

web3.toHex

将任何值转为HEX。

参数:

String|Number|Object|Array|BigNumber - 需要转化为HEX的值。如果是一个对象或数组类型,将会先用JSON.stringify1进行转换成字符串。如果传入的是BigNumber2,则将得到对应的Number的HEX。

示例:

//初始化基本对象

var Web3 = require('web3');

var web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));

var BigNumber = require('bignumber.js');

var str = "abcABC";

var obj = {abc: 'ABC'};

var bignumber = new BigNumber('12345678901234567890');

var hstr = web3.toHex(str);

var hobj = web3.toHex(obj);

var hbg = web3.toHex(bignumber);

console.log("Hex of Sring:" + hstr);

console.log("Hex of Object:" + hobj);

console.log("Hex of BigNumber:" + hbg);

$ node test.js

Hex of Sring:0x616263414243

Hex of Object:0x7b22616263223a22414243227d

Hex of BigNumber:0xab54a98ceb1f0ad2

web3.toAscii

web3.toAscii(hexString)

将HEX字符串转为ASCII3字符串

参数:

String - 十六进制字符串。

返回值:

String - 给定十六进制字符串对应的ASCII码值。

示例:

var str = web3.toAscii("0x657468657265756d000000000000000000000000000000000000000000000000");

console.log(str); // "ethereum"

web3.fromAscii

web3.fromAscii

将任何的ASCII码字符串转为HEX字符串。

参数:

  • String - ASCII码字符串

  • Number - 返回的字符串字节大小,不够长会自动填充。

返回值:

String - 转换后的HEX字符串。

示例:

var str = web3.fromAscii('ethereum');

console.log(str); // "0x657468657265756d"

var str2 = web3.fromAscii('ethereum', 32);

console.log(str2); // "0x657468657265756d000000000000000000000000000000000000000000000000"

$ node test.js

0x657468657265756d

0x657468657265756d

备注: 填充padding功能好像不可用。

web3.toDecimal

web3.toDecimal

将一个十六进制转为一个十进制的数字

参数:

String - 十六进制字符串

返回:

Number - 传入字符串所代表的十六进制值。

示例:

var number = web3.toDecimal('0x15');

console.log(number); // 21

**web3.fromDecimal**

web3.fromDecimal

将一个数字,或者字符串形式的数字转为一个十六进制串。

参数:

Number|String - 数字

返回值:

String - 给定数字对应的十六进制表示。

示例:

var value = web3.fromDecimal('21');

console.log(value); // "0x15"

web3.fromWei

web3.fromWei(number, 单位)

以太坊货币单位之间的转换。将以wei为单位的数量,转为下述的单位,可取值如下:

  • kwei/ada

  • mwei/babbage

  • gwei/shannon

  • szabo

  • finney

  • ether

  • kether/grand/einstein

  • mether

  • gether

  • tether

参数:

  • Number|String|BigNumber - 数字或BigNumber。

  • String - 单位字符串

返回值:

String|BigNumber - 根据传入参数的不同,分别是字符串形式的字符串,或者是BigNumber。

示例:

var value = web3.fromWei('21000000000000', 'finney');

console.log(value); // "0.021"

web3.toWei

web3.toWei(number, 单位)

按对应货币转为以wei为单位。可选择的单位如下:

  • kwei/ada

  • mwei/babbage

  • gwei/shannon

  • szabo

  • finney

  • ether

  • kether/grand/einstein

  • mether

  • gether

  • tether

参数:

  • Number|String|BigNumber - 数字或BigNumber

  • String - 字符串单位

返回值:

String|BigNumber - 根据传入参数的不同,分别是字符串形式的字符串,或者是BigNumber。

示例:

var value = web3.toWei('1', 'ether');

console.log(value); // "1000000000000000000"

web3.toBigNumber

web3.toBigNumber(数字或十六进制字符串)

将给定的数字或十六进制字符串转为BigNumber5。

参数:

Number|String - 数字或十六进制格式的数字

返回值:

BigNumber - BigNumber的实例

示例:

var value = web3.toBigNumber('200000000000000000000001');

console.log(value); // instanceOf BigNumber

console.log(value.toNumber()); // 2.0000000000000002e+23

console.log(value.toString(10)); // '200000000000000000000001'

4.2 web3.net

web3.net.listening

同步方式:

web3.net.listening

异步方式:

web3.net.getListener(callback(error, result){ ... })

此属性是只读的,表示当前连接的节点,是否正在listen网络连接与否。listen可以理解为接收。

返回值:

Boolean - true表示连接上的节点正在listen网络请求,否则返回false。

示例:

var listening = web3.net.listening;

console.log("client listening: " + listening);

$ node test.js
client listening: true

备注: 如果关闭我们要连接的测试节点,会报错Error: Invalid JSON RPC response: undefined。所以这个方法返回的是我们连上节点的listen状态。

web3.net.peerCount

同步方式:

web3.net.peerCount

异步方式:

web3.net.getPeerCount(callback(error, result){ ... })

属性是只读的,返回连接节点已连上的其它以太坊节点的数量。

返回值:

Number - 连接节点连上的其它以太坊节点的数量

示例:

var peerCount = web3.net.peerCount;

console.log("Peer count: " + peerCount); 

$ node test.js
Peer count: 0

4.3 web3.eth

包含以太坊区块链相关的方法

示例:

var eth = web3.eth;

**web3.eth.defaultAccount**

web3.eth.defaultAccount

默认的地址在使用下述方法时使用,你也可以选择通过指定from属性,来覆盖这个默认设置。

  • web3.eth.sendTransaction()

  • web3.eth.call()

默认值为undefined,20字节大小,任何你有私匙的你自己的地址。

返回值:

String - 20字节的当前设置的默认地址。

示例:

console.log("Current default: " + web3.eth.defaultAccount);

web3.eth.defaultAccount = '0x8888f1f195afa192cfee860698584c030f4c9db1';

console.log("Current default: " + web3.eth.defaultAccount);

$ node test.js

Current default: undefined

Current default: 0x8888f1f195afa192cfee860698584c030f4c9db1

web3.eth.defaultBlock

web3.eth.defaultBlock

使用下述方法时,会使用默认块设置,你也可以通过传入defaultBlock来覆盖默认配置。

  • web3.eth.getBalance()

  • web3.eth.getCode()

  • web3.eth.getTransactionCount()

  • web3.eth.getStorageAt()

  • web3.eth.call()

  • contract.myMethod.call()

  • contract.myMethod.estimateGas()

可选的块参数,可能下述值中的一个:

  • Number - 区块号

  • String - earliest,创世块。

  • String - latest,最近刚出的最新块,当前的区块头。

  • String - pending,当前正在mine的区块,包含正在打包的交易。

默认值是latest

返回值:

Number|String - 默认要查状态的区块号。

示例:

console.log("defaultBlock: " + web3.eth.defaultBlock);web3.eth.defaultBlock = 231;

console.log("defaultBlock: " + web3.eth.defaultBlock);

$ node test.js

defaultBlock: latest

defaultBlock: 231

web3.eth.syncing

同步方式:

web3.eth.syncing

异步方式:

web3.eth.getSyncing(callback(error, result){ ... })

这个属性是只读的。如果正在同步,返回同步对象。否则返回false。

返回值:

Object|Boolean - 如果正在同步,返回含下面属性的同步对象。否则返回false。

返回值:

  • startingBlock:Number - 同步开始区块号

  • currentBlock: Number - 节点当前正在同步的区块号

  • highestBlock: Number - 预估要同步到的区块

var sync = web3.eth.syncing;

console.log(sync);

$ node test.js

false

//正在sync的情况$ node test.js

{

   startingBlock: 300,

   currentBlock: 312, 

  highestBlock: 512

}

web3.eth.isSyncing

web3.eth.isSyncing(callback)

提供同步开始,更新,停止的回调函数方法。

返回值:

Object - 一个syncing对象,有下述方法:

  • syncing.addCallback(): 增加另一个回调函数,在节点开始或停止调用时进行调用。

  • syncing.stopWatching(): 停止同步回调。

回调返回值:

  • Boolean - 同步开始时,此值为true,同步停止时此回调值为false。

  • Object - 当正在同步时,会返回同步对象。

  • startingBlock:Number - 同步开始区块号

  • currentBlock: Number - 节点当前正在同步的区块号

  • highestBlock: Number - 预估要同步到的区块

示例:

//初始化基本对象

var Web3 = require('web3');

var web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));

var BigNumber = require('bignumber.js');

web3.eth.isSyncing(function(error, sync){

    if(!error) {

        // stop all app activity

        if(sync === true) {

           // we use `true`, so it stops all filters, but not the web3.eth.syncing polling 

          web3.reset(true); 

       // show sync info 

       } else if(sync) { 

          console.log(sync.currentBlock);  

      // re-gain app operation

        } else { 

           // run your app init function... 

       } 

   }

});

web3.eth.coinbase

同步方式:

web3.eth.coinbase

异步方式:

web3.eth.getCoinbase(callback(error, result){ ... })

只读属性,节点配置的,如果挖矿成功奖励的地址。

返回值:

String - 节点的挖矿奖励地址。

示例:

var coinbase = web3.eth.coinbase;

console.log(coinbase); // "0x407d73d8a49eeb85d32cf465507dd71d507100c1"

web3.eth.mining

同步方式:

web3.eth.mining

异步方式:

web3.eth.getMining(callback(error, result){ ... })

属性只读,表示该节点是否配置挖矿。

返回值:

Boolean - true 表示配置挖矿,否则表示没有。

var mining = web3.eth.mining;
console.log(mining); // true or false

web3.eth.hashrate

同步方式:

web3.eth.hashrate

异步方式:

web3.eth.getHashrate(callback(error, result){ ... })

属性只读,表示的是当前的每秒的哈希难度。

返回值:

Number - 每秒的哈希数

示例:

var hashrate = web3.eth.hashrate;

console.log(hashrate);

web3.eth.gasPrice

同步方式:

web3.eth.gasPrice

异步方式:

web3.eth.getGasPrice(callback(error, result){ ... })

属性是只读的,返回当前的gas价格。这个值由最近几个块的gas价格的中值6决定。

返回值:

BigNumber - 当前的gas价格的BigNumber实例,以wei为单位。

var gasPrice = web3.eth.gasPrice;

console.log(gasPrice.toString(10)); // "10000000000000"

web3.eth.accounts

同步方式:

web3.eth.accounts

异步方式:

web3.eth.getAccounts(callback(error, result){ ... })

只读属性,返回当前节点持有的帐户列表。

返回值:

Array - 节点持有的帐户列表。

示例:

var accounts = web3.eth.accounts;

console.log(accounts); 

web3.eth.blockNumber

同步方式:

web3.eth.blockNumber

异步方式:

web3.eth.getBlockNumber(callback(error, result){ ... })

属性只读,返回当前区块号。

var number = web3.eth.blockNumber;

console.log(number); // 2744

web3.eth.register

web3.eth.register(addressHexString [, callback])

(暂未实现)将给定地址注册到web3.eth.accounts。这将允许无私匙的帐户,如合约被关联到有私匙的帐户,如合约钱包。

参数:

  • String - 要注册的地址。

  • Function -(可选)回调函数,用于支持异步的方式执行7。

返回值:

待确定

示例:

web3.eth.register("0x407d73d8a49eeb85d32cf465507dd71d507100ca")

web3.eth.unRegister

异步方式

web3.eth.unRegister(addressHexString [, callback])

(暂未实现)取消注册给定地址

参数:

  • String - 要取消注册的地址

  • Function - (可选) 回调函数,用于支持异步的方式执行7。

返回值:

待确定

示例:

web3.eth.unRegister("0x407d73d8a49eeb85d32cf465507dd71d507100ca")

web3.eth.getBalance

web3.eth.getBalance(addressHexString [, defaultBlock] [, callback])

获得在指定区块时给定地址的余额。

参数:

  • String - 要查询余额的地址。

  • Number|String -(可选)如果不设置此值使用web3.eth.defaultBlock设定的块,否则使用指定的块。

  • Funciton - (可选)回调函数,用于支持异步的方式执行7。

返回值:

String - 一个包含给定地址的当前余额的BigNumber实例,单位为wei。

示例:

var balance = web3.eth.getBalance("0x407d73d8a49eeb85d32cf465507dd71d507100c1");

console.log(balance); // instanceof BigNumber

console.log(balance.toString(10)); // '1000000000000'

console.log(balance.toNumber()); // 1000000000000

web3.eth.getStorageAt

web3.eth.getStorageAt(addressHexString, position [, defaultBlock] [, callback])

获得某个地址指定位置的存储的状态值。

合约由控制执行的EVM字节码和用来保存状态的Storage两部分组成。Storage在区块链上是以均为32字节的键,值对的形式进行存储8。

参数:

  • String - 要获得存储的地址。

  • Number - 要获得的存储的序号

  • Number|String -(可选)如果未传递参数,默认使用web3.eth.defaultBlock定义的块,否则使用指定区块。

  • Function - 回调函数,用于支持异步的方式执行7。

返回值:

String - 给定位置的存储值

示例:

var state = web3.eth.getStorageAt("0x407d73d8a49eeb85d32cf465507dd71d507100c1", 0);

console.log(state); // "0x03"

web3.eth.getCode

web3.eth.getCode(addressHexString [, defaultBlock] [, callback])

获取指定地址的代码

参数:

  • String - 要获得代码的地址。

  • Number|String -(可选)如果未传递参数,默认使用web3.eth.defaultBlock定义的块,否则使用指定区块。

  • Function - 回调函数,用于支持异步的方式执行7。

返回值:

String - 给定地址合约编译后的字节代码。

示例:

var code = web3.eth.getCode("0xd5677cf67b5aa051bb40496e68ad359eb97cfbf8");

console.log(code); // "0x600160008035811a818181146012578301005b601b6001356025565b8060005260206000f25b600060078202905091905056"

web3.eth.getBlock

web3.eth.getBlock(blockHashOrBlockNumber [, returnTransactionObjects] [, callback])

返回块号或区块哈希值所对应的区块

参数:

  • Number|String -(可选)如果未传递参数,默认使用web3.eth.defaultBlock定义的块,否则使用指定区块。

  • Boolean -(可选)默认值为false。true会将区块包含的所有交易作为对象返回。否则只返回交易的哈希。

  • Function - 回调函数,用于支持异步的方式执行7。

返回值 - 区块对象:

  • Number - 区块号。当这个区块处于pending将会返回null。

  • hash - 字符串,区块的哈希串。当这个区块处于pending将会返回null。

  • parentHash - 字符串,32字节的父区块的哈希值。

  • nonce - 字符串,8字节。POW生成的哈希。当这个区块处于pending将会返回null。

  • sha3Uncles - 字符串,32字节。叔区块的哈希值。

  • logsBloom - 字符串,区块日志的布隆过滤器9。当这个区块处于pending将会返回null。

  • transactionsRoot - 字符串,32字节,区块的交易前缀树的根。

  • stateRoot - 字符串,32字节。区块的最终状态前缀树的根。

  • miner - 字符串,20字节。这个区块获得奖励的矿工。

  • difficulty - BigNumber类型。当前块的难度,整数。

  • totalDifficulty - BigNumber类型。区块链到当前块的总难度,整数。

  • extraData - 字符串。当前块的extra data字段。

  • size - Number。当前这个块的字节大小。

  • gasLimit - Number,当前区块允许使用的最大gas。

  • gasUsed - 当前区块累计使用的总的gas。

  • timestamp - Number。区块打包时的unix时间戳。

  • transactions - 数组。交易对象。或者是32字节的交易哈希。

  • uncles - 数组。叔哈希的数组。

示例:

var info = web3.eth.getBlock(3150);
console.log(info);
/*
{  "number": 3, 

 "hash": "0xef95f2f1ed3ca60b048b4bf67cde2195961e0bba6f70bcbea9a2c4e133e34b46", 

 "parentHash": "0x2302e1c0b972d00932deb5dab9eb2982f570597d9d42504c05d9c2147eaf9c88", 

 "nonce": "0xfb6e1a62d119228b", 

 "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", 

 "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",  "transactionsRoot": "0x3a1b03875115b79539e5bd33fb00d8f7b7cd61929d5a3c574f507b8acf415bee",

  "stateRoot": "0xf1133199d44695dfa8fd1bcfe424d82854b5cebef75bddd7e40ea94cda515bcb", 

 "miner": "0x8888f1f195afa192cfee860698584c030f4c9db1", 

 "difficulty": BigNumber,

  "totalDifficulty": BigNumber,

  "size": 616,

  "extraData": "0x",

  "gasLimit": 3141592, 

 "gasUsed": 21662, 

 "timestamp": 1429287689, 

 "transactions": [    "0x9fc76417374aa880d4449a1f7f31ec597f00b1f6f3dd2d66f4c9c6c445836d8b"
 ], 

 "uncles": []
}
*/

web3.eth.getBlockTransactionCount

web3.eth.getBlockTransactionCount(hashStringOrBlockNumber [, callback])

返回指定区块的交易数量。

参数:

  • Number|String -(可选)如果未传递参数,默认使用web3.eth.defaultBlock定义的块,否则使用指定区块。

  • Function - 回调函数,用于支持异步的方式执行7。

返回值:

Nubmer - 给定区块的交易数量。

示例:

var number = web3.eth.getBlockTransactionCount("0x407d73d8a49eeb85d32cf465507dd71d507100c1");

console.log(number); // 1

web3.eth.getUncle

web3.eth.getUncle(blockHashStringOrNumber, uncleNumber [, returnTransactionObjects] [, callback])

通过指定叔位置,返回指定叔块。

参数:

  • Number|String -(可选)如果未传递参数,默认使用web3.eth.defaultBlock定义的块,否则使用指定区块。

  • Number - 叔的序号。

  • Boolean -(可选)默认值为false。true会将区块包含的所有交易作为对象返回。否则只返回交易的哈希。

  • Function - 回调函数,用于支持异步的方式执行7。

返回值:

Object - 返回的叔块。返回值参考web3.eth.getBlock()。

备注: 叔块没有自己的交易数据。

示例:

var uncle = web3.eth.getUncle(500, 0);

console.log(uncle); // see web3.eth.getBlock

web3.eth.getTransaction

web3.eth.getTransaction(transactionHash [, callback])

返回匹配指定交易哈希值的交易。

参数:

  • String - 交易的哈希值。

  • Function - 回调函数,用于支持异步的方式执行7。

返回值:

Object - 一个交易对象

  • hash: String - 32字节,交易的哈希值。

  • nonce: Number - 交易的发起者在之前进行过的交易数量。

  • blockHash: String - 32字节。交易所在区块的哈希值。当这个区块处于pending将会返回null。

  • blockNumber: Number - 交易所在区块的块号。当这个区块处于pending将会返回null。

  • transactionIndex: Number - 整数。交易在区块中的序号。当这个区块处于pending将会返回null。

  • from: String - 20字节,交易发起者的地址。

  • to: String - 20字节,交易接收者的地址。当这个区块处于pending将会返回null。

  • value: BigNumber - 交易附带的货币量,单位为Wei。

  • gasPrice: BigNumber - 交易发起者配置的gas价格,单位是wei。

  • gas: Number - 交易发起者提供的gas。.

  • input: String - 交易附带的数据。

示例:

var blockNumber = 668;

var indexOfTransaction = 0

var transaction = web3.eth.getTransaction(blockNumber, indexOfTransaction);

console.log(transaction);

/*

{ 

 "hash": "0x9fc76417374aa880d4449a1f7f31ec597f00b1f6f3dd2d66f4c9c6c445836d8b", 

 "nonce": 2,

  "blockHash": "0xef95f2f1ed3ca60b048b4bf67cde2195961e0bba6f70bcbea9a2c4e133e34b46", 

 "blockNumber": 3, 

 "transactionIndex": 0,

  "from": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",  "to": "0x6295ee1b4f6dd65047762f924ecd367c17eabf8f", 

 "value": BigNumber, 

 "gas": 314159, 

 "gasPrice": BigNumber, 

 "input": "0x57cb2fc4"

}

*/

web3.eth.getTransactionFromBlock

getTransactionFromBlock(hashStringOrNumber, indexNumber [, callback])

返回指定区块的指定序号的交易。

参数:

  • String - 区块号或哈希。或者是earliest,latest或pending。查看web3.eth.defaultBlock了解可选值。

  • Number - 交易的序号。

  • Function - 回调函数,用于支持异步的方式执行7。

返回值:

Object - 交易对象,详见web3.eth.getTransaction

示例:

var transaction = web3.eth.getTransactionFromBlock('0x4534534534', 2);

console.log(transaction); // see web3.eth.getTransaction

web3.eth.getTransactionReceipt

web3.eth.getTransactionReceipt(hashString [, callback])

通过一个交易哈希,返回一个交易的收据。

备注:处于pending状态的交易,收据是不可用的。

参数:

  • String - 交易的哈希

  • Function - 回调函数,用于支持异步的方式执行7。

返回值:

Object - 交易的收据对象,如果找不到返回null

  • blockHash: String - 32字节,这个交易所在区块的哈希。

  • blockNumber: Number - 交易所在区块的块号。

  • transactionHash: String - 32字节,交易的哈希值。

  • transactionIndex: Number - 交易在区块里面的序号,整数。

  • from: String - 20字节,交易发送者的地址。

  • to: String - 20字节,交易接收者的地址。如果是一个合约创建的交易,返回null。

  • cumulativeGasUsed: Number - 当前交易执行后累计花费的gas总值10。

  • gasUsed: Number - 执行当前这个交易单独花费的gas。

  • contractAddress: String - 20字节,创建的合约地址。如果是一个合约创建交易,返回合约地址,其它情况返回null。

  • logs: Array - 这个交易产生的日志对象数组。

示例:

var receipt = web3.eth.getTransactionReceipt('0x9fc76417374aa880d4449a1f7f31ec597f00b1f6f3dd2d66f4c9c6c445836d8b');

console.log(receipt);

{

  "transactionHash": "0x9fc76417374aa880d4449a1f7f31ec597f00b1f6f3dd2d66f4c9c6c445836d8b", 

 "transactionIndex": 0, 

 "blockHash": "0xef95f2f1ed3ca60b048b4bf67cde2195961e0bba6f70bcbea9a2c4e133e34b46", 

 "blockNumber": 3, 

 "contractAddress": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", 

 "cumulativeGasUsed": 314159, 

 "gasUsed": 30234, 

 "logs": [{ 

        // logs as returned by getFilterLogs, etc.  

   }, ...]

}

web3.eth.getTransactionCount

web3.eth.getTransactionCount(addressHexString [, defaultBlock] [, callback])

返回指定地址发起的交易数。

参数:

  • String - 要获得交易数的地址。

  • Number|String -(可选)如果未传递参数,默认使用web3.eth.defaultBlock定义的块,否则使用指定区块。

  • Function - 回调函数,用于支持异步的方式执行7。

返回值:

Number - 指定地址发送的交易数量。

示例:

var number = web3.eth.getTransactionCount("0x407d73d8a49eeb85d32cf465507dd71d507100c1");console.log(number); 

// 1

**web3.eth.sendTransaction**

web3.eth.sendTransaction(transactionObject [, callback])

发送一个交易到网络。

参数:

Object - 要发送的交易对象。

  • from: String - 指定的发送者的地址。如果不指定,使用web3.eth.defaultAccount。

  • to: String - (可选)交易消息的目标地址,如果是合约创建,则不填.

  • value: Number|String|BigNumber - (可选)交易携带的货币量,以wei为单位。如果合约创建交易,则为初始的基金。

  • gas: Number|String|BigNumber - (可选)默认是自动,交易可使用的gas,未使用的gas会退回。

  • gasPrice: Number|String|BigNumber - (可选)默认是自动确定,交易的gas价格,默认是网络gas价格的平均值 。

  • data: String - (可选)或者包含相关数据的字节字符串,如果是合约创建,则是初始化要用到的代码。

  • nonce: Number - (可选)整数,使用此值,可以允许你覆盖你自己的相同nonce的,正在pending中的交易11。

Function - 回调函数,用于支持异步的方式执行7。

返回值:

String - 32字节的交易哈希串。用16进制表示。

如果交易是一个合约创建,请使用web3.eth.getTransactionReceipt()在交易完成后获取合约的地址。

示例:

// compiled solidity source code using https://chriseth.github.io/cpp-ethereum/

var code = "603d80600c6000396000f3007c01000000000000000000000000000000000000000000000000000000006000350463c6888fa18114602d57005b6007600435028060005260206000f3";

web3.eth.sendTransaction({data: code}, function(err, address)

 { 

 if (!err)

    console.log(address); // "0x7f9fade1c0d57a7af66ab4ead7c2eb7b11a91385"

});

web3.eth.sendRawTransaction

web3.eth.sendRawTransaction(signedTransactionData [, callback])

发送一个已经签名的交易。比如可以用下述签名的例子:https://github.com/SilentCicero/ethereumjs-accounts

参数:

  • String - 16进制格式的签名交易数据。

  • Function - 回调函数,用于支持异步的方式执行7。

返回值:

String - 32字节的16进制格式的交易哈希串。

如果交易是一个合约创建,请使用web3.eth.getTransactionReceipt()在交易完成后获取合约的地址。

示例:

var Tx = require('ethereumjs-tx');

var privateKey = new Buffer('e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109', 'hex')

var rawTx = { 

 nonce: '0x00', 

 gasPrice: '0x09184e72a000',

   gasLimit: '0x2710', 

 to: '0x0000000000000000000000000000000000000000', 

  value: '0x00', 

  data: '0x7f7465737432000000000000000000000000000000000000000000000000000000600057'

}

var tx = new Tx(rawTx);

tx.sign(privateKey);

var serializedTx = tx.serialize();

//console.log(serializedTx.toString('hex'));

//0xf889808609184e72a00082271094000000000000000000000000000000000000000080a47f74657374320000000000000000000000000000000000000000000000000000006000571ca08a8bbf888cfa37bbf0bb965423625641fc956967b81d12e23709cead01446075a01ce999b56a8a88504be365442ea61239198e23d1fce7d00fcfc5cd3b44b7215f

web3.eth.sendRawTransaction(serializedTx.toString('hex'), function(err, hash) { 

 if (!err) 

   console.log(hash); // "0x7f9fade1c0d57a7af66ab4ead79fade1c0d57a7af66ab4ead7c2c2eb7b11a91385"

});

web3.eth.sign

web3.eth.sign(address, dataToSign, [, callback])

使用指定帐户签名要发送的数据,帐户需要处于unlocked状态。

参数:

  • String - 签名使用的地址

  • String - 要签名的数据

  • Function -(可选)回调函数,用于支持异步的方式执行7。

返回值:

String - 签名后的数据。

返回的值对应的是ECDSA(Elliptic Curve Digital Signature Algorithm)12签名后的字符串。

r = signature[0:64]
s = signature[64:128]
v = signature[128:130]

需要注意的是,如果你使用ecrecover,这里的v值是00或01,所以如果你想使用他们,你需要把这里的v值转成整数,再加上27。最终你要用的值将是27或2813。

示例:

var result = web3.eth.sign("0x135a7de83802408321b74c322f8558db1679ac20",  

  "0x9dd2c369a187b4e6b9c402f030e50743e619301ea62aa4c0737d4ef7e10a3d49"); // second argument is web3.sha3("xyz")

console.log(result); // "0x30755ed65396facf86c53e6217c52b4daebe72aa4941d89635409de4c9c7f9466d4e9aaec7977f05e923889b33c0d0dd27d7226b6e6f56ce737465c5cfd04be400"

备注:如果你使用以太坊的客户端进行签名时,它们会在你要签名的数据前增加前缀\x19Ethereum Signed Message:\n14,感谢读者@刘兵同学的反馈。

eth_sign

The sign method calculates an Ethereum specific signature with: sign(keccak256(“\x19Ethereum Signed Message:\n” + len(message) + message))).

By adding a prefix to the message makes the calculated signature recognisable as an Ethereum specific signature. This prevents misuse where a malicious DApp can sign arbitrary data (e.g. transaction) and use the signature to impersonate the victim.

web3.eth.call

web3.eth.call(callObject [, defaultBlock] [, callback])

在节点的VM中,直接执行消息调用交易。但不会将数据合并区块链中(这样的调用不会修改状态)。

参数:

  • Object - 返回一个交易对象,同web3.eth.sendTransaction。与sendTransaction的区别在于,from属性是可选的。

  • Number|String -(可选)如果不设置此值使用web3.eth.defaultBlock设定的块,否则使用指定的块。

  • Function -(可选)回调函数,用于支持异步的方式执行7。

返回值:

String - 函数调用返回的值。

示例:

var Web3 = require('web3');

if (typeof web3 !== 'undefined') {

  web3 = new Web3(web3.currentProvider);

} else {

  // set the provider you want from Web3.providers

  web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));

}

var from = web3.eth.accounts[0];

//部署合约的发布地址

/*合约内容如下

pragma solidity ^0.4.0;

contract Calc{

  function add(uint a, uint b) returns (uint){

    return a + b;

  }

}

*/

var to = "0xa4b813d788218df688d167102e5daff9b524a8bc";

//要发送的数据

//格式说明见: http://me.tryblockchain.org/Solidity-call-callcode-delegatecall.html

var data = "0x771602f700000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002";

var result = web3.eth.call({

  from : from,

  to : to, 

 data : data

});

//返回结果32字长的结果3

console.log(result);

web3.eth.estimateGas

web3.eth.estimateGas(callObject [, callback])

在节点的VM节点中执行一个消息调用,或交易。但是不会合入区块链中。返回使用的gas量。

参数:

同web3.eth.sendTransaction,所有的属性都是可选的。

返回值:

Number - 模拟的call/transcation花费的gas。

示例:

var result = web3.eth.estimateGas({

    to: "0xc4abd0339eb8d57087278718986382264244252f", 

    data: "0xc6888fa10000000000000000000000000000000000000000000000000000000000000003"

});

console.log(result); // "0x0000000000000000000000000000000000000000000000000000000000000015"

web3.eth.filter

参数:

  • String|Object - 字符串的可取值[latest,pending]。latest表示监听最新的区块变化,pending表示监听正在pending的区块。如果需要按条件对象过滤,如下:

  • fromBlock: Number|string - 起始区块号(如果使用字符串latest,意思是最新的,正在打包的区块),默认值是latest。

  • toBlock: Number|string - 终止区块号(如果使用字符串latest,意思是最新的,正在打包的区块),默认值是latest。

  • address: String - 单个或多个地址。获取指定帐户的日志。

  • topics: String[] - 在日志对象中必须出现的字符串数组。顺序非常重要,如果你想忽略主题,使用null。如,[null,’0x00…’],你还可以为每个主题传递一个单独的可选项数组,如[null,[‘option1’,’option1’]]。

返回值:

  • Object - 有下述方法的过滤对象。

  • filter.get(callback): 返回满足过滤条件的日志。

  • filter.watch(callback): 监听满足条件的状态变化,满足条件时调用回调7。

  • filter.stopWatching(): 停止监听,清除节点中的过滤。你应该总是在监听完成后,执行这个操作。

监听回调返回值:

String - 当使用latest参数时。返回最新的一个区块哈希值。

String - 当使用pending参数时。返回最新的pending中的交易哈希值。

Object - 当使用手工过滤选项时,将返回下述的日志对象。

  • logIndex: Number - 日志在区块中的序号。如果是pending的日志,则为null。

  • transactionIndex: Number - 产生日志的交易在区块中的序号。如果是pending的日志,则为null。

  • transactionHash: String,32字节 - 产生日志的交易哈希值。

  • blockHash: String,32字节 - 日志所在块的哈希。如果是pending的日志,则为null。

  • blockNumber: Number - 日志所在块的块号。如果是pending的日志,则为null。

  • address: String,32字节 - 日志产生的合约地址。

  • data: string - 包含日志一个或多个32字节的非索引的参数。

  • topics: String[] - 一到四个32字节的索引的日志参数数组。(在Solidity中,第一个主题是整个事件的签名(如,Deposit(address,bytes32,uint256)),但如果使用匿名的方式定义事件的情况除外)

事件监听器的返回结果,见后合约对象的事件。

示例:

var filter = web3.eth.filter('pending');

filter.watch(function (error, log) {

  console.log(log); //  {"address":"0x0000000000000000000000000000000000000000", "data":"0x0000000000000000000000000000000000000000000000000000000000000000", ...}

});

// get all past logs again.

var myResults = filter.get(function(error, logs){ ... });

...

// stops and uninstalls the filter

filter.stopWatching();

web3.eth.contract

web3.eth.contract(abiArray)

创建一个Solidity的合约对象,用来在某个地址上初始化合约。

参数:

Array - 一到多个描述合约的函数,事件的ABI对象。

返回值:

Object - 一个合约对象。

示例:

var MyContract = web3.eth.contract(abiArray);

// instantiate by address

var contractInstance = MyContract.at([address]);

// deploy new contrac

tvar contractInstance = MyContract.new([contructorParam1] [, contructorParam2], {data: '0x12345...', from: myAccount, gas: 1000000});

// Get the data to deploy the contract manually

var contractData = MyContract.new.getData([contructorParam1] [, contructorParam2], {data: '0x12345...'});

// contractData = '0x12345643213456000000000023434234'

你可以或者使用一个在某个地址上已经存在的合约,或者使用编译后的字节码部署一个全新的的合约。

// Instantiate from an existing address:

var myContractInstance = MyContract.at(myContractAddress);

// Or deploy a new contract:

// Deploy the contract asyncronous from Solidity file:

...const fs = require("fs");

const solc = require('solc')

let source = fs.readFileSync('nameContract.sol', 'utf8');

let compiledContract = solc.compile(source, 1);

let abi = compiledContract.contracts['nameContract'].interface;

let bytecode = compiledContract.contracts['nameContract'].bytecode;

let gasEstimate = web3.eth.estimateGas({data: bytecode});

let MyContract = web3.eth.contract(JSON.parse(abi));

var myContractReturned = MyContract.new(param1, param2,

 {

   from:mySenderAddress, 

  data:bytecode,

   gas:gasEstimate}, function(err, myContract){

    if(!err) {

       // NOTE: The callback will fire twice! 

      // Once the contract has the transactionHash property set and once its deployed on an address. 

      // e.g. check tx hash on the first call (transaction send)       if(!myContract.address) {  

         console.log(myContract.transactionHash) // The hash of the transaction, which deploys the contract   

    // check address on the second call (contract deployed)  

     } else { 

          console.log(myContract.address) // the contract address

       } 

      // Note that the returned "myContractReturned" === "myContract",

       // so the returned "myContractReturned" object will also get the address set. 

   }

  });

// Deploy contract syncronous: The address will be added as soon as the contract is mined.

// Additionally you can watch the transaction by using the "transactionHash" property

var myContractInstance = MyContract.new(param1, param2, {

data: myContractCode, gas: 300000, from: mySenderAddress

});

myContractInstance.transactionHash // The hash of the transaction, which created the contract

myContractInstance.address // undefined at start, but will be auto-filled later

示例:

// contract abi

var abi = [{

     name: 'myConstantMethod',

     type: 'function', 

    constant: true,

     inputs: [{ name: 'a', type: 'string' }], 

    outputs: [{name: 'd', type: 'string' }]

}, { 

    name: 'myStateChangingMethod', 

    type: 'function', 

    constant: false,

     inputs: [{ name: 'a', type: 'string' }, { name: 'b', type: 'int' }], 

    outputs: []

}, {   

  name: 'myEvent', 

    type: 'event', 

    inputs: [{name: 'a', type: 'int', indexed: true},{name: 'b', type: 'bool', indexed: false}]

}];

// creation of contract object

var MyContract = web3.eth.contract(abi);

// initiate contract for an address

var myContractInstance = MyContract.at('0xc4abd0339eb8d57087278718986382264244252f');

// call constant function

var result = myContractInstance.myConstantMethod('myParam');

console.log(result) // '0x25434534534'

// send a transaction to a function

myContractInstance.myStateChangingMethod('someParam1', 23, {value: 200, gas: 2000});

// short hand style

web3.eth.contract(abi).at(address).myAwesomeMethod(...);

// create filter

var filter = myContractInstance.myEvent({a: 5}, function (error, result) { 

 if (!error)

    console.log(result);

    /*

    { 

       address: '0x8718986382264244252fc4abd0339eb8d5708727',       

 topics: "0x12345678901234567890123456789012", "0x0000000000000000000000000000000000000000000000000000000000000005", 

       data: "0x0000000000000000000000000000000000000000000000000000000000000001",   

     ... 

   }  

  */

});

合约对象的方法

// Automatically determines the use of call or sendTransaction based on the method type

myContractInstance.myMethod(param1 [, param2, ...] [, transactionObject] [, defaultBlock] [, callback]);

// Explicitly calling this method

myContractInstance.myMethod.call(param1 [, param2, ...] [, transactionObject] [, defaultBlock] [, callback]);

// Explicitly sending a transaction to this method

myContractInstance.myMethod.sendTransaction(param1 [, param2, ...] [, transactionObject] [, callback])

;// Get the call data, so you can call the contract through some other means

var myCallData = myContractInstance.myMethod.getData(param1 [, param2, ...]);

// myCallData = '0x45ff3ff6000000000004545345345345..'

合约对象内封装了使用合约的相关方法。可以通过传入参数,和交易对象来使用方法。

参数:

  • String|Number - (可选)零或多个函数参数。如果传入一个字符串,需要使用十六进制编码,如,0xdedbeef。

  • Object - (可选)最后一个参数(如果传了callback,则是倒数第二个参数),可以是一个交易对象。查看web3.eth.sendTransaction的第一个参数说明来了解更多。注意,这里不需要填data和to属性。

  • Number|String -(可选)如果不设置此值使用web3.eth.defaultBlock设定的块,否则使用指定的块。

  • Function -(可选)回调函数,用于支持异步的方式执行7。

返回值:

String - 如果发起的是一个call,对应的是返回结果。如果是transaction,则要么是一个创建的合约地址,或者是一个transaction的哈希值。查看web3.eth.sendTransaction了解更多。

示例:

// creation of contract object

var MyContract = web3.eth.contract(abi);

// initiate contract for an address

var myContractInstance = MyContract.at('0x78e97bcc5b5dd9ed228fed7a4887c0d7287344a9');

var result = myContractInstance.myConstantMethod('myParam');

console.log(result) // '0x25434534534'

myContractInstance.myStateChangingMethod('someParam1', 23, {value: 200, gas: 2000}, function(err, result){ ... });

合约对象的事件

你可以像web3.eth.filter这样使用事件,他们有相同的方法,但需要传递不同的对象来创建事件过滤器。

参数:

  • Object - 你想返回的索引值(过滤哪些日志)。如,{‘valueA’: 1, ‘valueB’: [myFirstAddress, mySecondAddress]}。默认情况下,所以有过滤项被设置为null。意味着默认匹配的是合约所有的日志。

  • Object - 附加的过滤选项。参见web3.eth.filter的第一个参数。默认情况下,这个对象会设置address为当前合约地址,同时第一个主题为事件的签名。

  • Function -(可选)传入一个回调函数,将立即开始监听,这样就不用主动调用myEvent.watch(function(){})7。

回调返回值:

Object - 事件对象,如下:

  • address: String,32字节 - 日志产生的合约地址。

  • args: Object - 事件的参数。

  • blockHash: String,32字节 - 日志所在块的哈希。如果是pending的日志,则为null。

  • blockNumber: Number - 日志所在块的块号。如果是pending的日志,则为null。

  • logIndex: Number - 日志在区块中的序号。如果是pending的日志,则为null。

  • event: String - 事件名称。

  • removed: bool - 标识产生事件的这个交易是否被移除(因为孤块),或从未生效(被拒绝的交易)。

  • transactionIndex: Number - 产生日志的交易在区块中的序号。如果是pending的日志,则为null。

  • transactionHash: String,32字节 - 产生日志的交易哈希值。

示例:

var MyContract = web3.eth.contract(abi);

var myContractInstance = MyContract.at('0x78e97bcc5b5dd9ed228fed7a4887c0d7287344a9');

// watch for an event with {some: 'args'}

var myEvent = myContractInstance.MyEvent({some: 'args'}, {fromBlock: 0, toBlock: 'latest'});

myEvent.watch(function(error, result){ 

  ...

});

// would get all past logs again.

var myResults = myEvent.get(function(error, logs){ ... });.

..

// would stop and uninstall the filter

myEvent.stopWatching();

合约 allEvents

var events = myContractInstance.allEvents([additionalFilterObject]);

// watch for changes

events.watch(function(error, event){

  if (!error)

    console.log(event);

});

// Or pass a callback to start watching immediately

var events = myContractInstance.allEvents([additionalFilterObject,] function(error, log){

  if (!error) 

   console.log(log);

});

调用合约创建的所有事件的回调。

参数:

  • Object - 附加的过滤选项。参见web3.eth.filter的第一个参数。默认情况下,这个对象会设置address为当前合约地址,同时第一个主题为事件的签名。

  • Function -(可选)传入一个回调函数,将立即开始监听,这样就不用主动调用myEvent.watch(function(){})7。

回调返回值:

Object - 详见合约对象的事件了解更多。

示例:

var MyContract = web3.eth.contract(abi);

var myContractInstance = MyContract.at('0x78e97bcc5b5dd9ed228fed7a4887c0d7287344a9');

// watch for an event with {some: 'args'}

var events = myContractInstance.allEvents({fromBlock: 0, toBlock: 'latest'});

events.watch(function(error, result){

   ...

});

// would get all past logs again.

events.get(function(error, logs){ ... });

...

// would stop and uninstall the filter

myEvent.stopWatching();

web3.eth.getCompilers

web3.eth.getCompilers([callback])

返回可用的编译器。

参数值:

Function -(可选)回调函数,用于支持异步的方式执行7。

返回值:

  • Array - 返回一个字符串数组,可用的编译器。

web3.eth.compile.solidity

web3.eth.compile.solidity(sourceString [, callback])

编译Solidity源代码。

参数:

  • String - Solidity源代码。

  • Function -(可选)回调函数,用于支持异步的方式执行7。

返回值:

Object - 合约和编译信息。

示例:

var source = "" +

     "contract test {\n" +

    "   function multiply(uint a) returns(uint d) {\n" +  

  "       return a * 7;\n" + 

   "   }\n" +  

  "}\n";

var compiled = web3.eth.compile.solidity(source);

console.log(compiled);

 // { 

 "test": {

    "code": "0x605280600c6000396000f3006000357c010000000000000000000000000000000000000000000000000000000090048063c6888fa114602e57005b60376004356041565b8060005260206000f35b6000600782029050604d565b91905056", 

   "info": {

      "source": "contract test {\n\tfunction multiply(uint a) returns(uint d) {\n\t\treturn a * 7;\n\t}\n}\n", 

     "language": "Solidity",  

    "languageVersion": "0", 

     "compilerVersion": "0.8.2", 

     "abiDefinition": [  

      { 

         "constant": false, 

         "inputs": [ 

           {  

            "name": "a",  

            "type": "uint256"

            } 

         ],

          "name": "multiply", 

         "outputs": [  

          { 

             "name": "d", 

             "type": "uint256" 

           } 

         ],  

        "type": "function" 

       }  

    ], 

     "userDoc": { 

       "methods": {}  

    },  

    "developerDoc": { 

       "methods": {}  

    } 

   } 

 }

}

web3.eth.compile.lll

web3. eth.compile.lll(sourceString [, callback])

编译LLL源代码。

参数:

  • String - LLL源代码。

  • Function -(可选)回调函数,用于支持异步的方式执行7。

返回值:

String - 十六进制格式编译后的LLL编码。

示例:

var source = "...";

var code = web3.eth.compile.lll(source);

console.log(code); // "0x603880600c6000396000f3006001600060e060020a600035048063c6888fa114601857005b6021600435602b565b8060005260206000f35b600081600702905091905056"

web3.eth.compile.serpent

web3.eth.compile.serpent(sourceString [, callback])

编译serpent源代码。

参数:

  • String - serpent源代码。

  • Function -(可选)回调函数,用于支持异步的方式执行7。

返回值:

String - 十六进制格式的编译后的serpent编码。

**web3.eth.namereg**

web3.eth.namereg

返回一个全球注意的对象。

使用方式:

查看这里的例子:https://github.com/ethereum/web3.js/blob/master/example/namereg.html

4.4 web3.db

web3.db.putString

web3.db.putString(db, key, value)

这个方法应当在我们打算以一个本地数据库的级别存储一个字符串时使用。

参数:

  • String - 存储使用的数据库。

  • String - 存储的键。

  • String - 存储的值。

返回值:

Boolean - true表示成功,否则返回false。

示例:

web3.db.putString('testDB', 'key', 'myString') // true

**web3.db.getString**

web3.db.getString(db, key)

从本地的leveldb数据库中返回一个字符串。

参数:

  • String - 存储使用的数据库。

  • String - 存储的键。

返回值:

String - 存储的值。

示例:

var value = web3.db.getString('testDB', 'key');

console.log(value); // "myString"

**web3.db.putHex**

web3.db.putHex(db, key, value)

在本地的leveldb中存储二进制数据。

参数:

  • String - 存储使用的数据库。

  • String - 存储的键。

  • String - 十六进制格式的二进制。

返回值:

Boolean - 成功返回true,失败返回false。

示例:

web3.db.putHex('testDB', 'key', '0x4f554b443'); // true

**web3.db.getHex**

web3.db.getHex(db, key)

返回本地的leveldb中的二进制数据。

参数:

  • String - 存储使用的数据库。

  • String - 存储的键。

返回值:

String - 存储的十六进制值。

示例:

var value = web3.db.getHex('testDB', 'key');

console.log(value); // "0x4f554b443"

5

参考文档

1] Web3 JavaScript app API英文官网接口文档(https://github.com/ethereum/wiki/wiki/JavaScript-API#web3ethaccounts)

2] WEB3.JS代码(https://github.com/ethereum/web3.js)

3] WEB3的中文帮助文档地址(https://blog.youkuaiyun.com/qq_28114645/article/details/78802176)

4] 以太坊DApp开发入门教程——区块链投票系统 - 汇智网(https://blog.youkuaiyun.com/mongo_node/article/details/79424450)

5] Web3与智能合约交互实战 - 熊丽兵(https://blog.youkuaiyun.com/xilibi2003/article/details/80338894)

拓展阅读:

辉哥的文章其他:Solidity语言编辑器REMIX指导大全

如何在Remix环境下进行Solidity代码单步调试

本文作者:HiBlock区块链技术布道群-笔名辉哥

原文发布于简书,原文地址:https://www.jianshu.com/p/47174718960b

加微信baobaotalk_com,加入技术布道群

以下是我们的社区介绍,欢迎各种合作、交流、学习:)

image

上位机开发实战指南:从C#/Qt技术选型到工业设备集成 上位机开发是工业自动化领域的核心技术,指在控制系统中负责监控、数据采集和人机交互的计算机系统。其工作原理是通过通信协议(如Modbus、OPC UA等)与下位机设备进行数据交换,实现实时监控和控制指令下发。在工业4.0和智能制造背景下,上位机开发的技术价值日益凸显,能够有效解决设备数据采集不稳定、界面响应卡顿等工程实践问题。典型应用场景包括生产线监控系统、智能仓储控制台、能源管理系统等工业自动化领域。针对C#与Qt等技术选型,需要根据Windows环境或跨平台需求进行合理选择,同时掌握通信协议解析和工业设备 阅读详情

相关推荐

宠物商店(pet-shop) 学习笔记

宠物商店(pet-shop) 学习笔记 truffle 可以算是一个超级强大的 Ethereum 开发工具集, 集各种的功能集一身, 今天, 照着官方的文档, 和 手把手的教程, 完成了其中提供的一个demo. truffle的目录结构 目录树 demo ├── build │ └── contracts │ ├── Migrations.json │ ...

Quartz's Blog 1万+

第七课 技术小白如何开发一个DAPP区块链应用(以宠物商店为例)

1. 文章摘要 #####【本文目标】 通过逐步的指导和截图举证,一步步带领一个技术小白完成一个宠物商店DAPP应用的开发和部署。 #####【环境前置条件】 参考《第一课 如何在WINDOWS环境下搭建以太坊开发环境》,已完成Ubuntu的安装,已完成TRUFFLE,Ganache-cli,lite-server的安装; 本案例是通过WINDOWS的XSHELL客户端同本机的Ubuntu命令操...

辉哥的技术投资路 2462

开发、部署第一个去中心化应用(Dapp) - 宠物商店

开发、部署第一个去中心化应用(Dapp) - 宠物商店 环境部署 1.安装Node: http://nodejs.org/ 在官网进行下载 查看npm是否安装完成: 2.创建项目并进入 mkdir pet-shop-tutorial cd pet-shop-tutorial 3.使用truffle unbox 创建项目 truffle unbox pet-shop 4.项目目录结构 contracts/ 智能合约的文件夹,所有的智能合约文件都放置在这里,里面包含一个重要的合约 Migration

weixin_45686964的博客 933

跟着cryptokitties(以太坊云养猫)学写智能合约(上)

cryptokitties(以太坊云养猫)是近期出现在以太坊区块链上一个游戏。超级可爱的猫形象,再配合上繁殖,配种,拍卖这样丰富的玩法,一下子就引爆了以太坊的区块链。这款游戏的核心是基于以太坊的智能合约,也是第一款基于智能合约的游戏。这款游戏除了繁殖时候的基因工程合约以外,其他合约都是开源的,她的源码对于学习智能合约的编写有着很大的启发意义。下面是我的一点点对于智能合约和cryptokitties

mergerly的专栏 6931

3、宠物商店智能合约实战(truffle智能合约项目实战)

只是一切在内部发生,没有metamask,无法明显显示,若安装metamask就会是否确认转钱的。新的私有链无智能合约,这个cmd的develop开发者模式既不直观也不能保存之前的结果。我们可以保存此私有链,下次再启动就可以选择之前的私有链,一启动页面,之前的领养也有记录。实现领养功能,及用户点击领养时,用户与狗狗就建立关系,关系要存到合约并不能被篡改。在控制台可以看到,查询余额明显变少了,所以前面的代币转账也是消耗的账户的gas。我们在chrome浏览器打开,直接点击领养,会成功,内部已经消耗了gas。

吾名招财的博客 2271

USB 3.0 Rx Detect之超速U盘的识别

USB 3.0 Rx Detect之超速U盘的识别

汽车以太网和SOA 2万+

web3.js跨源请求解决方案

       在基于以太坊进行DAPP开发中,会使用到web3.js与以太坊时行交互,当产品发布时会使用公共以太坊结点,因产品的域名和公共以太坊结点域名不一致,出现浏览器跨域问题,浏览器会出现如下错误信息: 已拦截跨源请求:同源策略禁止读取位于 https://ropsten.infura.io/&lt;your-key&gt;的远程资源。 (原因:CORS 请求未能成功)。 可使用代理进行...

深藏功与名 2046

Transformer时序预测避坑指南:TFT在风电场的5个实战经验

本文分享了Temporal Fusion Transformer在风电场功率预测中的五个实战经验,涵盖数据预处理、模型调优、显存优化、注意力机制解读及在线部署。针对风电数据噪声大、概念漂移等挑战,提供了从构建数据质量标签到高效超参调优的具体方案,并强调利用Transformer架构的可解释性进行业务洞察,助力实现稳健的工业级时序预测。

bert9linguist的博客 462

区块链DAPP-基于Truffle框架的宠物商店

1.业务背景 Pete有一个宠物店(Pete's Pet Shop),该商店在给定时间可以容纳16只宠物,并且已经有了宠物数据。他希望基于Truffle框架开发一个完全去中心化应用,让大家来领养宠物。 2.环境准备 安装Node:下载地址https://nodejs.org/en/download/ 安装Truffle :npm install -g truffle 安装ganache-cli:npm install -g ganache-cli 注意:Node、Truffle、ganach.

ytsm04的专栏 3710

8台 × 8卡 910B NPU之顶尖大模型选型分析

本文对比了2026年主流大语言模型在昇腾910B NPU集群上的部署方案。重点评估了GLM5、MiniMax M2.5、Kimi K2.5、DeepSeek V3.2和Qwen 3.5旗舰版等候选模型,从部署需求(显存占用)、能力表现(基准测试、多模态支持)和NPU生态适配度三个维度进行分析。结果显示DeepSeek V3.2综合表现最优:支持BF16/W8A8/INT4量化,在4TB显存环境下可实现2000+ TPS,首token延迟<100ms,且具备官方NPU支持。备选方案Qwen 3.5旗舰版

FeelTouch Labs 763

【ComfyUI】Wan2.2 Animate 背景保留动作迁移视频生成

本文介绍了一个基于ComfyUI的高精度视频生成工作流"Wan2.2 Animate",该系统融合动作捕捉、图像拼接和LoRA加权等技术,能自动识别人脸并完成精准动作迁移,同时保持背景稳定。工作流采用模块化设计,包含输入提取、图像融合、模型加载等关键节点,核心模型Wan2.2-Animate-14B支持fp8精度与BlockSwap控制。流程分为图像输入、动作提取、多图合成等五个阶段,通过文本提示编码器和图像语义编码器实现语义驱动的动作生成,最终输出高质量视频,适用于虚拟形象驱动和

Mr数据杨 2274

区块链开发工具大全:Blockchain for Software Engineers推荐的Truffle、Ganache和IPFS终极指南 [特殊字符]

在当今快速发展的区块链技术领域,掌握正确的开发工具是成功的关键。Blockchain for Software Engineers项目为软件工程师们精心整理了一套完整的区块链开发工具资源,特别是以太坊生态中的三大核心工具:Truffle、Ganache和IPFS。这些工具能够帮助开发者从零开始构建去中心化应用(DApp),大大提升开发效率和代码质量。 ## 📊 为什么需要专业的区块链开发工具?

gitblog_00457的博客 1007

2023华为OD面试手撕真题【最长公共前缀】

2023华为OD面试手撕真题【最长公共前缀】

MISAYAONE的博客 5243

HiBlock区块链技术布道:Learning blockchain together

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34261415的博客 370

为YOLOv11引入自适应特征融合模块(ASFF)

本文探讨了在YOLOv11中引入ASFF(自适应空间特征融合)模块以解决多尺度目标检测性能不均衡的问题。作者分析了传统FPN固定融合策略的缺陷,详细介绍了ASFF模块的实现原理,包括动态权重生成网络设计和特征融合机制。通过将ASFF集成到YOLOv11颈部网络,实现了特征在双向流动时的自适应融合,在复杂场景下mAP提升1.2%而推理时间仅增加3-5ms。文章还分享了训练调参技巧和部署注意事项,指出ASFF特别适合交通监控等目标尺度变化大的场景,但强调需根据实际需求平衡模型复杂度与性能。最后提供了工程实践建议

as1225120794的博客 322

Java 大视界 -- 基于 Java+Flink 构建实时电商交易风控系统实战(436)

本文介绍基于Java+Flink构建实时电商交易风控系统的实战经验。系统采用分层架构设计,包含数据采集层、实时计算层、规则引擎层、数据存储层和应用服务层,实现毫秒级风险识别与拦截。核心组件包括Flink 1.17处理交易数据流、Drools规则引擎动态匹配风险规则、Redis缓存热点数据等。文章详细提供了开发环境配置清单和Maven依赖说明,确保系统具备低延迟(≤200ms)、高吞吐(10万TPS)和高可用性(99.99%)特性。该方案已通过生产环境验证,可有效应对恶意刷单、盗刷支付等电商交易风险。

【青云交】华为云云享专家 | 阿里云开发者社区专家博主 技术圈个人影响力前 9 | 博客之星 TOP12 优快云 首位四榜(原力榜 / 作者周榜 / 领军人物 / 综合热榜)榜首,破平台纪录! 苏州地区全榜霸榜,感恩全网十多万粉丝同行! 3943

第十二课 从宠物商店案例看DAPP架构和WEB3.JS交互接口

1. 文章摘要 【本文目标】 了解ETH生态下DAPP去中心化应用程序的框架和交互流程,了解WEB3.JS的作用和接口函数。 【前置条件】 完成了《第六课 技术小白如何开发一个DAPP区块链应用(以宠物商店为例)》的学习实践,对智能合约了解。 【技术收获】 1). DAPP架构 2). ETH节点框架 3).宠物商店的APP.js文件的业务处理流程图和函数介绍 4).web3.js接口 【实操课...

辉哥的技术投资路 959

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

怎么使用Web3.js开发一个简单的Dapp

以太坊是一个基于区块链的开源去中心化平台,用于运行我们的智能合约。它不仅是一种加密货币,还是一种复杂的应用程序,可以在区块链上执行智能合约,以避免交易中出现任何欺诈企图。当满足预定义的条件时,它会自动执行。基于智能合约的交易的好处在于,这些交易是不可逆转的,但可以追踪。它不受单个组织的控制,并在不受中央控制的区块链网络上运行。一旦将 web3.js 作为项目的依赖项,您需要做的就是使用提供程序的实例实例化 web3 对象。在区块链中,数据可以作为块添加,其中每个块都有前一个块的地址,因此称为区块链。

qq_37116560的博客 1488

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

DPanel 一款更适合国人的 Docker 管理工具

DPanel 是个开源的Docker可视化管理面板,功能相当全面。它能帮我们管理容器、镜像、文件、网络等等,几乎涵盖了Docker的所有常用操作。而且,DPanel的界面设计得很人性化,操作起来特别顺手,就算是新手也能快速上手。最棒的是,它对中文用户特别友好,全中文界面,再也不用担心看不懂英文提示了。

901

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

docker检测与管理工具

【代码】docker检测与管理工具。

weixin_60092693的博客 391

国产神器DPanel:更适合中文环境的Docker可视化控制台(结尾附链接直达)

项目亮点 Github 1.6k+ Star | 支持容器/镜像/Compose全生命周期管理步骤1:拉取轻量版镜像 步骤2:一键启动管理面板 💡 访问地址:(首次访问需创建管理员账户) 🏆 核心功能全景 功能模块 关键能力 典型场景 镜像中心 多仓库加速/批量拉取 开发环境快速搭建 容器监控 实时资源占用分析 生产环境故障排查 网络拓扑 可视化容器通信关系 微服务架构调试 存储管理 卷挂载状态追踪 数据持久化保障 ✨ 如果本文对您有帮助,欢迎点赞收藏关注三连

The God Of BigData 的博客 2497

SAP学习笔记 - 开发05 - Fiori UI5 开发环境搭建2 Fiori Tools插件安装,SEGW创建后台程序,注册服务和Gateway Client确认,从SAP抽数据显示到页面

本章继续学习Fiori UI5开发环境搭建,包括 VSCode 安装Fiori Tools插件,SEGW 创建后台程序,注册服务,Gateway Client确认服务,以及提到了OData官网,要查资料可以到这里查。然后还讲了在VSCode中创建的Project中如何通过创建的SEGW服务来抽取SAP的数据。

shi_ly的专栏 4056

区块链案例实践报告_1_DAPP宠物商店

本文为个人学习报告,不做他用。 关于宠物商店的教程,网上已经给出了许多。因此,本文并不会十分详细地讲解具体操作,只是简述开发流程。 具体的实现步骤可参考 文字教程:https://www.jianshu.com/p/9844d97ef1d0 视频教程:https://www.bilibili.com/video/BV1ds41177Cy?p=7 以及我个人的部分代码:https://github.com/yumiki-syou/pet-shop 宠物商店学习报告项目目标项目介绍开发环境说明开发流程1.创建项

qq_29212049的博客 2033
上一篇: 30万精英人才大迁徙:进军区块链,他们是赌徒还是信徒?
下一篇: 区块链100讲:从宠物商店案例看DAPP架构和WEB3.JS交互接口
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值