tripio
Version:
Tripio SDK for JavaScript
644 lines (620 loc) • 23.3 kB
JavaScript
import ABI from '../abis/roomnight-customer';
import VABI from '../abis/roomnight-vendor';
import TABI from '../abis/roomnight-token';
import AABI from '../abis/roomnight-admin';
import bs58 from 'bs58';
import { Buffer } from 'buffer';
/**
* RoomNightCustomer
* @class
*/
class RoomNightCustomer {
constructor(web3, contractAddress, vendorAddress, adminAddress, options) {
this.web3 = web3;
this.contractAddress = contractAddress;
this.contract = this.web3.eth.contract(ABI).at(contractAddress);
this.vendorContract = this.web3.eth.contract(VABI).at(vendorAddress);
this.adminContract = this.web3.eth.contract(AABI).at(adminAddress);
}
/**
* Convert IPFS address from base58 to hex format(begin with 0x)
* @param {String} ipfs IPFS address with base58 encoded
* @returns {String} IPFS with hex format(begin with 0x)
*/
ipfsBase58ToHex(ipfs) {
let ipfsBuffer = bs58.decode(ipfs)
var ipfsHexString = ipfsBuffer.toString('hex');
if(ipfsHexString.length != 68) {
return null;
}
ipfsHexString = '0x' + ipfsHexString.slice(4);
return ipfsHexString
}
/**
* Conver IPFS address from hex format to base58 format
* @param {String} ipfs IPFS address with hex format
* @returns {String} IPFS with base58 format
*/
ipfsHexToBase58(ipfs) {
ipfs = ipfs.replace('0x', '');
if(ipfs.length != 64) {
return null;
}
let ipfsBuffer = Buffer.from('1220' + ipfs, 'hex');
return bs58.encode(ipfsBuffer);
}
/**
*
* @param {token} token
* @returns {Promise} {Contract instance}
*/
_getTokenContractInstance(token) {
return new Promise((resolve, reject) => {
this.adminContract.getToken(token, (err, res) => {
if(err) {
reject(err);
}else {
let tokenContract = this.web3.eth.contract(TABI).at(res[3]);
resolve(tokenContract);
}
});
});
}
/**
* The name of current room night token
* @returns {Promise} {String} The name of current room night token
*/
name() {
return new Promise((resolve, reject) => {
this.contract.name((err, res) => {
if(err) {
reject(err);
}
else {
resolve(res);
}
});
});
}
/**
* The symbol of current room night token
* @returns {Promise} {String} The symbol of current room night token
*/
symbol() {
return new Promise((resolve, reject) => {
this.contract.symbol((err, res) => {
if(err) {
reject(err);
}
else {
resolve(res);
}
});
});
}
/**
* The URI of token's information
* @param {Number} tokenId Token id
* @returns {Promise} {String} The URI of token. E.g: http://ipfs.tripiochina.cn/api/v0/cat/Qmaj8UWNjTzBMBHkkaqSiyax2nFgiwYP2ewxnhGBucn6S8
*/
tokenURI(tokenId) {
return new Promise((resolve, reject) => {
this.contract.tokenURI(tokenId, (err, res) => {
if(err) {
reject(err);
}
else {
resolve(res);
}
});
});
}
/**
* The balance of any address
* @param {String} owner The owner address of some token
* @returns {Promise} {BigNumber} The token balance
*/
balanceOf(owner) {
return new Promise((resolve, reject) => {
this.contract.balanceOf(owner, (err, res) => {
if(err) {
reject(err);
}
else {
resolve(res);
}
});
});
}
/**
* Get the owner of any token
* @param {Number} tokenId The room night token id
* @returns {Promise} {String} The token's owner address
*/
ownerOf(tokenId) {
return new Promise((resolve, reject) => {
this.contract.ownerOf(tokenId, (err, res) => {
if(err) {
reject(err);
}
else {
resolve(res);
}
});
});
}
/**
* Get the approved address for a single room night token
* @param {Number} tokenId The room night token id
* @returns {Promise} {String} The approved address for this token, or the zero address if there is none
*/
getApproved(tokenId) {
return new Promise((resolve, reject) => {
this.contract.getApproved(tokenId, (err, res) => {
if(err) {
reject(err);
}
else {
resolve(res);
}
});
});
}
/**
* Query if an address is an authorized operator for another address
* @param {String} owner The address that owns the token
* @param {String} operator The address that acts on behalf of the owner
* @returns {Promise} {Boolean} True if operator is an approved `operator` for `owner`, false otherwise
*/
isApprovedForAll(owner, operator) {
return new Promise((resolve, reject) => {
this.contract.isApprovedForAll(owner, operator, (err, res) => {
if(err) {
reject(err);
}
else {
resolve(res);
}
});
});
}
/**
* Whether the token is in refund applications
* @param {Number} rnid The room night token id
* @returns {Promise} {Boolean} True if token in refund applications, false otherwise
*/
isRefundApplied(rnid) {
return new Promise((resolve, reject) => {
this.contract.isRefundApplied(rnid, (err, res) => {
if(err) {
reject(err);
}
else {
resolve(res);
}
});
});
}
/**
* Get the room night infomation in detail
* @param {Number} rnid The room night token id
* @returns {Promise} {vendorId: BigNumber, rateplanId: BigNumber, tokenId: BigNumber, price: BigNumber, timestamp: BigNumber, date: BigNumber, ipfs: Hex String, rateplanName: String}
* * vendorId: Vendor id
* * rateplanId: Rateplan id
* * tokenId: ERC2.0 Token id
* * price: ERC2.0 price of RP
* * timestamp: Create time: UTC timestamp(s)
* * date: Order date E.g: 20180621
* * ipfs: The IPFS's address of rateplan's desc(Hex String)
* * rateplanName: Rateplan name
*/
roomNight(rnid) {
return new Promise((resolve, reject) => {
this.contract.roomNight(rnid, (err, res) => {
if(err) {
reject(err);
}
else {
resolve({
vendorId :res[0],
rateplanId: res[1],
tokenId: res[2],
price: res[3],
timestamp: res[4],
date: res[5],
ipfs: this.ipfsHexToBase58(res[6]),
rateplanName: res[7]
});
}
});
});
}
/**
* Get all the room nights of the msg.sender(Customer or Vendor)
* @param {Number} from The begin id, if id = 0 search from the begin
* @param {Number} limit The limit of one page
* @param {Boolean} isVendor Is vendor or not
* @param {Dict} options {from: msg.sender}
* @returns {Promise} {roomnightIds: BigNumber|Array, nextId: BigNumber}
* * roomnightIds: Room night token ids
* * nextId: The next id of token, if id = 0 the next token is null
*/
roomNightsOfOwner(from, limit, isVendor, options) {
return new Promise((resolve, reject) => {
this.contract.roomNightsOfOwner(from, limit, isVendor, {
from: options.from
}, (err, res) => {
if(err) {
reject(err);
}
else {
resolve({
roomnightIds : res[0],
nextId: res[1]
});
}
});
});
}
/**
* Transfers the ownership of an room night token from one address to another address.
* When transfer is complete, this function checks if _to is a smart contract (code size > 0).
* If so, it calls onERC721Received on _to and throws if the return value is not bytes4(keccak256("onERC721Received(address,uint256,bytes)")).
* @param {String} from The current owner of the room night token
* @param {String} to The new owner
* @param {Number} tokenId The token to transfer
* @param {String} data Additional data with no specified format, sent in call to `to`
* @param {Promise} {tx: String, from: BigNumber, to: BigNumber, tokenId: BigNumber}
* * tx: Transaction number
* * from: The current owner of the room night token
* * to: The new owner
* * tokenId: The token to transfer
*/
safeTransferFrom(from, to, tokenId, data) {
return new Promise((resolve, reject) => {
this.contract.safeTransferFrom(from, to, tokenId, data, (err, tx) => {
if(err) {
reject(err);
}
else {
let event = this.contract.Transfer((err, res) => {
event.stopWatching();
if (err) {
reject(err);
} else {
resolve({
tx: tx,
from: res[0],
to: res[1],
tokenId: res[2]
});
}
});
}
});
});
}
/**
* Transfers the ownership of an room night token from one address to another address
* @param {String} from The current owner of the room night token
* @param {String} to The new owner
* @param {Number} tokenId The token to transfer
* @param {Promise} {tx: String, from: BigNumber, to: BigNumber, tokenId: BigNumber}
* * tx: Transaction number
* * from: The current owner of the room night token
* * to: The new owner
* * tokenId: The token to transfer
*/
transferFrom(from, to, tokenId) {
return new Promise((resolve, reject) => {
this.contract.transferFrom(from, to, tokenId, (err, tx) => {
if(err) {
reject(err);
}
else {
let event = this.contract.Transfer((err, res) => {
event.stopWatching();
if (err) {
reject(err);
} else {
resolve({
tx: tx,
from: res[0],
to: res[1],
tokenId: res[2]
});
}
});
}
});
});
}
/**
* Transfers the ownership of tokens from one address to another address
* @param {String} from The current owner of the room night token
* @param {String} to The new owner
* @param {Number|Array} tokenIds The tokens to transfer
* @param {Promise} {tx: String, from: BigNumber, to: BigNumber, tokenIds: Number|Array}
* * tx: Transaction number
* * from: The current owner of the room night token
* * to: The new owner
* * tokenIds: The token to transfer
*/
transferFromInBatch(from, to, tokenIds) {
return new Promise((resolve, reject) => {
this.contract.transferFromInBatch(from, to, tokenIds, (err, tx) => {
if(err) {
reject(err);
}
else {
let event = this.contract.Transfer((err, res) => {
event.stopWatching();
if (err) {
reject(err);
} else {
resolve({
tx: tx,
from: res[0],
to: res[1],
tokenIds: tokenIds
});
}
});
}
});
});
}
/**
* Set or reaffirm the approved address for an room night token
* @param {String} approved The new approved token controller
* @param {Number} tokenId The token to approve
* @param {Promise} {tx: String, owner: String, approved: String, tokenId: BigNumber}
* * tx: Transaction number
* * owner: The current owner of the room night token
* * approved: The new approved token controller
* * tokenId: The token to approve
*/
approve(approved, tokenId) {
return new Promise((resolve, reject) => {
this.contract.approve(approved, tokenId, (err, tx) => {
if(err) {
reject(err);
}
else {
let event = this.contract.Approval((err, res) => {
event.stopWatching();
if (err) {
reject(err);
} else {
resolve({
tx: tx,
owner: res[0],
approved: res[1],
tokenId: res[2]
});
}
});
}
});
});
}
/**
* Enable or disable approval for a third party ("operator") to manage all of msg.sender's assets
* @param {String} operator The new approved token controller
* @param {Boolean} approved The token to approve
* @param {Promise} {tx: String, owner: String, operator: String, approved: Boolean}
* * tx: Transaction number
* * owner: The current owner of the room night token
* * operator: The new approved token controller
* * approved: The token to approve
*/
setApprovalForAll(operator, approved) {
return new Promise((resolve, reject) => {
this.contract.setApprovalForAll(operator, approved, (err, tx) => {
if(err) {
reject(err);
}
else {
let event = this.contract.ApprovalForAll((err, res) => {
event.stopWatching();
if (err) {
reject(err);
} else {
resolve({
tx: tx,
owner: res[0],
operator: res[1],
approved: res[2]
});
}
});
}
});
});
}
/**
* By room nigth in batch through ETH(`token` == 0) or other digital token(`token` != 0)
* @param {Number} vendorId The vendor Id
* @param {Number} rpid The vendor's rate plan id
* @param {Number|Array} dates The booking dates
* @param {Number} token The digital currency token
* @param {Dict} options {from: msg.sender}
* @param {Promise} {tx: String, customer: String, vendor: String, rpid: BigNumber, dates: Number|Array, token: BigNumber}
* * tx: Transaction number
* * customer: The customer address
* * vendor: Then vendor address
* * rpid: The rateplan id
* * dates: The booking dates
* * token: The digital currency token
*/
buyInBatch(vendorId, rpid, dates, token, options) {
let self = this;
let _buy = function(value) {
return new Promise((resolve, reject) => {
self.contract.buyInBatch(vendorId, rpid, dates, token, {from: options.from, value: value}, (err, tx) => {
if(err) {
reject(err);
}
else {
let event = self.contract.BuyInBatch((err, res) => {
event.stopWatching();
if (err) {
reject(err);
} else {
resolve({
tx: tx,
customer: res[0],
vendor: res[1],
rpid: res[2],
dates: dates,
token: res[4]
});
}
});
}
});
});
};
return new Promise((resolve, reject) => {
this.vendorContract.pricesOfDate(vendorId, rpid, dates, token,(err, prices) => {
if(err) {
reject(err);
}else {
var total = prices.reduce((left, right) => {
return left.plus(right);
});
resolve(total);
}
});
}).then((total) => {
if(token == 0) {
// ETH Pay
return _buy(total);
}else {
return this._getTokenContractInstance(token).then((contractInstance) => {
return new Promise((resolve, reject) => {
contractInstance.approve(this.contractAddress, total, {from: options.from}, (err, res) => {
if(err) {
reject(err);
}else {
let event = contractInstance.Approval((err, res) => {
event.stopWatching();
if(err) {
reject(err);
}else {
resolve(res);
}
});
}
});
});
}).then((res) => {
return _buy(0);
});
}
});
}
/**
* Apply room night refund
* @param {Number} rnid Room night token id
* @param {Boolean} isRefund if true the `rnid` can refund else not
* @param {Dict} options {from: msg.sender}
* @param {Promise} {tx: String, customer: String, rnid: BigNumber, isRefund: Boolean}
* * tx: Transaction number
* * customer: The customer address
* * rnid: The rateplan id
* * isRefund: if true the `rnid` can refund else not
*/
applyRefund(rnid, isRefund, options) {
return new Promise((resolve, reject) => {
this.contract.applyRefund(rnid, isRefund,{
from: options.from
}, (err, tx) => {
if(err) {
reject(err);
}
else {
let event = this.contract.ApplyRefund((err, res) => {
event.stopWatching();
if (err) {
reject(err);
} else {
resolve({
tx: tx,
customer: res[0],
rnid: res[1],
isRefund: res[2]
});
}
});
}
});
});
}
/**
* Refund through ETH or other digital token, give the room night ETH/TOKEN to customer and take back inventory
* @param {Number} rnid Room night token id
* @param {Dict} options {from: msg.sender}
* @param {Promise} {tx: String, vendor: String, rnid: BigNumber}
* * tx: Transaction number
* * vendor: Then vendor address
* * rnid: Room night token id
*/
refund(rnid, options) {
let self = this;
let _refund = function(rnid, value) {
return new Promise((resolve, reject) => {
self.contract.refund(rnid, {from: options.from, value: value}, (err, tx) => {
if(err) {
reject(err);
}
else {
let event = self.contract.Refund((err, res) => {
event.stopWatching();
if (err) {
reject(err);
} else {
resolve({
tx: tx,
vendor: res[0],
rnid: res[1]
});
}
});
}
});
});
}
return this.roomNight(rnid).then((res) => {
let tokenId = res.tokenId;
let price = res.price;
if (tokenId == 0) {
// ETH
return _refund(rnid, price);
}else {
// ERC2.0
return this._getTokenContractInstance(token).then((contractInstance) => {
return new Promise((resolve, reject) => {
contractInstance.approve(this.contractAddress, price, {from: options.from}, (err, res) => {
if(err) {
reject(err);
}else {
let event = contractInstance.Approval((err, res) => {
event.stopWatching();
if(err) {
reject(err);
}else {
resolve(res);
}
});
}
});
});
}).then((res) => {
return _refund(rnid, 0);
});
}
});
}
}
export default RoomNightCustomer;