connext
Advanced tools
Comparing version 3.0.7 to 3.0.8
@@ -44,4 +44,7 @@ import { WithdrawalParameters, ChannelManagerChannelDetails, Sync, ThreadState, ThreadStateUpdate } from './types'; | ||
getChannelStateAtNonce(txCountGlobal: number): Promise<ChannelStateUpdate>; | ||
getThreadInitialStates(): Promise<UnsignedThreadState[]>; | ||
getThreadInitialStates(): Promise<ThreadState[]>; | ||
getIncomingThreads(): Promise<ThreadRow[]>; | ||
getActiveThreads(): Promise<ThreadState[]>; | ||
getLastThreadUpdateId(): Promise<number>; | ||
getAllThreads(): Promise<ThreadState[]>; | ||
getThreadByParties(partyB: Address, userIsSender: boolean): Promise<ThreadRow>; | ||
@@ -60,3 +63,7 @@ sync(txCountGlobal: number, lastThreadUpdateId: number): Promise<Sync | null>; | ||
updateThread(update: ThreadStateUpdate): Promise<ThreadStateUpdate>; | ||
getLatestChannelState(): Promise<ChannelState | null>; | ||
getLatestChannelStateAndUpdate(): Promise<{ | ||
state: ChannelState; | ||
update: UpdateRequest; | ||
} | null>; | ||
getLatestStateNoPendingOps(): Promise<ChannelState | null>; | ||
} | ||
@@ -63,0 +70,0 @@ export interface ConnextOptions { |
@@ -32,2 +32,3 @@ "use strict"; | ||
const CollateralController_1 = require("./controllers/CollateralController"); | ||
const actions = require("./state/actions"); | ||
const ThreadsController_1 = require("./controllers/ThreadsController"); | ||
@@ -77,13 +78,17 @@ class HubAPIClient { | ||
} | ||
getLatestChannelState() { | ||
getLatestStateNoPendingOps() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
try { | ||
const res = yield this.networking.get(`channel/${this.user}/latest-update`); | ||
const res = yield this.networking.get(`channel/${this.user}/latest-no-pending`); | ||
if (!res.data) { | ||
return null; | ||
} | ||
return res.data; | ||
} | ||
catch (e) { | ||
if (e.statusCode === 404) { | ||
if (e.status == 404) { | ||
console.log(`Channel not found for user ${this.user}`); | ||
return null; | ||
} | ||
console.log('Error getting latest state no pending ops:', e); | ||
throw e; | ||
@@ -93,2 +98,40 @@ } | ||
} | ||
getLastThreadUpdateId() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
try { | ||
const res = yield this.networking.get(`thread/${this.user}/last-update-id`); | ||
if (!res.data) { | ||
return 0; | ||
} | ||
return res.data; | ||
} | ||
catch (e) { | ||
if (e.status == 404) { | ||
console.log(`Thread update not found for user ${this.user}`); | ||
return 0; | ||
} | ||
console.log('Error getting latest state no pending ops:', e); | ||
throw e; | ||
} | ||
}); | ||
} | ||
getLatestChannelStateAndUpdate() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
try { | ||
const res = yield this.networking.get(`channel/${this.user}/latest-update`); | ||
if (!res.data) { | ||
return null; | ||
} | ||
return { state: res.data.state, update: types_1.channelUpdateToUpdateRequest(res.data) }; | ||
} | ||
catch (e) { | ||
if (e.status == 404) { | ||
console.log(`Channel not found for user ${this.user}`); | ||
return null; | ||
} | ||
console.log('Error getting latest state:', e); | ||
throw e; | ||
} | ||
}); | ||
} | ||
updateThread(update) { | ||
@@ -149,2 +192,22 @@ return __awaiter(this, void 0, void 0, function* () { | ||
} | ||
getActiveThreads() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
// get the current channel state and return it | ||
const response = yield this.networking.get(`thread/${this.user}/active`); | ||
if (!response.data) { | ||
return []; | ||
} | ||
return response.data; | ||
}); | ||
} | ||
getAllThreads() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
// get the current channel state and return it | ||
const response = yield this.networking.get(`thread/${this.user}/all`); | ||
if (!response.data) { | ||
return []; | ||
} | ||
return response.data; | ||
}); | ||
} | ||
getIncomingThreads() { | ||
@@ -565,7 +628,56 @@ return __awaiter(this, void 0, void 0, function* () { | ||
this.store = yield this.getStore(); | ||
this.store.subscribe(() => { | ||
this.store.subscribe(() => __awaiter(this, void 0, void 0, function* () { | ||
const state = this.store.getState(); | ||
this.emit('onStateChange', state); | ||
this._saveState(state); | ||
}); | ||
yield this._saveState(state); | ||
})); | ||
// TODO: appropriately set the latest | ||
// valid state ?? | ||
const channelAndUpdate = yield this.hub.getLatestChannelStateAndUpdate(); | ||
console.log('Found latest double signed state:', JSON.stringify(channelAndUpdate, null, 2)); | ||
if (channelAndUpdate) { | ||
this.store.dispatch(actions.setChannelAndUpdate(channelAndUpdate)); | ||
// update the latest valid state | ||
const latestValid = yield this.hub.getLatestStateNoPendingOps(); | ||
console.log('latestValid:', latestValid); | ||
if (latestValid) { | ||
this.store.dispatch(actions.setLatestValidState(latestValid)); | ||
} | ||
// unconditionally update last thread update id, thread history | ||
const lastThreadUpdateId = yield this.hub.getLastThreadUpdateId(); | ||
console.log('lastThreadUpdateId:', lastThreadUpdateId); | ||
this.store.dispatch(actions.setLastThreadUpdateId(lastThreadUpdateId)); | ||
// extract thread history, sort by descending threadId | ||
const threadHistoryDuplicates = (yield this.hub.getAllThreads()).map(t => { | ||
return { | ||
sender: t.sender, | ||
receiver: t.receiver, | ||
threadId: t.threadId, | ||
}; | ||
}).sort((a, b) => b.threadId - a.threadId); | ||
console.log('threadHistoryDuplicates', threadHistoryDuplicates); | ||
// filter duplicates | ||
const threadHistory = threadHistoryDuplicates.filter((thread, i) => { | ||
const search = JSON.stringify({ | ||
sender: thread.sender, | ||
receiver: thread.receiver | ||
}); | ||
const elts = threadHistoryDuplicates.map(t => { | ||
return JSON.stringify({ sender: t.sender, receiver: t.receiver }); | ||
}); | ||
return elts.indexOf(search) == i; | ||
}); | ||
console.log('threadHistory:', threadHistory); | ||
this.store.dispatch(actions.setThreadHistory(threadHistory)); | ||
// if thread count is greater than 0, update | ||
// activeThreads, initial states | ||
if (channelAndUpdate.state.threadCount > 0) { | ||
const initialStates = yield this.hub.getThreadInitialStates(); | ||
console.log('initialStates:', initialStates); | ||
this.store.dispatch(actions.setActiveInitialThreadStates(initialStates)); | ||
const threadRows = yield this.hub.getActiveThreads(); | ||
console.log('threadRows:', threadRows); | ||
this.store.dispatch(actions.setActiveThreads(threadRows)); | ||
} | ||
} | ||
// Start all controllers | ||
@@ -572,0 +684,0 @@ for (let controller of this.getControllers()) { |
@@ -12,3 +12,3 @@ import { AbstractController } from './AbstractController'; | ||
private pollExchangeRates; | ||
exchange: (toSell: string, currency: "wei" | "token") => Promise<void>; | ||
exchange: (toSell: string, currency: "token" | "wei") => Promise<void>; | ||
} |
@@ -323,2 +323,17 @@ "use strict"; | ||
if (item.type === 'thread') { // handle thread updates | ||
if (item.update.state.txCount == 0) { | ||
console.log(`Received opening thread state, should be handled in OpenThread channel update. State: ${JSON.stringify(this.getState(), null, 2)}`); | ||
return; | ||
} | ||
if (!item.update.id) { | ||
throw new Error(`Uh oh! Thread update should definitely have the id at this point! Sync item: ${JSON.stringify(item)}`); | ||
} | ||
const persistent = this.getState().persistent; | ||
// do nothing if update is below latest in store | ||
if (item.update.id <= persistent.lastThreadUpdateId) { | ||
// TODO: handle case where thread update is one | ||
// we need to close as a receiver | ||
console.warn(`Received old thread update, doing nothing.`); | ||
return; | ||
} | ||
console.log(`Received a thread payment from the hub. Sync item: ${JSON.stringify(item)}`); | ||
@@ -336,3 +351,2 @@ // since threads are single-payment constructs, received thread | ||
// should update the store with the new active thread state | ||
const persistent = this.getState().persistent; | ||
const prevThreadState = persistent.activeThreads.filter(t => t.threadId == newThreadState.threadId && t.sender == newThreadState.sender && t.receiver == newThreadState.receiver); | ||
@@ -343,7 +357,4 @@ if (prevThreadState.length != 1) { | ||
const newActiveThreads = persistent.activeThreads.filter(t => t.threadId != newThreadState.threadId && t.sender != newThreadState.sender && t.receiver != newThreadState.receiver).concat([newThreadState]); | ||
if (!item.update.id) { | ||
throw new Error(`Uh oh! Thread update should definitely have the id at this point! Sync item: ${JSON.stringify(item)}`); | ||
} | ||
// update the latest id | ||
this.store.dispatch(actions.setLastThreadUpdateId(item.update.id)); | ||
this.store.dispatch(actions.setLastThreadUpdateId(Number(item.update.id))); | ||
// update active threads state | ||
@@ -366,3 +377,3 @@ this.store.dispatch(actions.setActiveThreads(newActiveThreads)); | ||
} | ||
const update = item.update; | ||
let update = item.update; | ||
console.log(`Applying update from hub: ${update.reason} txCount=${update.txCount}:`, update); | ||
@@ -388,2 +399,7 @@ const connextState = this.getState(); | ||
// TODO: Write this for nukeThreads | ||
// add initial thread states from our store if the update | ||
// type includes threads | ||
if (update.reason.includes('Thread')) { | ||
update.initialThreadStates = connextState.persistent.activeInitialThreadStates; | ||
} | ||
const nextState = yield this.connext.validator.generateChannelStateFromRequest(update.reason === 'Invalidation' ? latestValidState : prevState, update); | ||
@@ -398,3 +414,3 @@ // any sigs included on the updates should be valid | ||
if (update.sigHub && update.sigUser) { | ||
this.store.dispatch(actions.setChannel({ | ||
this.store.dispatch(actions.setChannelAndUpdate({ | ||
update: update, | ||
@@ -408,10 +424,24 @@ state: Object.assign({}, nextState, { sigHub: update.sigHub, sigUser: update.sigUser }), | ||
const args = update.args; | ||
const connextState = this.store.getState(); | ||
// unconditionally update thread history whether it is open or close | ||
// thread | ||
const threadHistory = connextState.persistent.threadHistory.concat({ | ||
sender: args.sender, | ||
receiver: args.receiver, | ||
threadId: args.threadId | ||
// thread. | ||
let wasDuplicate = false; | ||
const threadHistory = connextState.persistent.threadHistory.map(t => { | ||
if (t.receiver == args.receiver && t.sender == args.sender) { | ||
// update the threadId in history with the one in args | ||
wasDuplicate = true; | ||
return Object.assign({}, t, { threadId: args.threadId }); | ||
} | ||
else { | ||
// otherwise, return the thread history item | ||
return t; | ||
} | ||
}); | ||
// if this is new sender/receiver combo, push the thread history item | ||
if (!wasDuplicate) { | ||
threadHistory.push({ | ||
threadId: args.threadId, | ||
sender: args.sender, | ||
receiver: args.receiver, | ||
}); | ||
} | ||
// update active initial states depending if open or close | ||
@@ -418,0 +448,0 @@ const prevActiveInitialThreads = connextState.persistent.activeInitialThreadStates; |
@@ -12,2 +12,3 @@ "use strict"; | ||
const utils_1 = require("../lib/utils"); | ||
const types_1 = require("../types"); | ||
const Poller_1 = require("../lib/poller/Poller"); | ||
@@ -21,12 +22,2 @@ const getLastThreadUpdateId_1 = require("../lib/getLastThreadUpdateId"); | ||
const hasPendingOps_1 = require("../hasPendingOps"); | ||
function channelUpdateToUpdateRequest(up) { | ||
return { | ||
id: up.id, | ||
reason: up.reason, | ||
args: up.args, | ||
txCount: up.state.txCountGlobal, | ||
sigHub: up.state.sigHub, | ||
sigUser: up.state.sigUser, | ||
}; | ||
} | ||
/** | ||
@@ -256,2 +247,5 @@ * This function should be used to update the `syncResultsFromHub` value in the | ||
// to be sent, the corresponding incoming update will be ignored. | ||
// TODO: first ensure that any updates from or to hub are for the instantiated | ||
// user, hub currently does not return user for channels, users must | ||
// reinstantiate connext | ||
const updateKey = (x) => { | ||
@@ -329,9 +323,3 @@ if (x.type == 'channel') { | ||
const state = this.store.getState(); | ||
let txCount = state.persistent.channel.txCountGlobal; | ||
// TODO: fix the txCount with the state update controller | ||
// // ensure txCount is the latest | ||
// if (txCount == 0) { | ||
// const latest = await this.hub.getLatestChannelState() | ||
// txCount = latest ? latest.txCountGlobal : txCount | ||
// } | ||
const txCount = state.persistent.channel.txCountGlobal; | ||
const hubSync = yield this.hub.sync(txCount, getLastThreadUpdateId_1.getLastThreadUpdateId(this.store)); | ||
@@ -436,3 +424,3 @@ if (!hubSync) { | ||
const sync = Object.keys(update.state).indexOf('sigA') == -1 | ||
? { type: 'channel', update: channelUpdateToUpdateRequest(update) } | ||
? { type: 'channel', update: types_1.channelUpdateToUpdateRequest(update) } | ||
: { type: 'thread', update }; | ||
@@ -551,4 +539,2 @@ this.store.dispatch(actions.setSyncControllerState(Object.assign({}, state, { updatesToSync: [ | ||
const [res, err] = yield utils_2.maybe(this.hub.updateHub(channelUp, getLastThreadUpdateId_1.getLastThreadUpdateId(this.store))); | ||
// TODO: will you ever have to add thread updates here | ||
// most thread updates are sent via the buy controller | ||
const threadSync = state.updatesToSync.filter(u => u.type == "thread"); | ||
@@ -617,3 +603,6 @@ const threadUp = threadSync.map(u => u.update); | ||
console.log('** merged **:', JSON.stringify(merged, null, 2)); | ||
const filtered = filterPendingSyncResults(merged, this.getSyncState().updatesToSync); | ||
const updatesToSync = this.getSyncState().updatesToSync; | ||
console.log('** updatesToSync **', updatesToSync); | ||
const filtered = filterPendingSyncResults(merged, updatesToSync); | ||
console.log('** filtered **:', JSON.stringify(filtered, null, 2)); | ||
console.info(`updates from hub: ${updates.length}; old len: ${oldSyncResults.length}; merged: ${filtered.length}:`, filtered); | ||
@@ -620,0 +609,0 @@ this.store.dispatch(actions.setSortedSyncResultsFromHub(filtered)); |
@@ -53,2 +53,3 @@ "use strict"; | ||
const hubResponse = yield this.hub.updateHub([updateRequest], state.persistent.lastThreadUpdateId); | ||
console.log('hubResponse:', hubResponse); | ||
this.connext.syncController.handleHubSync(hubResponse.updates); | ||
@@ -75,11 +76,8 @@ return { thread: initialState, channel: newChannelState }; // shortcut for access within buycontroller | ||
const newChannelState = yield this.connext.signChannelState(this.validator.generateCloseThread(channel, initialThreadStates, thread[0])); | ||
const updateRequest = { | ||
const update = { | ||
reason: "CloseThread", | ||
args: thread[0], | ||
txCount: newChannelState.txCountGlobal, | ||
sigUser: newChannelState.sigUser, | ||
initialThreadStates, | ||
state: newChannelState, | ||
}; | ||
const hubResponse = yield this.hub.updateHub([updateRequest], state.persistent.lastThreadUpdateId); | ||
this.connext.syncController.handleHubSync(hubResponse.updates); | ||
yield this.connext.syncController.sendUpdateToHub(update); | ||
}); | ||
@@ -86,0 +84,0 @@ } |
@@ -22,3 +22,3 @@ import { SyncControllerState, RuntimeState, PendingRequestedDeposit } from './store'; | ||
}; | ||
export declare const setChannel: { | ||
export declare const setChannelAndUpdate: { | ||
(payload: SetChannelActionArgs, meta?: { | ||
@@ -30,2 +30,4 @@ [key: string]: any; | ||
}; | ||
export declare const setChannel: ActionCreatorWithHandler<ChannelState<string>>; | ||
export declare const setLatestValidState: ActionCreatorWithHandler<ChannelState<string>>; | ||
export declare const setSyncControllerState: ActionCreatorWithHandler<SyncControllerState>; | ||
@@ -32,0 +34,0 @@ export declare const setRequestedDeposit: ActionCreatorWithHandler<PendingRequestedDeposit | null>; |
@@ -40,3 +40,5 @@ "use strict"; | ||
exports.setLastThreadUpdateId = setterAction('persistent.lastThreadUpdateId'); | ||
exports.setChannel = actionCreator('setChannelAndUpdate'); | ||
exports.setChannelAndUpdate = actionCreator('setChannelAndUpdate'); | ||
exports.setChannel = setterAction('persistent.channel'); | ||
exports.setLatestValidState = setterAction('persistent.latestValidState'); | ||
exports.setSyncControllerState = setterAction('persistent.syncControllerState'); | ||
@@ -43,0 +45,0 @@ exports.setRequestedDeposit = setterAction('persistent.requestedDeposit'); |
@@ -13,2 +13,3 @@ "use strict"; | ||
if (!didInitialUpdate || | ||
action.type === 'connext/setChannelAndUpdate' || | ||
action.type === 'connext/set:runtime.syncResultsFromHub' || | ||
@@ -15,0 +16,0 @@ action.type === 'connext/set:persistent.channel' || |
import { ConnextState } from './store'; | ||
import { ReducerBuilder } from 'typescript-fsa-reducers/dist'; | ||
import { UpdateRequest, ChannelState } from '@src/types'; | ||
export declare let reducers: ReducerBuilder<ConnextState, ConnextState>; | ||
export declare function handleChannelChange(state: ConnextState, channel: ChannelState, update?: UpdateRequest): { | ||
persistent: { | ||
channel: ChannelState<string>; | ||
channelUpdate: UpdateRequest<string, import("../types").ArgsTypes<string>>; | ||
latestValidState: ChannelState<string>; | ||
activeThreads: import("../types").ThreadState<string>[]; | ||
activeInitialThreadStates: import("../types").ThreadState<string>[]; | ||
threadHistory: import("../types").ThreadHistoryItem[]; | ||
lastThreadUpdateId: number; | ||
syncControllerState: import("./store").SyncControllerState; | ||
}; | ||
runtime: import("./store").RuntimeState; | ||
}; |
@@ -15,10 +15,16 @@ "use strict"; | ||
// }) | ||
exports.reducers = exports.reducers.case(actions.setChannel, (state, action) => { | ||
const hasPending = (Object.keys(action.state) | ||
.some(field => field.startsWith('pending') && action.state[field] != '0')); | ||
function handleChannelChange(state, channel, update) { | ||
const hasPending = (Object.keys(channel) | ||
.some(field => field.startsWith('pending') && channel[field] != '0')); | ||
if (!hasPending) { | ||
state = Object.assign({}, state, { persistent: Object.assign({}, state.persistent, { latestValidState: action.state }) }); | ||
state = Object.assign({}, state, { persistent: Object.assign({}, state.persistent, { latestValidState: channel }) }); | ||
} | ||
return Object.assign({}, state, { persistent: Object.assign({}, state.persistent, { channel: action.state, channelUpdate: action.update }) }); | ||
}); | ||
if (!update) { | ||
update = state.persistent.channelUpdate; | ||
} | ||
return Object.assign({}, state, { persistent: Object.assign({}, state.persistent, { channel: channel, channelUpdate: update }) }); | ||
} | ||
exports.handleChannelChange = handleChannelChange; | ||
exports.reducers = exports.reducers.case(actions.setChannelAndUpdate, (state, action) => handleChannelChange(state, action.state, action.update)); | ||
exports.reducers = exports.reducers.case(actions.setChannel, (state, action) => handleChannelChange(state, action)); | ||
for (let action of Object.values(actions)) { | ||
@@ -25,0 +31,0 @@ if (utils_1.isFunction(action && action.handler)) |
@@ -52,4 +52,7 @@ import { IWeb3TxWrapper } from '../Connext'; | ||
getChannel(): Promise<ChannelRow>; | ||
getActiveThreads(): Promise<ThreadState[]>; | ||
getLastThreadUpdateId(): Promise<number>; | ||
getAllThreads(): Promise<ThreadState[]>; | ||
getChannelStateAtNonce(): Promise<ChannelStateUpdate>; | ||
getThreadInitialStates(): Promise<UnsignedThreadState[]>; | ||
getThreadInitialStates(): Promise<ThreadState[]>; | ||
getIncomingThreads(): Promise<ThreadRow[]>; | ||
@@ -69,3 +72,4 @@ getThreadByParties(): Promise<ThreadRow>; | ||
updateThread(update: ThreadStateUpdate): Promise<ThreadStateUpdate>; | ||
getLatestChannelState(): Promise<ChannelState | null>; | ||
getLatestChannelStateAndUpdate(): Promise<null>; | ||
getLatestStateNoPendingOps(): Promise<ChannelState | null>; | ||
assertReceivedUpdate(expected: PartialUpdateRequest): void; | ||
@@ -72,0 +76,0 @@ } |
@@ -203,2 +203,17 @@ "use strict"; | ||
} | ||
getActiveThreads() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
return []; | ||
}); | ||
} | ||
getLastThreadUpdateId() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
return 0; | ||
}); | ||
} | ||
getAllThreads() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
return []; | ||
}); | ||
} | ||
getChannelStateAtNonce() { | ||
@@ -380,7 +395,15 @@ return __awaiter(this, void 0, void 0, function* () { | ||
} | ||
getLatestChannelState() { | ||
let store = new MockStore; | ||
//@ts-ignore | ||
return store._initialState.persistent.channel; | ||
getLatestChannelStateAndUpdate() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
return null; | ||
// let store = new MockStore() | ||
// //@ts-ignore | ||
// return {state: store._initialState.persistent.channel, update: store._initialState.persistent.channelUpdate} | ||
}); | ||
} | ||
getLatestStateNoPendingOps() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
return null; | ||
}); | ||
} | ||
assertReceivedUpdate(expected) { | ||
@@ -387,0 +410,0 @@ for (let req of this.receivedUpdateRequests) { |
@@ -91,2 +91,9 @@ import BN = require('bn.js'); | ||
export declare type ChannelStatus = keyof typeof ChannelStatus; | ||
export declare const DisputeStatus: { | ||
CD_PENDING: string; | ||
CD_IN_DISPUTE_PERIOD: string; | ||
CD_FAILED: string; | ||
CD_FINISHED: string; | ||
}; | ||
export declare type DisputeStatus = keyof typeof DisputeStatus; | ||
export declare const ChannelUpdateReasons: { | ||
@@ -409,5 +416,7 @@ [key in keyof UpdateRequestTypes]: string; | ||
export declare type WithdrawalParametersBigNumber = WithdrawalParameters<BigNumber>; | ||
export declare const withdrawalParamsNumericFields: string[]; | ||
/********************************* | ||
******* TYPE CONVERSIONS ******** | ||
*********************************/ | ||
export declare function channelUpdateToUpdateRequest(up: ChannelStateUpdate): UpdateRequest; | ||
export declare const channelNumericFields: string[]; | ||
@@ -414,0 +423,0 @@ export declare function convertChannelState(to: "bn", obj: ChannelState<any>): ChannelStateBN; |
@@ -80,2 +80,8 @@ "use strict"; | ||
}; | ||
exports.DisputeStatus = { | ||
CD_PENDING: 'CD_PENDING', | ||
CD_IN_DISPUTE_PERIOD: 'CD_IN_DISPUTE_PERIOD', | ||
CD_FAILED: 'CD_FAILED', | ||
CD_FINISHED: 'CD_FINISHED' | ||
}; | ||
// channel update reasons | ||
@@ -238,5 +244,22 @@ exports.ChannelUpdateReasons = { | ||
exports.convertVerboseEvent = convertVerboseEvent; | ||
exports.withdrawalParamsNumericFields = [ | ||
'withdrawalWeiUser', | ||
'tokensToSell', | ||
'weiToSell', | ||
'withdrawalTokenUser', | ||
]; | ||
/********************************* | ||
******* TYPE CONVERSIONS ******** | ||
*********************************/ | ||
function channelUpdateToUpdateRequest(up) { | ||
return { | ||
id: up.id, | ||
reason: up.reason, | ||
args: up.args, | ||
txCount: up.state.txCountGlobal, | ||
sigHub: up.state.sigHub, | ||
sigUser: up.state.sigUser, | ||
}; | ||
} | ||
exports.channelUpdateToUpdateRequest = channelUpdateToUpdateRequest; | ||
// util to convert from string to bn for all types | ||
@@ -243,0 +266,0 @@ exports.channelNumericFields = [ |
@@ -26,2 +26,4 @@ import { InvalidationArgs, EmptyChannelArgs, SignedDepositRequestProposal } from './types'; | ||
generateProposePendingExchange: (prevStr: ChannelState<string>, argsStr: PendingExchangeArgs<string>) => UnsignedChannelState<string>; | ||
withdrawalParams: (params: import("./types").WithdrawalParameters<BN>) => string | null; | ||
payment: (params: Payment<BN>) => string | null; | ||
proposePendingWithdrawal: (prev: ChannelState<BN>, args: WithdrawalArgs<BN>) => string | null; | ||
@@ -28,0 +30,0 @@ generateProposePendingWithdrawal(prevStr: ChannelState, argsStr: WithdrawalArgs): UnsignedChannelState; |
@@ -81,2 +81,10 @@ "use strict"; | ||
}; | ||
this.withdrawalParams = (params) => { | ||
if (+params.exchangeRate != +params.exchangeRate || +params.exchangeRate < 0) | ||
return 'invalid exchange rate: ' + params.exchangeRate; | ||
return this.hasNegative(params, types_2.withdrawalParamsNumericFields); | ||
}; | ||
this.payment = (params) => { | ||
return this.hasNegative(params, types_2.argNumericFields.Payment); | ||
}; | ||
this.proposePendingWithdrawal = (prev, args) => { | ||
@@ -357,3 +365,3 @@ const errs = [ | ||
// If user is receiver then that means that prev is hub-receiver channel | ||
const userIsSender = args.sender === prev.user; | ||
const userIsSender = args.sender == prev.user; | ||
// First check thread state independently | ||
@@ -603,3 +611,3 @@ // Then check that thread state against prev channel state: | ||
catch (e) { | ||
return e.message; | ||
errs.push('Error asserting thread signer: ' + e.message); | ||
} | ||
@@ -606,0 +614,0 @@ if (errs) { |
{ | ||
"name": "connext", | ||
"description": "Shared code between wallet and hub", | ||
"version": "3.0.7", | ||
"version": "3.0.8", | ||
"main": "dist", | ||
@@ -6,0 +6,0 @@ "devDependencies": { |
@@ -1,2 +0,2 @@ | ||
import { WithdrawalParameters, ChannelManagerChannelDetails, Sync, ThreadState, addSigToThreadState, ThreadStateUpdate } from './types' | ||
import { WithdrawalParameters, ChannelManagerChannelDetails, Sync, ThreadState, addSigToThreadState, ThreadStateUpdate, channelUpdateToUpdateRequest, ThreadHistoryItem } from './types' | ||
import { DepositArgs, SignedDepositRequestProposal, Omit } from './types' | ||
@@ -49,2 +49,3 @@ import { PurchaseRequest } from './types' | ||
import ThreadsController from './controllers/ThreadsController'; | ||
import { getLastThreadUpdateId } from './lib/getLastThreadUpdateId'; | ||
@@ -78,4 +79,7 @@ type Address = string | ||
getChannelStateAtNonce(txCountGlobal: number): Promise<ChannelStateUpdate> | ||
getThreadInitialStates(): Promise<UnsignedThreadState[]> | ||
getThreadInitialStates(): Promise<ThreadState[]> | ||
getIncomingThreads(): Promise<ThreadRow[]> | ||
getActiveThreads(): Promise<ThreadState[]> | ||
getLastThreadUpdateId(): Promise<number> | ||
getAllThreads(): Promise<ThreadState[]> | ||
getThreadByParties(partyB: Address, userIsSender: boolean): Promise<ThreadRow> | ||
@@ -97,3 +101,4 @@ sync(txCountGlobal: number, lastThreadUpdateId: number): Promise<Sync | null> | ||
updateThread(update: ThreadStateUpdate): Promise<ThreadStateUpdate> | ||
getLatestChannelState(): Promise<ChannelState | null> | ||
getLatestChannelStateAndUpdate(): Promise<{state: ChannelState, update: UpdateRequest} | null> | ||
getLatestStateNoPendingOps(): Promise<ChannelState | null> | ||
} | ||
@@ -112,11 +117,15 @@ | ||
async getLatestChannelState(): Promise<ChannelState | null> { | ||
async getLatestStateNoPendingOps(): Promise<ChannelState | null> { | ||
try { | ||
const res = await this.networking.get(`channel/${this.user}/latest-update`) | ||
const res = await this.networking.get(`channel/${this.user}/latest-no-pending`) | ||
if (!res.data) { | ||
return null | ||
} | ||
return res.data | ||
} catch (e) { | ||
if (e.statusCode === 404) { | ||
if (e.status == 404) { | ||
console.log(`Channel not found for user ${this.user}`) | ||
return null | ||
} | ||
console.log('Error getting latest state no pending ops:', e) | ||
throw e | ||
@@ -126,2 +135,36 @@ } | ||
async getLastThreadUpdateId(): Promise<number> { | ||
try { | ||
const res = await this.networking.get(`thread/${this.user}/last-update-id`) | ||
if (!res.data) { | ||
return 0 | ||
} | ||
return res.data | ||
} catch (e) { | ||
if (e.status == 404) { | ||
console.log(`Thread update not found for user ${this.user}`) | ||
return 0 | ||
} | ||
console.log('Error getting latest state no pending ops:', e) | ||
throw e | ||
} | ||
} | ||
async getLatestChannelStateAndUpdate(): Promise<{state: ChannelState, update: UpdateRequest} | null> { | ||
try { | ||
const res = await this.networking.get(`channel/${this.user}/latest-update`) | ||
if (!res.data) { | ||
return null | ||
} | ||
return { state: res.data.state, update: channelUpdateToUpdateRequest(res.data) } | ||
} catch (e) { | ||
if (e.status == 404) { | ||
console.log(`Channel not found for user ${this.user}`) | ||
return null | ||
} | ||
console.log('Error getting latest state:', e) | ||
throw e | ||
} | ||
} | ||
async updateThread(update: ThreadStateUpdate): Promise<ThreadStateUpdate> { | ||
@@ -172,3 +215,3 @@ // 'POST /:sender/to/:receiver/update': 'doUpdateThread' | ||
async getThreadInitialStates(): Promise<UnsignedThreadState[]> { | ||
async getThreadInitialStates(): Promise<ThreadState[]> { | ||
// get the current channel state and return it | ||
@@ -184,2 +227,24 @@ const response = await this.networking.get( | ||
async getActiveThreads(): Promise<ThreadState[]> { | ||
// get the current channel state and return it | ||
const response = await this.networking.get( | ||
`thread/${this.user}/active`, | ||
) | ||
if (!response.data) { | ||
return [] | ||
} | ||
return response.data | ||
} | ||
async getAllThreads(): Promise<ThreadState[]> { | ||
// get the current channel state and return it | ||
const response = await this.networking.get( | ||
`thread/${this.user}/all`, | ||
) | ||
if (!response.data) { | ||
return [] | ||
} | ||
return response.data | ||
} | ||
async getIncomingThreads(): Promise<ThreadRow[]> { | ||
@@ -851,8 +916,61 @@ // get the current channel state and return it | ||
this.store = await this.getStore() | ||
this.store.subscribe(() => { | ||
this.store.subscribe(async () => { | ||
const state = this.store.getState() | ||
this.emit('onStateChange', state) | ||
this._saveState(state) | ||
await this._saveState(state) | ||
}) | ||
// TODO: appropriately set the latest | ||
// valid state ?? | ||
const channelAndUpdate = await this.hub.getLatestChannelStateAndUpdate() | ||
console.log('Found latest double signed state:', JSON.stringify(channelAndUpdate, null, 2)) | ||
if (channelAndUpdate) { | ||
this.store.dispatch(actions.setChannelAndUpdate(channelAndUpdate)) | ||
// update the latest valid state | ||
const latestValid = await this.hub.getLatestStateNoPendingOps() | ||
console.log('latestValid:', latestValid) | ||
if (latestValid) { | ||
this.store.dispatch(actions.setLatestValidState(latestValid)) | ||
} | ||
// unconditionally update last thread update id, thread history | ||
const lastThreadUpdateId = await this.hub.getLastThreadUpdateId() | ||
console.log('lastThreadUpdateId:', lastThreadUpdateId) | ||
this.store.dispatch(actions.setLastThreadUpdateId(lastThreadUpdateId)) | ||
// extract thread history, sort by descending threadId | ||
const threadHistoryDuplicates = (await this.hub.getAllThreads()).map(t => { | ||
return { | ||
sender: t.sender, | ||
receiver: t.receiver, | ||
threadId: t.threadId, | ||
} | ||
}).sort((a, b) => b.threadId - a.threadId) | ||
console.log('threadHistoryDuplicates', threadHistoryDuplicates) | ||
// filter duplicates | ||
const threadHistory = threadHistoryDuplicates.filter((thread, i) => { | ||
const search = JSON.stringify({ | ||
sender: thread.sender, | ||
receiver: thread.receiver | ||
}) | ||
const elts = threadHistoryDuplicates.map(t => { | ||
return JSON.stringify({ sender: t.sender, receiver: t.receiver }) | ||
}) | ||
return elts.indexOf(search) == i | ||
}) | ||
console.log('threadHistory:', threadHistory) | ||
this.store.dispatch(actions.setThreadHistory(threadHistory)) | ||
// if thread count is greater than 0, update | ||
// activeThreads, initial states | ||
if (channelAndUpdate.state.threadCount > 0) { | ||
const initialStates = await this.hub.getThreadInitialStates() | ||
console.log('initialStates:', initialStates) | ||
this.store.dispatch(actions.setActiveInitialThreadStates(initialStates)) | ||
const threadRows = await this.hub.getActiveThreads() | ||
console.log('threadRows:', threadRows) | ||
this.store.dispatch(actions.setActiveThreads(threadRows)) | ||
} | ||
} | ||
// Start all controllers | ||
@@ -859,0 +977,0 @@ for (let controller of this.getControllers()) { |
@@ -167,2 +167,21 @@ import { ConnextState } from '../state/store' | ||
if (item.type === 'thread') { // handle thread updates | ||
if (item.update.state.txCount == 0) { | ||
console.log(`Received opening thread state, should be handled in OpenThread channel update. State: ${JSON.stringify(this.getState(), null, 2)}`) | ||
return | ||
} | ||
if (!item.update.id) { | ||
throw new Error(`Uh oh! Thread update should definitely have the id at this point! Sync item: ${JSON.stringify(item)}`) | ||
} | ||
const persistent = this.getState().persistent | ||
// do nothing if update is below latest in store | ||
if (item.update.id <= persistent.lastThreadUpdateId) { | ||
// TODO: handle case where thread update is one | ||
// we need to close as a receiver | ||
console.warn(`Received old thread update, doing nothing.`) | ||
return | ||
} | ||
console.log(`Received a thread payment from the hub. Sync item: ${JSON.stringify(item)}`) | ||
@@ -183,3 +202,2 @@ // since threads are single-payment constructs, received thread | ||
// should update the store with the new active thread state | ||
const persistent = this.getState().persistent | ||
const prevThreadState = persistent.activeThreads.filter( | ||
@@ -197,8 +215,4 @@ t => t.threadId == newThreadState.threadId && t.sender == newThreadState.sender && t.receiver == newThreadState.receiver | ||
if (!item.update.id) { | ||
throw new Error(`Uh oh! Thread update should definitely have the id at this point! Sync item: ${JSON.stringify(item)}`) | ||
} | ||
// update the latest id | ||
this.store.dispatch(actions.setLastThreadUpdateId(item.update.id)) | ||
this.store.dispatch(actions.setLastThreadUpdateId(Number(item.update.id))) | ||
// update active threads state | ||
@@ -225,3 +239,3 @@ this.store.dispatch(actions.setActiveThreads(newActiveThreads)) | ||
const update = item.update | ||
let update = item.update | ||
console.log(`Applying update from hub: ${update.reason} txCount=${update.txCount}:`, update) | ||
@@ -258,2 +272,8 @@ | ||
// add initial thread states from our store if the update | ||
// type includes threads | ||
if (update.reason.includes('Thread')) { | ||
update.initialThreadStates = connextState.persistent.activeInitialThreadStates | ||
} | ||
const nextState = await this.connext.validator.generateChannelStateFromRequest( | ||
@@ -273,3 +293,3 @@ update.reason === 'Invalidation' ? latestValidState : prevState, | ||
if (update.sigHub && update.sigUser) { | ||
this.store.dispatch(actions.setChannel({ | ||
this.store.dispatch(actions.setChannelAndUpdate({ | ||
update: update, | ||
@@ -288,10 +308,23 @@ state: { | ||
const args = update.args as ThreadState | ||
const connextState = this.store.getState() | ||
// unconditionally update thread history whether it is open or close | ||
// thread | ||
const threadHistory = connextState.persistent.threadHistory.concat({ | ||
sender: args.sender, | ||
receiver: args.receiver, | ||
threadId: args.threadId | ||
// thread. | ||
let wasDuplicate = false | ||
const threadHistory = connextState.persistent.threadHistory.map(t => { | ||
if (t.receiver == args.receiver && t.sender == args.sender) { | ||
// update the threadId in history with the one in args | ||
wasDuplicate = true | ||
return { ...t, threadId: args.threadId } | ||
} else { | ||
// otherwise, return the thread history item | ||
return t | ||
} | ||
}) | ||
// if this is new sender/receiver combo, push the thread history item | ||
if (!wasDuplicate) { | ||
threadHistory.push({ | ||
threadId: args.threadId, | ||
sender: args.sender, | ||
receiver: args.receiver, | ||
}) | ||
} | ||
@@ -298,0 +331,0 @@ // update active initial states depending if open or close |
import { assertUnreachable } from '../lib/utils' | ||
import { Block } from 'web3/eth/types' | ||
import { UpdateRequest, ChannelState, InvalidationArgs, Sync, ThreadStateUpdate, ArgsTypes, convertThreadState } from '../types' | ||
import { UpdateRequest, ChannelState, InvalidationArgs, Sync, ThreadStateUpdate, ArgsTypes, channelUpdateToUpdateRequest } from '../types' | ||
import { ChannelStateUpdate, SyncResult, InvalidationReason } from '../types' | ||
@@ -17,13 +17,2 @@ import { Poller } from '../lib/poller/Poller' | ||
function channelUpdateToUpdateRequest(up: ChannelStateUpdate): UpdateRequest { | ||
return { | ||
id: up.id, | ||
reason: up.reason, | ||
args: up.args, | ||
txCount: up.state.txCountGlobal, | ||
sigHub: up.state.sigHub, | ||
sigUser: up.state.sigUser, | ||
} | ||
} | ||
/** | ||
@@ -302,2 +291,7 @@ * This function should be used to update the `syncResultsFromHub` value in the | ||
// TODO: first ensure that any updates from or to hub are for the instantiated | ||
// user, hub currently does not return user for channels, users must | ||
// reinstantiate connext | ||
const updateKey = (x: SyncResult) => { | ||
@@ -381,9 +375,4 @@ if (x.type == 'channel') { | ||
const state = this.store.getState() | ||
let txCount = state.persistent.channel.txCountGlobal | ||
// TODO: fix the txCount with the state update controller | ||
// // ensure txCount is the latest | ||
// if (txCount == 0) { | ||
// const latest = await this.hub.getLatestChannelState() | ||
// txCount = latest ? latest.txCountGlobal : txCount | ||
// } | ||
const txCount = state.persistent.channel.txCountGlobal | ||
const hubSync = await this.hub.sync( | ||
@@ -397,2 +386,3 @@ txCount, | ||
} | ||
this.handleHubSync(hubSync) | ||
@@ -603,22 +593,22 @@ } catch (e) { | ||
public handleHubSync(sync: Sync) { | ||
if (this.store.getState().runtime.channelStatus !== sync.status) { | ||
this.store.dispatch(actions.setChannelStatus(sync.status)) | ||
} | ||
if (this.store.getState().runtime.channelStatus !== sync.status) { | ||
this.store.dispatch(actions.setChannelStatus(sync.status)) | ||
} | ||
// signing disabled in state update controller based on channel sync status | ||
// unconditionally enqueue results | ||
this.enqueueSyncResultsFromHub(sync.updates) | ||
// signing disabled in state update controller based on channel sync status | ||
// unconditionally enqueue results | ||
this.enqueueSyncResultsFromHub(sync.updates) | ||
// descriptive status error handling | ||
switch (sync.status) { | ||
case "CS_OPEN": | ||
break | ||
case "CS_CHANNEL_DISPUTE": | ||
break | ||
case "CS_THREAD_DISPUTE": | ||
throw new Error('THIS IS BAD. Channel is set to thread dispute state, before threads are enabled. See See REB-36. Disabling client.') | ||
default: | ||
assertUnreachable(sync.status) | ||
// descriptive status error handling | ||
switch (sync.status) { | ||
case "CS_OPEN": | ||
break | ||
case "CS_CHANNEL_DISPUTE": | ||
break | ||
case "CS_THREAD_DISPUTE": | ||
throw new Error('THIS IS BAD. Channel is set to thread dispute state, before threads are enabled. See See REB-36. Disabling client.') | ||
default: | ||
assertUnreachable(sync.status) | ||
} | ||
} | ||
} | ||
@@ -644,4 +634,2 @@ private async _flushPendingUpdatesToHub() { | ||
// TODO: will you ever have to add thread updates here | ||
// most thread updates are sent via the buy controller | ||
const threadSync = state.updatesToSync.filter(u => u.type == "thread") | ||
@@ -727,4 +715,8 @@ const threadUp = threadSync.map(u => u.update) as ThreadStateUpdate[] | ||
console.log('** merged **:', JSON.stringify(merged, null, 2)) | ||
const filtered = filterPendingSyncResults(merged, this.getSyncState().updatesToSync) | ||
const updatesToSync = this.getSyncState().updatesToSync | ||
console.log('** updatesToSync **', updatesToSync) | ||
const filtered = filterPendingSyncResults(merged, updatesToSync) | ||
console.log('** filtered **:', JSON.stringify(filtered, null, 2)) | ||
console.info(`updates from hub: ${updates.length}; old len: ${oldSyncResults.length}; merged: ${filtered.length}:`, filtered) | ||
@@ -731,0 +723,0 @@ this.store.dispatch(actions.setSortedSyncResultsFromHub(filtered)) |
@@ -1,2 +0,2 @@ | ||
import { Address, Payment, ThreadState, UnsignedThreadState, UpdateRequest, ThreadHistoryItem, ChannelState } from '../types' | ||
import { Address, Payment, ThreadState, UnsignedThreadState, UpdateRequest, ThreadHistoryItem, ChannelState, ChannelStateUpdate } from '../types' | ||
import { AbstractController } from './AbstractController'; | ||
@@ -55,2 +55,3 @@ | ||
const hubResponse = await this.hub.updateHub([updateRequest], state.persistent.lastThreadUpdateId) | ||
console.log('hubResponse:', hubResponse) | ||
this.connext.syncController.handleHubSync(hubResponse.updates) | ||
@@ -86,12 +87,9 @@ return { thread: initialState, channel: newChannelState } // shortcut for access within buycontroller | ||
const updateRequest: UpdateRequest = { | ||
const update: ChannelStateUpdate = { | ||
reason: "CloseThread", | ||
args: thread[0], | ||
txCount: newChannelState.txCountGlobal, | ||
sigUser: newChannelState.sigUser, | ||
initialThreadStates, // corr. to previous initial threads | ||
state: newChannelState, | ||
} | ||
const hubResponse = await this.hub.updateHub([updateRequest], state.persistent.lastThreadUpdateId) | ||
this.connext.syncController.handleHubSync(hubResponse.updates) | ||
await this.connext.syncController.sendUpdateToHub(update) | ||
} | ||
@@ -98,0 +96,0 @@ } |
@@ -67,3 +67,5 @@ import { SyncControllerState, RuntimeState, PendingRequestedDeposit } from './store' | ||
} | ||
export const setChannel = actionCreator<SetChannelActionArgs>('setChannelAndUpdate') | ||
export const setChannelAndUpdate = actionCreator<SetChannelActionArgs>('setChannelAndUpdate') | ||
export const setChannel = setterAction<ChannelState>('persistent.channel') | ||
export const setLatestValidState = setterAction<ChannelState>('persistent.latestValidState') | ||
export const setSyncControllerState = setterAction<SyncControllerState>('persistent.syncControllerState') | ||
@@ -70,0 +72,0 @@ export const setRequestedDeposit = setterAction<PendingRequestedDeposit | null>('persistent.requestedDeposit') |
@@ -19,2 +19,3 @@ import { SyncResult, } from '../types' | ||
!didInitialUpdate || | ||
action.type === 'connext/setChannelAndUpdate' || | ||
action.type === 'connext/set:runtime.syncResultsFromHub' || | ||
@@ -21,0 +22,0 @@ action.type === 'connext/set:persistent.channel' || |
@@ -5,2 +5,3 @@ import { isFunction } from '../lib/utils' | ||
import * as actions from './actions' | ||
import { UpdateRequest, ChannelState } from '@src/types'; | ||
@@ -17,6 +18,6 @@ export let reducers = reducerWithInitialState(new ConnextState()) | ||
reducers = reducers.case(actions.setChannel, (state, action) => { | ||
export function handleChannelChange(state: ConnextState, channel: ChannelState, update?: UpdateRequest) { | ||
const hasPending = ( | ||
Object.keys(action.state) | ||
.some(field => field.startsWith('pending') && (action.state as any)[field] != '0') | ||
Object.keys(channel) | ||
.some(field => field.startsWith('pending') && (channel as any)[field] != '0') | ||
) | ||
@@ -28,3 +29,3 @@ if (!hasPending) { | ||
...state.persistent, | ||
latestValidState: action.state, | ||
latestValidState: channel, | ||
}, | ||
@@ -34,2 +35,6 @@ } | ||
if (!update) { | ||
update = state.persistent.channelUpdate | ||
} | ||
return { | ||
@@ -39,8 +44,12 @@ ...state, | ||
...state.persistent, | ||
channel: action.state, | ||
channelUpdate: action.update, | ||
channel: channel, | ||
channelUpdate: update, | ||
}, | ||
} | ||
}) | ||
} | ||
reducers = reducers.case(actions.setChannelAndUpdate, (state, action) => handleChannelChange(state, action.state, action.update)) | ||
reducers = reducers.case(actions.setChannel, (state, action) => handleChannelChange(state, action)) | ||
for (let action of Object.values(actions) as any[]) { | ||
@@ -47,0 +56,0 @@ if (isFunction(action && action.handler)) |
@@ -191,2 +191,14 @@ import { mkHash, getWithdrawalArgs, getExchangeArgs } from '.' | ||
async getActiveThreads(): Promise<ThreadState[]> { | ||
return [] | ||
} | ||
async getLastThreadUpdateId(): Promise<number> { | ||
return 0 | ||
} | ||
async getAllThreads(): Promise<ThreadState[]> { | ||
return [] | ||
} | ||
async getChannelStateAtNonce(): Promise<ChannelStateUpdate> { | ||
@@ -200,3 +212,3 @@ return { | ||
async getThreadInitialStates(): Promise<UnsignedThreadState[]> { | ||
async getThreadInitialStates(): Promise<ThreadState[]> { | ||
return [getThreadState('full')] | ||
@@ -374,8 +386,14 @@ } | ||
} | ||
getLatestChannelState(): Promise<ChannelState | null> { | ||
let store = new MockStore | ||
//@ts-ignore | ||
return store._initialState.persistent.channel as ChannelState | null | ||
async getLatestChannelStateAndUpdate() { | ||
return null | ||
// let store = new MockStore() | ||
// //@ts-ignore | ||
// return {state: store._initialState.persistent.channel, update: store._initialState.persistent.channelUpdate} | ||
} | ||
async getLatestStateNoPendingOps(): Promise<ChannelState | null> { | ||
return null | ||
} | ||
assertReceivedUpdate(expected: PartialUpdateRequest) { | ||
@@ -382,0 +400,0 @@ for (let req of this.receivedUpdateRequests as any[]) { |
@@ -172,2 +172,9 @@ import BN = require('bn.js') | ||
export const DisputeStatus = { | ||
CD_PENDING: 'CD_PENDING', | ||
CD_IN_DISPUTE_PERIOD: 'CD_IN_DISPUTE_PERIOD', | ||
CD_FAILED: 'CD_FAILED', | ||
CD_FINISHED: 'CD_FINISHED' | ||
} | ||
export type DisputeStatus = keyof typeof DisputeStatus | ||
@@ -707,2 +714,9 @@ // channel update reasons | ||
export const withdrawalParamsNumericFields = [ | ||
'withdrawalWeiUser', | ||
'tokensToSell', | ||
'weiToSell', | ||
'withdrawalTokenUser', | ||
] | ||
/********************************* | ||
@@ -712,2 +726,13 @@ ******* TYPE CONVERSIONS ******** | ||
export function channelUpdateToUpdateRequest(up: ChannelStateUpdate): UpdateRequest { | ||
return { | ||
id: up.id, | ||
reason: up.reason, | ||
args: up.args, | ||
txCount: up.state.txCountGlobal, | ||
sigHub: up.state.sigHub, | ||
sigUser: up.state.sigUser, | ||
} | ||
} | ||
// util to convert from string to bn for all types | ||
@@ -714,0 +739,0 @@ export const channelNumericFields = [ |
import { subOrZero, objMap } from './StateGenerator' | ||
import { convertProposePending, InvalidationArgs, ArgsTypes, UnsignedThreadStateBN, EmptyChannelArgs, VerboseChannelEvent, VerboseChannelEventBN, EventInputs, ChannelEventReason, convertVerboseEvent, makeEventVerbose, SignedDepositRequestProposal } from './types' | ||
import { convertProposePending, InvalidationArgs, ArgsTypes, UnsignedThreadStateBN, EmptyChannelArgs, VerboseChannelEvent, VerboseChannelEventBN, EventInputs, ChannelEventReason, convertVerboseEvent, makeEventVerbose, SignedDepositRequestProposal, WithdrawalParametersBN } from './types' | ||
import { PendingArgs } from './types' | ||
@@ -42,3 +42,4 @@ import { PendingArgsBN } from './types' | ||
Payment, | ||
convertArgs | ||
convertArgs, | ||
withdrawalParamsNumericFields | ||
} from './types' | ||
@@ -50,4 +51,2 @@ import { StateGenerator } from './StateGenerator' | ||
import { TransactionReceipt } from 'web3/types' | ||
import { assert } from './testing'; | ||
import { util } from 'prettier'; | ||
@@ -262,2 +261,12 @@ // this constant is used to not lose precision on exchanges | ||
public withdrawalParams = (params: WithdrawalParametersBN): string | null => { | ||
if (+params.exchangeRate != +params.exchangeRate || +params.exchangeRate < 0) | ||
return 'invalid exchange rate: ' + params.exchangeRate | ||
return this.hasNegative(params, withdrawalParamsNumericFields) | ||
} | ||
public payment = (params: PaymentBN): string | null => { | ||
return this.hasNegative(params, argNumericFields.Payment) | ||
} | ||
public proposePendingWithdrawal = (prev: ChannelStateBN, args: WithdrawalArgsBN): string | null => { | ||
@@ -464,3 +473,3 @@ const errs = [ | ||
// If user is receiver then that means that prev is hub-receiver channel | ||
const userIsSender = args.sender === prev.user | ||
const userIsSender = args.sender == prev.user | ||
@@ -779,3 +788,3 @@ // First check thread state independently | ||
} catch (e) { | ||
return e.message | ||
errs.push('Error asserting thread signer: ' + e.message) | ||
} | ||
@@ -782,0 +791,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
4384035
621
26458