其实除了买家后面还有,不过我看了一会实在是放弃了,因为是个全栈视频,web相关我实在是不行了,因为js我真是一点都不会。教程中用react库,在web上链接到ganache这个虚拟区块链上,同时metamask也获取ganache数据显示出来,最后全栈为用户提供了web接口,这就是全部过程。最有意思的是,这个系统所有的调用都用的js,只有脚本用的solidity。脚本用的面向对象,其实面向对象长得都一样,我用C++的底子完全可以理解。这就是我学会的东西。我在网上看到还有用其它语言写合约的。
其实我想学会的是设计dapp,而smart contract只是二代区块链,教程的题目也是dapp university。不过仔细想一下,web不管是调用smart contract还是dapp,效果都是一样的,只不过smart contract需要付钱,dapp不需要付钱,再有些其它的修改罢了,我理解为dapp只是在smart contract的应用场景上多了一些,本质没有太大变化。
下面尽快学习网络和操作系统的基本知识,保证工作能做好,后续是搞js还是换语言搞dapp还是怎么样,再说吧,该定计划了蓝莓侠
合约
// the file is for creating smart contract
pragma solidity ^0.5.0;
contract Marketplace {
//state variable
string public name;
mapping(uint => Product) public products; //key and value,id and smartcontract
uint public productCount = 0;//solidity dosen't has size function for mapping
struct Product {
uint id; //unique
string name;
uint price;
address payable owner;
bool purchased;
}
event ProductCreated(
uint id,
string name,
uint price,
address payable owner,
bool purchased
);
event ProductPurchased(
uint id,
string name,
uint price,
address payable owner,
bool purchased
);
constructor() public {
name = "Dapp University Marketplace";
}
function createProduct(string memory _name, uint _price) public{
//Make sure parameters are correct
require(bytes(_name).length > 0);
require(_price > 0);
//Increment product count
productCount++;//因为productCount初始值为0,所以这个要放在创建product之前
// Create the product,将新建的product加入哈希中
products[productCount] = Product(productCount, _name, _price, msg.sender, false);//msg是个全局变量,sender就是调用ganache的那个用户,也就是谁调创建这个合约,msg.sender就是谁
//Trigger an event
emit ProductCreated(productCount, _name, _price, msg.sender, false);
}
//<按照id将product从协议中提出来,修改后再放回去,这样可以保证原子性,智能合约肯定要考虑并发的
function purchaseProduct(uint _id) public payable {
// Fetch the product
Product memory _product = products[_id];
// Fetch the owner
address payable _seller = _product.owner;
// Make sure the product has a valid id
require(_product.id > 0 && _product.id <= productCount);
// Require that there is enough Ether in the transaction
require(msg.value >= _product.price);
// Require that the product has not been purchased already
require(!_product.purchased);
// Require that the buyer is not the seller
require(_seller != msg.sender);
// Transfer ownership to the buyer
_product.owner = msg.sender;
// Mark as purchased
_product.purchased = true;
// Update the product
products[_id] = _product;
// Pay the seller by sending them Ether
address(_seller).transfer(msg.value);
// Trigger an event
emit ProductPurchased(productCount, _product.name, _product.price, msg.sender, true);
}
}
调用过程
//it's for calling smartcontract
const Marketplace = artifacts.require('./Marketplace.sol') //import the contract into the test file, of course the smartcontact is defined in this file
require('chai')
.use(require('chai-as-promised'))
.should()
contract('Marketplace', ([deployer, seller, buyer]) =>{
let marketplace
before(async () => {
marketplace = await Marketplace.deployed()//deployed这个函数是异步的,await关键字为了将异步变为同步
})
describe('deployment', async() => { //mocha which is a framework of js
it('deploys successfully', async()=> {
const address = await marketplace.address
assert.notEqual(address, 0x0) //chai for assert
assert.notEqual(address, null)
assert.notEqual(address, '')
assert.notEqual(address, undefined)
})
it('has a name', async() => {
const name = await marketplace.name()
assert.equal(name, 'Dapp University Marketplace')
})
})
describe('products', async() => { //mocha which is a framework of js
let result, productCount
before(async () => {
result = await marketplace.createProduct('iPhone X', web3.utils.toWei('1','Ether'),{from:seller })//使用的时候都是用的wei为单位,但是因为wei特别的小,IPHONEX价格为2以太币比较合适,就用个转换函数
productCount = await marketplace.productCount()
})
it('creates products', async() => {
// success
assert.equal(productCount, 1)
const event = result.logs[0].args
assert.equal(event.id.toNumber(), productCount.toNumber(), 'id is correct')
assert.equal(event.name, 'iPhone X', 'name is correct')
assert.equal(event.price, '1000000000000000000', 'price is correct')
assert.equal(event.owner,seller ,'owner is correct')
assert.equal(event.purchased,false,'purchased is correct')
// FAILURE: Product must have a name
await await marketplace.createProduct('', web3.utils.toWei('1', 'Ether'), { from: seller }).should.be.rejected;
// FAILURE: Product must have a price
await await marketplace.createProduct('iPhone X', 0, { from: seller }).should.be.rejected;
})
it('lists products', async() => {
const product = await marketplace.products(productCount)
assert.equal(product.id.toNumber(), productCount.toNumber(), 'id is correct')
assert.equal(product.name, 'iPhone X', 'name is correct')
assert.equal(product.price, '1000000000000000000', 'price is correct')
assert.equal(product.owner,seller ,'owner is correct')
assert.equal(product.purchased,false,'purchased is correct')
})
it('sells products', async () => {
// Track the seller balance before purchase
let oldSellerBalance
oldSellerBalance = await web3.eth.getBalance(seller)
oldSellerBalance = new web3.utils.BN(oldSellerBalance)
// SUCCESS: Buyer makes purchase
result = await marketplace.purchaseProduct(productCount, { from: buyer, value: web3.utils.toWei('1', 'Ether')})
// Check logs
const event = result.logs[0].args
assert.equal(event.id.toNumber(), productCount.toNumber(), 'id is correct')
assert.equal(event.name, 'iPhone X', 'name is correct')
assert.equal(event.price, '1000000000000000000', 'price is correct')
assert.equal(event.owner, buyer, 'owner is correct')
assert.equal(event.purchased, true, 'purchased is correct')
// Check that seller received funds
let newSellerBalance
newSellerBalance = await web3.eth.getBalance(seller)
newSellerBalance = new web3.utils.BN(newSellerBalance)
let price
price = web3.utils.toWei('1', 'Ether')
price = new web3.utils.BN(price)
const exepectedBalance = oldSellerBalance.add(price)
// assert.equal(newSellerBalance.toString(), exepectedBalance.toString())
// FAILURE: Tries to buy a product that does not exist, i.e., product must have valid id
await marketplace.purchaseProduct(99, { from: buyer, value: web3.utils.toWei('1', 'Ether')}).should.be.rejected; // FAILURE: Buyer tries to buy without enough ether
// FAILURE: Buyer tries to buy without enough ether
await marketplace.purchaseProduct(productCount, { from: buyer, value: web3.utils.toWei('0.5', 'Ether') }).should.be.rejected;
// FAILURE: Deployer tries to buy the product, i.e., product can't be purchased twice
await marketplace.purchaseProduct(productCount, { from: deployer, value: web3.utils.toWei('1', 'Ether') }).should.be.rejected;
// FAILURE: Buyer tries to buy again, i.e., buyer can't be the seller
await marketplace.purchaseProduct(productCount, { from: buyer, value: web3.utils.toWei('1', 'Ether') }).should.be.rejected;
})
})
})