1 | import { providers } from "ethers";
|
2 |
|
3 | import {
|
4 | AppChallenge,
|
5 | ChallengeEvent,
|
6 | ChallengeEventData,
|
7 | ChallengeUpdatedEventPayload,
|
8 | SignedCancelChallengeRequest,
|
9 | StateProgressedEventPayload,
|
10 | ChallengeEvents,
|
11 | ContractAddresses,
|
12 | } from "./contracts";
|
13 | import { StateChannelJSON } from "./state";
|
14 | import { Address, Bytes32 } from "./basic";
|
15 | import { AppInstanceJson } from "./app";
|
16 | import {
|
17 | ConditionalTransactionCommitmentJSON,
|
18 | MinimalTransaction,
|
19 | SetStateCommitmentJSON,
|
20 | } from "./commitments";
|
21 | import { IChannelSigner } from "./crypto";
|
22 | import { ILoggerService, ILogger } from "./logger";
|
23 | import { Ctx } from "evt";
|
24 |
|
25 |
|
26 |
|
27 |
|
28 | export type WatcherInitOptions = {
|
29 | signer: IChannelSigner | string;
|
30 | provider: providers.JsonRpcProvider | string;
|
31 | context: ContractAddresses;
|
32 | store: IWatcherStoreService;
|
33 | logger?: ILoggerService | ILogger;
|
34 | logLevel?: number;
|
35 | };
|
36 |
|
37 |
|
38 |
|
39 |
|
40 | type BaseChallengeTransactionCompletedEvent = {
|
41 | transaction: providers.TransactionReceipt;
|
42 | appInstanceId: Bytes32;
|
43 | multisigAddress: Address;
|
44 | };
|
45 | type BaseChallengeTransactionFailedEvent = {
|
46 | appInstanceId: Bytes32;
|
47 | error: string;
|
48 | multisigAddress: Address;
|
49 | challenge: StoredAppChallenge | undefined;
|
50 | params: any;
|
51 | };
|
52 |
|
53 |
|
54 | export const ChallengeProgressedEvent = "ChallengeProgressedEvent";
|
55 | export type ChallengeProgressedEventData = BaseChallengeTransactionCompletedEvent;
|
56 |
|
57 |
|
58 | export const ChallengeProgressionFailedEvent = "ChallengeProgressionFailedEvent";
|
59 | export type ChallengeProgressionFailedEventData = BaseChallengeTransactionFailedEvent;
|
60 |
|
61 |
|
62 | export const ChallengeCompletedEvent = "ChallengeCompletedEvent";
|
63 | export type ChallengeCompletedEventData = BaseChallengeTransactionCompletedEvent;
|
64 |
|
65 |
|
66 | export const ChallengeCompletionFailedEvent = "ChallengeCompletionFailedEvent";
|
67 | export type ChallengeCompletionFailedEventData = BaseChallengeTransactionFailedEvent;
|
68 |
|
69 |
|
70 | export const ChallengeOutcomeSetEvent = "ChallengeOutcomeSetEvent";
|
71 | export type ChallengeOutcomeSetEventData = BaseChallengeTransactionCompletedEvent;
|
72 |
|
73 |
|
74 | export const ChallengeOutcomeFailedEvent = "ChallengeOutcomeFailedEvent";
|
75 | export type ChallengeOutcomeFailedEventData = BaseChallengeTransactionFailedEvent;
|
76 |
|
77 |
|
78 | export const ChallengeCancelledEvent = "ChallengeCancelledEvent";
|
79 | export type ChallengeCancelledEventData = BaseChallengeTransactionCompletedEvent;
|
80 |
|
81 |
|
82 | export const ChallengeCancellationFailedEvent = "ChallengeCancellationFailedEvent";
|
83 | export type ChallengeCancellationFailedEventData = BaseChallengeTransactionFailedEvent;
|
84 |
|
85 |
|
86 |
|
87 | export const ChallengeUpdatedEvent = "ChallengeUpdatedEvent";
|
88 | export type ChallengeUpdatedEventData = ChallengeEventData[typeof ChallengeEvents.ChallengeUpdated];
|
89 |
|
90 | export const StateProgressedEvent = "StateProgressedEvent";
|
91 | export type StateProgressedEventData = ChallengeEventData[typeof ChallengeEvents.StateProgressed];
|
92 |
|
93 |
|
94 | export const WatcherEvents = {
|
95 | [ChallengeUpdatedEvent]: ChallengeUpdatedEvent,
|
96 | [StateProgressedEvent]: StateProgressedEvent,
|
97 | [ChallengeProgressedEvent]: ChallengeProgressedEvent,
|
98 | [ChallengeProgressionFailedEvent]: ChallengeProgressionFailedEvent,
|
99 | [ChallengeOutcomeSetEvent]: ChallengeOutcomeSetEvent,
|
100 | [ChallengeOutcomeFailedEvent]: ChallengeOutcomeFailedEvent,
|
101 | [ChallengeCompletedEvent]: ChallengeCompletedEvent,
|
102 | [ChallengeCompletionFailedEvent]: ChallengeCompletionFailedEvent,
|
103 | [ChallengeCancelledEvent]: ChallengeCancelledEvent,
|
104 | [ChallengeCancellationFailedEvent]: ChallengeCancellationFailedEvent,
|
105 | } as const;
|
106 | export type WatcherEvent = keyof typeof WatcherEvents;
|
107 |
|
108 | interface WatcherEventDataMap {
|
109 | [ChallengeUpdatedEvent]: ChallengeUpdatedEventData;
|
110 | [StateProgressedEvent]: StateProgressedEventData;
|
111 | [ChallengeProgressedEvent]: ChallengeProgressedEventData;
|
112 | [ChallengeProgressionFailedEvent]: ChallengeProgressionFailedEventData;
|
113 | [ChallengeOutcomeFailedEvent]: ChallengeOutcomeFailedEventData;
|
114 | [ChallengeOutcomeSetEvent]: ChallengeOutcomeSetEventData;
|
115 | [ChallengeCompletedEvent]: ChallengeCompletedEventData;
|
116 | [ChallengeCompletionFailedEvent]: ChallengeCompletionFailedEventData;
|
117 | [ChallengeCancelledEvent]: ChallengeCancelledEventData;
|
118 | [ChallengeCancellationFailedEvent]: ChallengeCancellationFailedEventData;
|
119 | }
|
120 | export type WatcherEventData = {
|
121 | [P in keyof WatcherEventDataMap]: WatcherEventDataMap[P];
|
122 | };
|
123 |
|
124 |
|
125 |
|
126 |
|
127 |
|
128 |
|
129 |
|
130 | export type ChallengeInitiatedResponse = {
|
131 | freeBalanceChallenge: providers.TransactionReceipt;
|
132 | appChallenge: providers.TransactionReceipt;
|
133 | };
|
134 |
|
135 | export interface IWatcher {
|
136 |
|
137 | emit<T extends WatcherEvent>(event: T, data: WatcherEventData[T]): void;
|
138 | on<T extends WatcherEvent>(
|
139 | event: T,
|
140 | callback: (data: WatcherEventData[T]) => Promise<void>,
|
141 | filter?: (payload: WatcherEventData[T]) => boolean,
|
142 | ): void;
|
143 | once<T extends WatcherEvent>(
|
144 | event: T,
|
145 | callback: (data: WatcherEventData[T]) => Promise<void>,
|
146 | filter?: (payload: WatcherEventData[T]) => boolean,
|
147 | ): void;
|
148 | waitFor<T extends WatcherEvent>(
|
149 | event: T,
|
150 | timeout: number,
|
151 | filter?: (payload: WatcherEventData[T]) => boolean,
|
152 | ): Promise<WatcherEventData[T]>;
|
153 | off(): void;
|
154 |
|
155 |
|
156 | enable(): Promise<void>;
|
157 | disable(): Promise<void>;
|
158 | initiate(appIdentityHash: string): Promise<ChallengeInitiatedResponse>;
|
159 | cancel(
|
160 | appIdentityHash: string,
|
161 | req: SignedCancelChallengeRequest,
|
162 | ): Promise<providers.TransactionReceipt>;
|
163 | }
|
164 |
|
165 |
|
166 |
|
167 |
|
168 | export interface IChainListener {
|
169 |
|
170 | attach<T extends ChallengeEvent>(
|
171 | event: T,
|
172 | callback: (data: ChallengeEventData[T]) => Promise<void>,
|
173 | providedFilter?: (data: ChallengeEventData[T]) => boolean,
|
174 | ctx?: Ctx<ChallengeEventData[T]>,
|
175 | ): void;
|
176 |
|
177 | attachOnce<T extends ChallengeEvent>(
|
178 | event: T,
|
179 | callback: (data: ChallengeEventData[T]) => Promise<void>,
|
180 | providedFilter?: (data: ChallengeEventData[T]) => boolean,
|
181 | ctx?: Ctx<ChallengeEventData[T]>,
|
182 | ): void;
|
183 |
|
184 | waitFor<T extends ChallengeEvent>(
|
185 | event: T,
|
186 | timeout: number,
|
187 | providedFilter?: (data: ChallengeEventData[T]) => boolean,
|
188 | ctx?: Ctx<ChallengeEventData[T]>,
|
189 | ): Promise<ChallengeEventData[T]>;
|
190 |
|
191 | createContext<T extends ChallengeEvent>(): Ctx<ChallengeEventData[T]>;
|
192 | detach<T extends ChallengeEvent>(ctx?: Ctx<ChallengeEventData[T]>): void;
|
193 |
|
194 |
|
195 | enable(): Promise<void>;
|
196 | disable(): Promise<void>;
|
197 | parseLogsFrom(startingBlock: number): Promise<void>;
|
198 | }
|
199 |
|
200 |
|
201 |
|
202 |
|
203 | export enum StoredAppChallengeStatus {
|
204 | NO_CHALLENGE = 0,
|
205 | IN_DISPUTE = 1,
|
206 | IN_ONCHAIN_PROGRESSION = 2,
|
207 | EXPLICITLY_FINALIZED = 3,
|
208 | OUTCOME_SET = 4,
|
209 | CONDITIONAL_SENT = 5,
|
210 | PENDING_TRANSITION = 6,
|
211 | }
|
212 | export type StoredAppChallenge = Omit<AppChallenge, "status"> & {
|
213 | identityHash: Bytes32;
|
214 | status: StoredAppChallengeStatus;
|
215 | };
|
216 |
|
217 | export interface IWatcherStoreService {
|
218 |
|
219 | getAppChallenge(appIdentityHash: Bytes32): Promise<StoredAppChallenge | undefined>;
|
220 | saveAppChallenge(data: ChallengeUpdatedEventPayload | StoredAppChallenge): Promise<void>;
|
221 | getActiveChallenges(): Promise<StoredAppChallenge[]>;
|
222 |
|
223 |
|
224 | getLatestProcessedBlock(): Promise<number>;
|
225 | updateLatestProcessedBlock(blockNumber: number): Promise<void>;
|
226 |
|
227 | getStateProgressedEvents(appIdentityHash: Bytes32): Promise<StateProgressedEventPayload[]>;
|
228 | createStateProgressedEvent(event: StateProgressedEventPayload): Promise<void>;
|
229 |
|
230 | getChallengeUpdatedEvents(appIdentityHash: Bytes32): Promise<ChallengeUpdatedEventPayload[]>;
|
231 | createChallengeUpdatedEvent(event: ChallengeUpdatedEventPayload): Promise<void>;
|
232 |
|
233 | addOnchainAction(appIdentityHash: Bytes32, provider: providers.JsonRpcProvider): Promise<void>;
|
234 |
|
235 |
|
236 |
|
237 |
|
238 |
|
239 | getSchemaVersion(): Promise<number>;
|
240 |
|
241 |
|
242 | getAllChannels(): Promise<StateChannelJSON[]>;
|
243 | getStateChannel(multisigAddress: Address): Promise<StateChannelJSON | undefined>;
|
244 | getStateChannelByOwnersAndChainId(
|
245 | owners: Address[],
|
246 | chainId: number,
|
247 | ): Promise<StateChannelJSON | undefined>;
|
248 | getStateChannelByAppIdentityHash(appIdentityHash: Bytes32): Promise<StateChannelJSON | undefined>;
|
249 |
|
250 |
|
251 | getAppInstance(appIdentityHash: Bytes32): Promise<AppInstanceJson | undefined>;
|
252 |
|
253 |
|
254 | getAppProposal(appIdentityHash: Bytes32): Promise<AppInstanceJson | undefined>;
|
255 |
|
256 |
|
257 | getFreeBalance(multisigAddress: Address): Promise<AppInstanceJson | undefined>;
|
258 |
|
259 |
|
260 | getSetupCommitment(multisigAddress: Address): Promise<MinimalTransaction | undefined>;
|
261 |
|
262 |
|
263 | getSetStateCommitments(appIdentityHash: Bytes32): Promise<SetStateCommitmentJSON[]>;
|
264 |
|
265 |
|
266 | getConditionalTransactionCommitment(
|
267 | appIdentityHash: Bytes32,
|
268 | ): Promise<ConditionalTransactionCommitmentJSON | undefined>;
|
269 | }
|