machinomy
Version:
Micropayments powered by Ethereum
117 lines • 4.91 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const bignumber_js_1 = require("bignumber.js");
const logger_1 = require("@machinomy/logger");
const ChannelManager_1 = require("./ChannelManager");
const ChannelState_1 = require("./ChannelState");
const contracts_1 = require("@machinomy/contracts");
const ChannelId_1 = require("./ChannelId");
const abi = require("ethereumjs-abi");
const sigUtil = require("eth-sig-util");
const MemoryCache_1 = require("./caching/MemoryCache");
const log = new logger_1.default('channel-eth-contract');
const CREATE_CHANNEL_GAS = 300000;
class ChannelEthContract {
constructor(web3, ttl) {
this.web3 = web3;
this.contract = contracts_1.Unidirectional.contract(this.web3.currentProvider).deployed();
this.cache = new MemoryCache_1.default(ttl);
}
async open(sender, receiver, price, settlementPeriod, channelId) {
log.info(`Creating channel. Value: ${price} / Settlement: ${settlementPeriod}`);
let _channelId = channelId || ChannelId_1.default.random();
const deployed = await this.contract;
return deployed.open(_channelId.toString(), receiver, new bignumber_js_1.BigNumber(settlementPeriod), {
from: sender,
value: price,
gas: CREATE_CHANNEL_GAS
});
}
async claim(receiver, channelId, value, signature) {
log.info(`Claiming channel with id ${channelId} on behalf of receiver ${receiver}`);
log.info(`Values: ${value} / Signature: ${signature.toString()}`);
const deployed = await this.contract;
return deployed.claim(channelId, value, signature.toString(), { from: receiver });
}
async deposit(sender, channelId, value) {
log.info(`Depositing ${value} into channel ${channelId}`);
const deployed = await this.contract;
return deployed.deposit(channelId, {
from: sender,
value: value,
gas: CREATE_CHANNEL_GAS
});
}
async getState(channelId) {
log.info(`Fetching state for channel ${channelId}`);
const chan = await this.channelById(channelId);
if (!chan)
return ChannelState_1.ChannelState.Settled;
const settlingPeriod = chan[3];
const settlingUntil = chan[4];
log.info(`Fetched state for channel ${channelId}`);
if (settlingPeriod.gt(0) && settlingUntil.gt(0)) {
return ChannelState_1.ChannelState.Settling;
}
else if (settlingPeriod.gt(0) && settlingUntil.eq(0)) {
return ChannelState_1.ChannelState.Open;
}
else {
return ChannelState_1.ChannelState.Settled;
}
}
async getSettlementPeriod(channelId) {
log.info(`Fetching settlement period for channel ${channelId}`);
const channel = await this.channelById(channelId);
if (channel) {
return channel[3];
}
else {
return new bignumber_js_1.BigNumber(ChannelManager_1.default.DEFAULT_SETTLEMENT_PERIOD);
}
}
async startSettle(account, channelId) {
log.info(`Starting settle for account ${account} and channel id ${channelId}.`);
const deployed = await this.contract;
return deployed.startSettling(channelId, { from: account });
}
async finishSettle(account, channelId) {
log.info(`Finishing settle for account ${account} and channel ID ${channelId}.`);
const deployed = await this.contract;
return deployed.settle(channelId, { from: account, gas: 400000 });
}
async paymentDigest(channelId, value) {
const deployed = await this.contract;
const digest = abi.soliditySHA3(['address', 'bytes32', 'uint256'], [deployed.address, channelId, value.toString()]);
return '0x' + digest.toString('hex');
}
async canClaim(channelId, payment, receiver, signature) {
const channel = await this.channelById(channelId);
if (!channel)
return false;
const sender = channel[0];
let digest = await this.paymentDigest(channelId, payment);
let recovered = sigUtil.recoverPersonalSignature({
data: digest,
sig: signature.toString()
});
return recovered === sender;
}
async channelById(channelId) {
const cached = await this.cache.get(channelId);
if (cached) {
return cached;
}
else {
const deployed = await this.contract;
const exists = await deployed.isPresent(channelId);
if (!exists)
return undefined;
const instance = await deployed.channels(channelId);
await this.cache.set(channelId, instance);
return instance;
}
}
}
exports.default = ChannelEthContract;
//# sourceMappingURL=ChannelEthContract.js.map