From 8afc78245747ab9d05fc541eccc144e84a50360d Mon Sep 17 00:00:00 2001 From: Akuukis Date: Thu, 25 Jul 2019 10:31:08 +0300 Subject: [PATCH 1/3] feat(typings): brand Secret, PublicKey, AccounId --- package.json | 3 +- types/index.d.ts | 110 +++++++++++++++++++++++++++++++---------------- yarn.lock | 5 +++ 3 files changed, 80 insertions(+), 38 deletions(-) diff --git a/package.json b/package.json index f8e296ba4..73b8110f7 100644 --- a/package.json +++ b/package.json @@ -108,7 +108,8 @@ "js-xdr": "^1.1.1", "lodash": "^4.17.11", "sha.js": "^2.3.6", - "tweetnacl": "^1.0.0" + "tweetnacl": "^1.0.0", + "utility-types": "^3.7.0" }, "optionalDependencies": { "sodium-native": "^2.3.0" diff --git a/types/index.d.ts b/types/index.d.ts index 71a38b689..77f6c17a9 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -1,11 +1,47 @@ // TypeScript Version: 2.9 - /// + +import { Brand } from "utility-types"; + + export {}; +/** + * 56-character long string, starts with S and passes `StrKey.isValidEd25519SecretSeed()`. + */ +export type Secret = Brand; + +/** + * 56-character long string, starts with G, passes `StrKey.isValidEd25519PublicKey()` + * and account does not exist on the given Network.. + * + * See also `AccountId`, `PublicKey`. + */ +export type NonExistingAccountId = Brand; + +/** + * 56-character long string, starts with G, passes `StrKey.isValidEd25519PublicKey()` + * and account exists on the given Network. + * + * See also `NonExistingAccountId`, `PublicKey`. + */ +export type AccountId = Brand; + +/** + * 56-character long string, starts with G and passes `StrKey.isValidEd25519PublicKey()`. + * Does **not** imply that an account with such address exists. + * + * See also `AccountId`, `NonExistingAccountId`. + */ +export type PublicKey = NonExistingAccountId | AccountId; + +/** + * `Account` can be created using either `AccountId` or `PublicKey`, + * and it's up to developer to ensure that Account exists at transaction submission. + */ export class Account { - constructor(accountId: string, sequence: string); - accountId(): string; + constructor(accountId: PublicKey, sequence: string); + accountId(): AccountId; sequenceNumber(): string; incrementSequenceNumber(): void; } @@ -24,17 +60,17 @@ export class Asset { static native(): Asset; static fromOperation(xdr: xdr.Asset): Asset; - constructor(code: string, issuer: string); + constructor(code: string, issuer: AccountId); getCode(): string; - getIssuer(): string; + getIssuer(): AccountId; getAssetType(): AssetType; isNative(): boolean; equals(other: Asset): boolean; toXDRObject(): xdr.Asset; code: string; - issuer: string; + issuer: AccountId; } export const FastSigning: boolean; @@ -44,20 +80,20 @@ export type KeypairType = 'ed25519'; export class Keypair { static fromRawEd25519Seed(secretSeed: Buffer): Keypair; static fromBase58Seed(secretSeed: string): Keypair; - static fromSecret(secretKey: string): Keypair; + static fromSecret(secretKey: Secret): Keypair; static master(): Keypair; - static fromPublicKey(publicKey: string): Keypair; + static fromPublicKey(publicKey: PublicKey): Keypair; static random(): Keypair; constructor( keys: - | { type: KeypairType; secretKey: string; publicKey?: string } - | { type: KeypairType; publicKey: string } + | { type: KeypairType; secretKey: Secret; publicKey?: PublicKey } + | { type: KeypairType; publicKey: PublicKey } ); readonly type: KeypairType; - publicKey(): string; - secret(): string; + publicKey(): PublicKey; + secret(): Secret; rawPublicKey(): Buffer; rawSecretKey(): Buffer; canSign(): boolean; @@ -153,7 +189,7 @@ export type AuthFlag = export namespace Signer { interface Ed25519PublicKey { - ed25519PublicKey: string; + ed25519PublicKey: PublicKey; weight: number | undefined; } interface Sha256Hash { @@ -172,7 +208,7 @@ export type Signer = export namespace SignerOptions { interface Ed25519PublicKey { - ed25519PublicKey: string; + ed25519PublicKey: PublicKey; weight?: number | string; } interface Sha256Hash { @@ -221,13 +257,13 @@ export type OperationType = export namespace OperationOptions { interface BaseOptions { - source?: string; + source?: AccountId; } interface AccountMerge extends BaseOptions { - destination: string; + destination: AccountId; } interface AllowTrust extends BaseOptions { - trustor: string; + trustor: AccountId; assetCode: string; authorize?: boolean; } @@ -236,7 +272,7 @@ export namespace OperationOptions { limit?: string; } interface CreateAccount extends BaseOptions { - destination: string; + destination: NonExistingAccountId; startingBalance: string; } interface CreatePassiveSellOffer extends BaseOptions { @@ -266,7 +302,7 @@ export namespace OperationOptions { interface PathPayment extends BaseOptions { sendAsset: Asset; sendMax: string; - destination: string; + destination: AccountId; destAsset: Asset; destAmount: string; path?: Asset[]; @@ -274,10 +310,10 @@ export namespace OperationOptions { interface Payment extends BaseOptions { amount: string; asset: Asset; - destination: string; + destination: AccountId; } interface SetOptions extends BaseOptions { - inflationDest?: string; + inflationDest?: AccountId; clearFlags?: AuthFlag; setFlags?: AuthFlag; masterWeight?: number | string; @@ -309,18 +345,18 @@ export type OperationOptions = export namespace Operation { interface BaseOperation { type: T; - source?: string; + source?: AccountId; } interface AccountMerge extends BaseOperation { - destination: string; + destination: NonExistingAccountId; } function accountMerge( options: OperationOptions.AccountMerge ): xdr.Operation; interface AllowTrust extends BaseOperation { - trustor: string; + trustor: AccountId; assetCode: string; authorize: boolean | undefined; } @@ -337,7 +373,7 @@ export namespace Operation { ): xdr.Operation; interface CreateAccount extends BaseOperation { - destination: string; + destination: AccountId; startingBalance: string; } function createAccount( @@ -394,7 +430,7 @@ export namespace Operation { interface PathPayment extends BaseOperation { sendAsset: Asset; sendMax: string; - destination: string; + destination: AccountId; destAsset: Asset; destAmount: string; path: Asset[]; @@ -406,13 +442,13 @@ export namespace Operation { interface Payment extends BaseOperation { amount: string; asset: Asset; - destination: string; + destination: AccountId; } function payment(options: OperationOptions.Payment): xdr.Operation; interface SetOptions extends BaseOperation { - inflationDest?: string; + inflationDest?: AccountId; clearFlags?: AuthFlag; setFlags?: AuthFlag; masterWeight?: number; @@ -420,7 +456,7 @@ export namespace Operation { medThreshold?: number; highThreshold?: number; homeDomain?: string; - signer: T extends { ed25519PublicKey: any } + signer: T extends { ed25519PublicKey: PublicKey } ? Signer.Ed25519PublicKey : T extends { sha256Hash: any } ? Signer.Sha256Hash @@ -459,13 +495,13 @@ export type Operation = | Operation.BumpSequence; export namespace StrKey { - function encodeEd25519PublicKey(data: Buffer): string; - function decodeEd25519PublicKey(data: string): Buffer; - function isValidEd25519PublicKey(Key: string): boolean; + function encodeEd25519PublicKey(data: Buffer): PublicKey; + function decodeEd25519PublicKey(publicKey: PublicKey): Buffer; + function isValidEd25519PublicKey(publicKey: string): publicKey is AccountId; - function encodeEd25519SecretSeed(data: Buffer): string; - function decodeEd25519SecretSeed(data: string): Buffer; - function isValidEd25519SecretSeed(seed: string): boolean; + function encodeEd25519SecretSeed(data: Buffer): Secret; + function decodeEd25519SecretSeed(secret: Secret): Buffer; + function isValidEd25519SecretSeed(secret: string): secret is Secret; function encodePreAuthTx(data: Buffer): string; function decodePreAuthTx(data: string): Buffer; @@ -479,7 +515,7 @@ export class Transaction< TOps extends Operation[] = Operation[] > { constructor(envelope: string | xdr.TransactionEnvelope); - addSignature(publicKey: string, signature: string): void; + addSignature(publicKey: PublicKey, signature: Secret): void; getKeypairSignature(keypair: Keypair): string; hash(): Buffer; sign(...keypairs: Keypair[]): void; @@ -490,7 +526,7 @@ export class Transaction< operations: TOps; sequence: string; fee: number; - source: string; + source: AccountId; memo: TMemo; signatures: xdr.DecoratedSignature[]; timeBounds?: { diff --git a/yarn.lock b/yarn.lock index 246116408..d598a2ac2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7603,6 +7603,11 @@ util@^0.10.3: dependencies: inherits "2.0.3" +utility-types@^3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/utility-types/-/utility-types-3.7.0.tgz#51f1c29fa35d4267488345706efcf3f68f2b1933" + integrity sha512-mqRJXN7dEArK/NZNJUubjr9kbFFVZcmF/JHDc9jt5O/aYXUVmopHYujDMhLmLil1Bxo2+khe6KAIVvDH9Yc4VA== + utils-merge@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" From b2f0ca8baa147c20bfbffddd6cb3a03d5878d484 Mon Sep 17 00:00:00 2001 From: Akuukis Date: Thu, 25 Jul 2019 14:13:06 +0300 Subject: [PATCH 2/3] fix(typings): bump required TS version for Brand --- types/index.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/index.d.ts b/types/index.d.ts index 77f6c17a9..4ab029bef 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -1,4 +1,4 @@ -// TypeScript Version: 2.9 +// TypeScript Version: 3.0 /// import { Brand } from "utility-types"; From 0d31c21e3b7f4bb5a649987f192e1305a99a3452 Mon Sep 17 00:00:00 2001 From: Akuukis Date: Thu, 25 Jul 2019 15:28:08 +0300 Subject: [PATCH 3/3] fix(typings): adjust tests --- types/index.d.ts | 1 - types/test.ts | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/types/index.d.ts b/types/index.d.ts index 4ab029bef..157ccae93 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -3,7 +3,6 @@ import { Brand } from "utility-types"; - export {}; /** diff --git a/types/test.ts b/types/test.ts index 6f18055a4..976bf6025 100644 --- a/types/test.ts +++ b/types/test.ts @@ -1,11 +1,10 @@ import * as StellarSdk from 'stellar-base'; const sourceKey = StellarSdk.Keypair.random(); // $ExpectType Keypair -const destKey = StellarSdk.Keypair.random(); const account = new StellarSdk.Account(sourceKey.publicKey(), '1'); const transaction = new StellarSdk.TransactionBuilder(account) .addOperation( - StellarSdk.Operation.accountMerge({ destination: destKey.publicKey() }) + StellarSdk.Operation.accountMerge({ destination: account.accountId() }) ) .addMemo(new StellarSdk.Memo(StellarSdk.MemoText, 'memo')) .setTimeout(5)