diff --git a/package-lock.json b/package-lock.json index 5ea89484..918c4472 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@terra-money/feather.js", - "version": "2.0.0-beta.14", + "version": "2.0.0-beta.15", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@terra-money/feather.js", - "version": "2.0.0-beta.14", + "version": "2.0.0-beta.15", "license": "MIT", "dependencies": { "@ethersproject/bytes": "^5.7.0", diff --git a/package.json b/package.json index da740d53..2b433835 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@terra-money/feather.js", - "version": "2.0.0-beta.14", + "version": "2.0.0-beta.15", "description": "The JavaScript SDK for Terra and Feather chains", "license": "MIT", "author": "Terraform Labs, PTE.", diff --git a/src/client/lcd/api/IbcAPI.ts b/src/client/lcd/api/IbcAPI.ts index e3cdc9c3..8efa5dda 100644 --- a/src/client/lcd/api/IbcAPI.ts +++ b/src/client/lcd/api/IbcAPI.ts @@ -5,7 +5,7 @@ import { ClientConsensusStates } from '../../../core/ibc/core/client/ClientConse import { LCDClient } from '../LCDClient'; //import { Params as ControllerParams } from '../../../core/ibc/applications/interchain-account/controller/Params'; import { Params as HostParams } from '../../../core/ibc/applications/interchain-account/host/Params'; -import { Channel } from '../../../core/ibc/core/channel'; +import { Channel, IdentifiedChannel } from '../../../core/ibc/core/channel'; import { IdentifiedConnection } from '../../../core/ibc/core/connection'; import { Height } from '../../../core/ibc/core/client/Height'; export interface IbcClientParams { @@ -53,13 +53,16 @@ export class IbcAPI extends BaseAPI { public async channels( chainID: string, params: APIParams = {} - ): Promise<[Channel[], Pagination]> { - return this.getReqFromChainID(chainID) - .get<{ - channels: Channel.Data[]; - pagination: Pagination; - }>(`/ibc/core/channel/v1/channels`, params) - .then(d => [d.channels.map(Channel.fromData), d.pagination]); + ): Promise<{ channels: IdentifiedChannel[]; pagination: Pagination }> { + const res = await this.getReqFromChainID(chainID).get<{ + channels: IdentifiedChannel.Data[]; + pagination: Pagination; + }>(`/ibc/core/channel/v1/channels`, params); + + return { + channels: res.channels.map(IdentifiedChannel.fromData), + pagination: res.pagination, + }; } /** diff --git a/src/core/ibc/core/channel/IdentifiedChannel.ts b/src/core/ibc/core/channel/IdentifiedChannel.ts new file mode 100644 index 00000000..f67bdc0c --- /dev/null +++ b/src/core/ibc/core/channel/IdentifiedChannel.ts @@ -0,0 +1,191 @@ +import { + State, + Order, + IdentifiedChannel as IdentifiedChannel_pb, +} from '@terra-money/terra.proto/ibc/core/channel/v1/channel'; +import { JSONSerializable } from '../../../../util/json'; +import { Counterparty } from './Counterparty'; + +/** + * IdentifiedChannel is a monotonically increasing data type + * that can be compared against another IdentifiedChannel for the purposes of updating and + * freezing clients + * + * Normally the RevisionChannel is incremented at each height while keeping + * RevisionNumber the same. However some consensus algorithms may choose to + * reset the height in certain conditions e.g. hard forks, state-machine + * breaking changes In these cases, the RevisionNumber is incremented so that + * height continues to be monitonically increasing even as the RevisionChannel + * gets reset + */ +export class IdentifiedChannel extends JSONSerializable< + IdentifiedChannel.Amino, + IdentifiedChannel.Data, + IdentifiedChannel.Proto +> { + /** + * @param state current state of the channel end + * @param ordering whether the channel is ordered or unordered + * @param counterparty counterparty channel end + * @param connection_hops list of connection identifiers, in order, along which packets sent on this channel will travel + * @param version opaque channel version, which is agreed upon during the handshake + * @param port_id the + * @param channel_id + */ + constructor( + public state: State, + public ordering: Order, + public counterparty: Counterparty | undefined, + public connection_hops: string[], + public version: string, + public port_id: string, + public channel_id: string + ) { + super(); + } + + public static fromAmino(data: IdentifiedChannel.Amino): IdentifiedChannel { + const { + state, + ordering, + counterparty, + connection_hops, + version, + port_id, + channel_id, + } = data; + return new IdentifiedChannel( + state, + ordering, + counterparty ? Counterparty.fromAmino(counterparty) : undefined, + connection_hops, + version, + port_id, + channel_id + ); + } + + public toAmino(): IdentifiedChannel.Amino { + const { + state, + ordering, + counterparty, + connection_hops, + version, + port_id, + channel_id, + } = this; + const res: IdentifiedChannel.Amino = { + state, + ordering, + counterparty: counterparty ? counterparty.toAmino() : undefined, + connection_hops, + version, + port_id, + channel_id, + }; + return res; + } + + public static fromData(data: IdentifiedChannel.Data): IdentifiedChannel { + const { + state, + ordering, + counterparty, + connection_hops, + version, + port_id, + channel_id, + } = data; + return new IdentifiedChannel( + state, + ordering, + counterparty ? Counterparty.fromData(counterparty) : undefined, + connection_hops, + version, + port_id, + channel_id + ); + } + + public toData(): IdentifiedChannel.Data { + const { + state, + ordering, + counterparty, + connection_hops, + version, + port_id, + channel_id, + } = this; + const res: IdentifiedChannel.Data = { + state, + ordering, + counterparty: counterparty ? counterparty.toData() : undefined, + connection_hops, + version, + port_id, + channel_id, + }; + return res; + } + + public static fromProto(proto: IdentifiedChannel.Proto): IdentifiedChannel { + return new IdentifiedChannel( + proto.state, + proto.ordering, + proto.counterparty + ? Counterparty.fromProto(proto.counterparty) + : undefined, + proto.connectionHops, + proto.version, + proto.portId, + proto.channelId + ); + } + + public toProto(): IdentifiedChannel.Proto { + const { + state, + ordering, + counterparty, + connection_hops, + version, + port_id, + channel_id, + } = this; + return IdentifiedChannel_pb.fromPartial({ + state, + ordering, + counterparty: counterparty ? counterparty.toProto() : undefined, + connectionHops: connection_hops, + version, + portId: port_id, + channelId: channel_id, + }); + } +} + +export namespace IdentifiedChannel { + export interface Amino { + state: State; + ordering: Order; + counterparty?: Counterparty.Amino; + connection_hops: string[]; + version: string; + port_id: string; + channel_id: string; + } + + export interface Data { + state: State; + ordering: Order; + counterparty?: Counterparty.Data; + connection_hops: string[]; + version: string; + port_id: string; + channel_id: string; + } + + export type Proto = IdentifiedChannel_pb; +} diff --git a/src/core/ibc/core/channel/index.ts b/src/core/ibc/core/channel/index.ts index 1bad8331..2d38f805 100644 --- a/src/core/ibc/core/channel/index.ts +++ b/src/core/ibc/core/channel/index.ts @@ -1,2 +1,5 @@ export * from './Channel'; +export * from './Counterparty'; export * from './PacketId'; +export * from './Packet'; +export * from './IdentifiedChannel'; diff --git a/src/core/ibc/core/index.ts b/src/core/ibc/core/index.ts index 978a24b6..df932e08 100644 --- a/src/core/ibc/core/index.ts +++ b/src/core/ibc/core/index.ts @@ -1,3 +1,2 @@ export * from './channel'; export * from './commitment'; -export * from './connection';