diff --git a/packages/nitro-client/src/channel/channel.ts b/packages/nitro-client/src/channel/channel.ts index 11ba2caf..65b70e6d 100644 --- a/packages/nitro-client/src/channel/channel.ts +++ b/packages/nitro-client/src/channel/channel.ts @@ -87,7 +87,15 @@ export class Channel extends FixedPart { // json-encoded data // TODO: Can throw an error // TODO: Implement - UnmarshalJSON(data: Buffer): void {} + unmarshalJSON(data: Buffer): void { + try { + // TODO: Implement json.Unmarshal + const jsonCh = JSON.parse(data.toString()); + Object.assign(this, jsonCh); + } catch (err) { + throw new Error('error unmarshaling channel data'); + } + } // MyDestination returns the client's destination // TODO: Implement diff --git a/packages/nitro-client/src/client/engine/store/memstore.ts b/packages/nitro-client/src/client/engine/store/memstore.ts index 05b31a06..65b6e604 100644 --- a/packages/nitro-client/src/client/engine/store/memstore.ts +++ b/packages/nitro-client/src/client/engine/store/memstore.ts @@ -2,7 +2,7 @@ import { bytes2Hex } from '@cerc-io/nitro-util'; import { ethers } from 'ethers'; import assert from 'assert'; -import { Store } from './store'; +import { ErrNoSuchChannel, Store } from './store'; import { Objective, ObjectiveStatus } from '../../../protocols/interfaces'; import { Channel } from '../../../channel/channel'; import { ConsensusChannel } from '../../../channel/consensus-channel/consensus-channel'; @@ -150,13 +150,33 @@ export class MemStore implements Store { destroyConsensusChannel(id: string): void {} getChannelById(id: Destination): [Channel, boolean] { - // TODO: Implement - return [{} as Channel, false]; + try { + const ch = this._getChannelById(id); + + return [ch, true]; + } catch (err) { + return [new Channel({}), false]; + } } private _getChannelById(id: Destination): Channel { - // TODO: Implement - return {} as Channel; + const [chJSON, ok] = this.channels.load(id.toString()); + + if (!ok) { + throw ErrNoSuchChannel; + } + + assert(chJSON); + + const ch = new Channel({}); + + try { + ch.unmarshalJSON(chJSON); + + return ch; + } catch (err) { + throw new Error(`error unmarshaling channel ${ch.id}`); + } } // TODO: Implement diff --git a/packages/nitro-client/src/client/engine/store/store.ts b/packages/nitro-client/src/client/engine/store/store.ts index 88af5f11..cb9dd10a 100644 --- a/packages/nitro-client/src/client/engine/store/store.ts +++ b/packages/nitro-client/src/client/engine/store/store.ts @@ -5,6 +5,8 @@ import { VoucherStore } from '../../../payments/voucher-manager'; import { Address } from '../../../types/types'; import { Destination } from '../../../types/destination'; +export const ErrNoSuchChannel = new Error('store: failed to find required channel data'); + // Store is responsible for persisting objectives, objective metadata, states, signatures, private keys and blockchain data export interface Store extends ConsensusChannelStore, VoucherStore { // Get a pointer to a secret key for signing channel updates diff --git a/packages/nitro-client/src/client/query/query.ts b/packages/nitro-client/src/client/query/query.ts index 613a3e9e..6fe65ce0 100644 --- a/packages/nitro-client/src/client/query/query.ts +++ b/packages/nitro-client/src/client/query/query.ts @@ -68,11 +68,6 @@ const getLatestSupportedOrPreFund = (channel: Channel): State => { return channel.preFundState(); }; -// GetPaymentChannelInfo returns the PaymentChannelInfo for the given channel -// It does this by querying the provided store and voucher manager -// TODO: Implement -export const getPaymentChannelInfo = (id: Destination, store: Store, vm: VoucherManager): PaymentChannelInfo => new PaymentChannelInfo({}); - export const getVoucherBalance = (id: Destination, vm: VoucherManager): [bigint, bigint] => { let paid: bigint = BigInt(0); let remaining: bigint = BigInt(0); @@ -87,25 +82,6 @@ export const getVoucherBalance = (id: Destination, vm: VoucherManager): [bigint, return [paid, remaining]; }; -export const constructLedgerInfoFromConsensus = (con: ConsensusChannel): LedgerChannelInfo => { - const latest = con.consensusVars().asState(con.fixedPart()); - return new LedgerChannelInfo({ - iD: con.id, - status: ChannelStatus.Open, - balance: getLedgerBalanceFromState(latest), - }); -}; - -export const constructLedgerInfoFromChannel = (c: Channel): LedgerChannelInfo => { - const latest = getLatestSupportedOrPreFund(c); - - return new LedgerChannelInfo({ - iD: c.id, - status: getStatusFromChannel(c), - balance: getLedgerBalanceFromState(latest), - }); -}; - export const constructPaymentInfo = (c: Channel, paid: bigint, remaining: bigint): PaymentChannelInfo => { let status = getStatusFromChannel(c); @@ -129,3 +105,36 @@ export const constructPaymentInfo = (c: Channel, paid: bigint, remaining: bigint balance, }); }; + +// GetPaymentChannelInfo returns the PaymentChannelInfo for the given channel +// It does this by querying the provided store and voucher manager +export const getPaymentChannelInfo = (id: Destination, store: Store, vm: VoucherManager): PaymentChannelInfo => { + const [c, channelFound] = store.getChannelById(id); + + if (channelFound) { + const [paid, remaining] = getVoucherBalance(id, vm); + + return constructPaymentInfo(c, paid, remaining); + } + + throw new Error(`Could not find channel with id ${id}`); +}; + +export const constructLedgerInfoFromConsensus = (con: ConsensusChannel): LedgerChannelInfo => { + const latest = con.consensusVars().asState(con.fixedPart()); + return new LedgerChannelInfo({ + iD: con.id, + status: ChannelStatus.Open, + balance: getLedgerBalanceFromState(latest), + }); +}; + +export const constructLedgerInfoFromChannel = (c: Channel): LedgerChannelInfo => { + const latest = getLatestSupportedOrPreFund(c); + + return new LedgerChannelInfo({ + iD: c.id, + status: getStatusFromChannel(c), + balance: getLedgerBalanceFromState(latest), + }); +};