diff --git a/src/@types/js-xdr/index.d.ts b/src/@types/js-xdr/index.d.ts new file mode 100644 index 000000000..950c37c2f --- /dev/null +++ b/src/@types/js-xdr/index.d.ts @@ -0,0 +1,42 @@ +// Type definitions for js-xdr v1.1.1 +declare module "js-xdr" { + // TS-TODO: Add original signature https://github.com/stellar/js-stellar-base/blob/typescript/types/index.d.ts#L530 + export class Operation extends XDRStruct { + static fromXDR(xdr: Buffer): Operation; + } + + export class XDRStruct { + static fromXDR(xdr: Buffer): XDRStruct; + + toXDR(base?: string): Buffer; + toXDR(encoding: string): string; + } + + export class Asset extends XDRStruct { + static fromXDR(xdr: Buffer): Asset; + } + + export class Memo extends XDRStruct { + static fromXDR(xdr: Buffer): Memo; + } + + export class TransactionEnvelope extends XDRStruct { + static fromXDR(xdr: Buffer): TransactionEnvelope; + } + + export class DecoratedSignature extends XDRStruct { + static fromXDR(xdr: Buffer): DecoratedSignature; + + constructor(keys: { hint: SignatureHint; signature: Signature }); + + hint(): SignatureHint; + signature(): Buffer; + } + + export type SignatureHint = Buffer; + export type Signature = Buffer; + + export class TransactionResult extends XDRStruct { + static fromXDR(xdr: Buffer): TransactionResult; + } +} diff --git a/src/memo.ts b/src/memo.ts index 988822b35..137394bfb 100644 --- a/src/memo.ts +++ b/src/memo.ts @@ -1,7 +1,7 @@ import isUndefined from 'lodash/isUndefined'; import isString from 'lodash/isString'; import clone from 'lodash/clone'; -import { UnsignedHyper } from 'js-xdr'; +import { UnsignedHyper, Memo as XDRMemo } from 'js-xdr'; import BigNumber from 'bignumber.js'; import xdr from './generated/stellar-xdr_generated'; @@ -26,34 +26,60 @@ export const MemoHash = 'hash'; */ export const MemoReturn = 'return'; +export namespace MemoType { + export type None = typeof MemoNone; + export type ID = typeof MemoID; + export type Text = typeof MemoText; + export type Hash = typeof MemoHash; + export type Return = typeof MemoReturn; +} + +export type MemoType = + | MemoType.None + | MemoType.ID + | MemoType.Text + | MemoType.Hash + | MemoType.Return; + +export type MemoValue = + T extends MemoType.None ? null : + T extends MemoType.ID ? string : + T extends MemoType.Text ? string | Buffer : // github.com/stellar/js-stellar-base/issues/152 + T extends MemoType.Hash ? string | Buffer : + T extends MemoType.Return ? string | Buffer + : never; + /** * `Memo` represents memos attached to transactions. * - * @param {string} type - `MemoNone`, `MemoID`, `MemoText`, `MemoHash` or `MemoReturn` + * @param {string} memoType - `MemoNone`, `MemoID`, `MemoText`, `MemoHash` or `MemoReturn` * @param {*} value - `string` for `MemoID`, `MemoText`, buffer of hex string for `MemoHash` or `MemoReturn` * @see [Transactions concept](https://www.stellar.org/developers/learn/concepts/transactions.html) * @class Memo */ -export class Memo { - constructor(type, value = null) { - this._type = type; - this._value = value; +export class Memo { + _type: T; + _value: MemoValue; + + constructor(memoType: T, value?: MemoValue) { + this._type = memoType; + this._value = value as MemoValue; switch (this._type) { case MemoNone: break; case MemoID: - Memo._validateIdValue(value); + Memo._validateIdValue(value as MemoValue); break; case MemoText: - Memo._validateTextValue(value); + Memo._validateTextValue(value as MemoValue); break; case MemoHash: case MemoReturn: - Memo._validateHashValue(value); + Memo._validateHashValue(value as MemoValue); // We want MemoHash and MemoReturn to have Buffer as a value if (isString(value)) { - this._value = Buffer.from(value, 'hex'); + this._value = Buffer.from(value, 'hex') as MemoValue; } break; default: @@ -64,11 +90,11 @@ export class Memo { /** * Contains memo type: `MemoNone`, `MemoID`, `MemoText`, `MemoHash` or `MemoReturn` */ - get type() { + get type(): T { return clone(this._type); } - set type(type) { + set type(_type: T) { throw new Error('Memo is immutable'); } @@ -79,26 +105,26 @@ export class Memo { * * `Buffer` for `MemoText` after decoding using `fromXDRObject`, original value otherwise, * * `Buffer` for `MemoHash`, `MemoReturn`. */ - get value() { + get value(): MemoValue { switch (this._type) { case MemoNone: - return null; + return null as MemoValue; case MemoID: case MemoText: return clone(this._value); case MemoHash: case MemoReturn: - return Buffer.from(this._value); + return Buffer.from(this._value as string) as MemoValue; default: throw new Error('Invalid memo type'); } } - set value(value) { + set value(_value: MemoValue) { throw new Error('Memo is immutable'); } - static _validateIdValue(value) { + static _validateIdValue(value: MemoValue) { const error = new Error(`Expects a int64 as a string. Got ${value}`); if (!isString(value)) { @@ -123,13 +149,13 @@ export class Memo { } } - static _validateTextValue(value) { + static _validateTextValue(value: MemoValue) { if (!xdr.Memo.armTypeForArm('text').isValid(value)) { throw new Error('Expects string, array or buffer, max 28 bytes'); } } - static _validateHashValue(value) { + static _validateHashValue(value: MemoValue) { const error = new Error( `Expects a 32 byte hash value or hex encoded string. Got ${value}` ); @@ -159,7 +185,7 @@ export class Memo { * Returns an empty memo (`MemoNone`). * @returns {Memo} */ - static none() { + static none(): Memo { return new Memo(MemoNone); } @@ -168,7 +194,7 @@ export class Memo { * @param {string} text - memo text * @returns {Memo} */ - static text(text) { + static text(text: MemoValue): Memo { return new Memo(MemoText, text); } @@ -177,7 +203,7 @@ export class Memo { * @param {string} id - 64-bit number represented as a string * @returns {Memo} */ - static id(id) { + static id(id: MemoValue): Memo { return new Memo(MemoID, id); } @@ -186,7 +212,7 @@ export class Memo { * @param {array|string} hash - 32 byte hash or hex encoded string * @returns {Memo} */ - static hash(hash) { + static hash(hash: MemoValue): Memo { return new Memo(MemoHash, hash); } @@ -195,7 +221,7 @@ export class Memo { * @param {array|string} hash - 32 byte hash or hex encoded string * @returns {Memo} */ - static return(hash) { + static return(hash: MemoValue): Memo { return new Memo(MemoReturn, hash); } @@ -203,7 +229,7 @@ export class Memo { * Returns XDR memo object. * @returns {xdr.Memo} */ - toXDRObject() { + toXDRObject(): XDRMemo | null { switch (this._type) { case MemoNone: return xdr.Memo.memoNone(); @@ -222,24 +248,24 @@ export class Memo { /** * Returns {@link Memo} from XDR memo object. - * @param {xdr.Memo} object XDR memo object + * @param {xdr.Memo} xdrObject XDR memo object * @returns {Memo} */ - static fromXDRObject(object) { - switch (object.arm()) { + static fromXDRObject(xdrObject: XDRMemo): Memo { + switch (xdrObject.arm()) { case 'id': - return Memo.id(object.value().toString()); + return Memo.id(xdrObject.value().toString()); case 'text': - return Memo.text(object.value()); + return Memo.text(xdrObject.value()); case 'hash': - return Memo.hash(object.value()); + return Memo.hash(xdrObject.value()); case 'retHash': - return Memo.return(object.value()); + return Memo.return(xdrObject.value()); default: break; } - if (typeof object.value() === 'undefined') { + if (typeof xdrObject.value() === 'undefined') { return Memo.none(); } diff --git a/src/network.ts b/src/network.ts index bc7b869c4..a08099b10 100644 --- a/src/network.ts +++ b/src/network.ts @@ -1,17 +1,22 @@ import { hash } from './hashing'; +interface Networks { + PUBLIC: string; + TESTNET: string; +} + /** * Contains passphrases for common networks: * * `Networks.PUBLIC`: `Public Global Stellar Network ; September 2015` * * `Networks.TESTNET`: `Test SDF Network ; September 2015` * @type {{PUBLIC: string, TESTNET: string}} */ -export const Networks = { +export const Networks: Networks = { PUBLIC: 'Public Global Stellar Network ; September 2015', TESTNET: 'Test SDF Network ; September 2015' }; -let current = null; +let current: Network | null = null; /** * The Network class provides helper methods to get the passphrase or id for different @@ -26,7 +31,9 @@ let current = null; * @param {string} networkPassphrase Network passphrase */ export class Network { - constructor(networkPassphrase) { + private _networkPassphrase: string; + + constructor(networkPassphrase: string) { this._networkPassphrase = networkPassphrase; } @@ -34,7 +41,7 @@ export class Network { * Use Stellar Public Network * @returns {void} */ - static usePublicNetwork() { + static usePublicNetwork(): void { this.use(new Network(Networks.PUBLIC)); } @@ -42,7 +49,7 @@ export class Network { * Use test network. * @returns {void} */ - static useTestNetwork() { + static useTestNetwork(): void { this.use(new Network(Networks.TESTNET)); } @@ -51,28 +58,28 @@ export class Network { * @param {Network} network Network to use * @returns {void} */ - static use(network) { + static use(network: Network): void { current = network; } /** * @returns {Network} Currently selected network */ - static current() { + static current(): Network | null { return current; } /** * @returns {string} Network passphrase */ - networkPassphrase() { + public networkPassphrase(): string { return this._networkPassphrase; } /** * @returns {string} Network ID (SHA-256 hash of network passphrase) */ - networkId() { + public networkId(): Buffer { return hash(this.networkPassphrase()); } }