UNPKG

machinomy

Version:

Micropayments powered by Ethereum

117 lines 4.91 kB
"use strict"; 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