@stellar/typescript-wallet-sdk 1.10.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,7 +7,7 @@ type Sep10Params = {
7
7
  webAuthEndpoint: string;
8
8
  homeDomain: string;
9
9
  httpClient: AxiosInstance;
10
- serverSigningKey?: string;
10
+ serverSigningKey: string;
11
11
  };
12
12
  /**
13
13
  * @alias Auth alias for Sep10 class.
@@ -24,7 +24,7 @@ export declare class Sep10 {
24
24
  private webAuthEndpoint;
25
25
  private homeDomain;
26
26
  private httpClient;
27
- private serverSigningKey?;
27
+ private serverSigningKey;
28
28
  /**
29
29
  * Creates a new instance of the Sep10 class.
30
30
  *
@@ -103,6 +103,9 @@ export declare class NoAccountAndNoSponsorError extends Error {
103
103
  export declare class Sep38PriceOnlyOneAmountError extends Error {
104
104
  constructor();
105
105
  }
106
+ export declare class MissingSigningKeyError extends Error {
107
+ constructor();
108
+ }
106
109
  export declare class ChallengeValidationFailedError extends Error {
107
110
  constructor(cause: Error);
108
111
  }
@@ -56,7 +56,7 @@ export type RecoveryServer = {
56
56
  endpoint: string;
57
57
  authEndpoint: string;
58
58
  homeDomain: string;
59
- signingKey?: string;
59
+ signingKey: string;
60
60
  walletSigner?: WalletSigner;
61
61
  clientDomain?: string;
62
62
  };
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@stellar/typescript-wallet-sdk",
3
- "version": "1.10.0",
3
+ "version": "2.0.0",
4
4
  "engines": {
5
- "node": ">=18"
5
+ "node": ">=20"
6
6
  },
7
7
  "browser": "./lib/bundle_browser.js",
8
8
  "main": "./lib/bundle.js",
@@ -47,7 +47,7 @@
47
47
  "dependencies": {
48
48
  "@stablelib/base64": "^2.0.0",
49
49
  "@stablelib/utf8": "^2.0.0",
50
- "@stellar/stellar-sdk": "13.0.0-beta.1",
50
+ "@stellar/stellar-sdk": "14.5.0",
51
51
  "axios": "^1.4.0",
52
52
  "base64url": "^3.0.1",
53
53
  "https-browserify": "^1.0.0",
@@ -7,6 +7,7 @@ import { Customer, Sep12 } from "../Customer";
7
7
  import {
8
8
  ServerRequestFailedError,
9
9
  KYCServerNotFoundError,
10
+ MissingSigningKeyError,
10
11
  } from "../Exceptions";
11
12
  import { Sep6, Transfer } from "./Sep6";
12
13
  import { Interactive, Sep24 } from "./Sep24";
@@ -104,6 +105,9 @@ export class Anchor {
104
105
  */
105
106
  async sep10(): Promise<Sep10> {
106
107
  const tomlInfo = await this.sep1();
108
+ if (!tomlInfo.signingKey) {
109
+ throw new MissingSigningKeyError();
110
+ }
107
111
  return new Sep10({
108
112
  cfg: this.cfg,
109
113
  webAuthEndpoint: tomlInfo.webAuthEndpoint,
@@ -1,10 +1,5 @@
1
1
  import { AxiosInstance } from "axios";
2
- import {
3
- TransactionBuilder,
4
- Transaction,
5
- FeeBumpTransaction,
6
- WebAuth,
7
- } from "@stellar/stellar-sdk";
2
+ import { TransactionBuilder, Transaction, WebAuth } from "@stellar/stellar-sdk";
8
3
  import { decode } from "jws";
9
4
 
10
5
  import { Config } from "../";
@@ -38,7 +33,7 @@ type Sep10Params = {
38
33
  webAuthEndpoint: string;
39
34
  homeDomain: string;
40
35
  httpClient: AxiosInstance;
41
- serverSigningKey?: string;
36
+ serverSigningKey: string;
42
37
  };
43
38
 
44
39
  /**
@@ -57,7 +52,7 @@ export class Sep10 {
57
52
  private webAuthEndpoint: string;
58
53
  private homeDomain: string;
59
54
  private httpClient: AxiosInstance;
60
- private serverSigningKey?: string;
55
+ private serverSigningKey: string;
61
56
 
62
57
  /**
63
58
  * Creates a new instance of the Sep10 class.
@@ -176,22 +171,13 @@ export class Sep10 {
176
171
  try {
177
172
  const webAuthDomain = new URL(this.webAuthEndpoint).hostname;
178
173
 
179
- if (this.serverSigningKey) {
180
- WebAuth.readChallengeTx(
181
- challengeResponse.transaction,
182
- this.serverSigningKey,
183
- networkPassphrase,
184
- this.homeDomain,
185
- webAuthDomain,
186
- );
187
- } else {
188
- readChallengeTx(
189
- challengeResponse.transaction,
190
- networkPassphrase,
191
- this.homeDomain,
192
- webAuthDomain,
193
- );
194
- }
174
+ WebAuth.readChallengeTx(
175
+ challengeResponse.transaction,
176
+ this.serverSigningKey,
177
+ networkPassphrase,
178
+ this.homeDomain,
179
+ webAuthDomain,
180
+ );
195
181
  } catch (e) {
196
182
  throw new ChallengeValidationFailedError(
197
183
  e instanceof Error ? e : new Error(String(e)),
@@ -255,136 +241,6 @@ export const validateToken = (token: string) => {
255
241
  }
256
242
  };
257
243
 
258
- /*
259
- * Validates a SEP-10 challenge transaction without requiring the server's
260
- * signing key. This performs all structural validations from the SEP-10 spec
261
- * (sequence number, operation types, timebounds, home domain, web_auth_domain,
262
- * nonce format) but skips the server account and signature checks.
263
- *
264
- * Used as a fallback when the anchor's stellar.toml does not publish a
265
- * SIGNING_KEY, providing strong protection against malformed or malicious
266
- * challenge transactions.
267
- *
268
- * @internal
269
- * @see {@link https://github.com/stellar/js-stellar-sdk/blob/v13.0.0-beta.1/src/webauth/utils.ts#L188 | WebAuth.readChallengeTx}
270
- */
271
- const readChallengeTx = (
272
- challengeTx: string,
273
- networkPassphrase: string,
274
- homeDomain: string,
275
- webAuthDomain: string,
276
- ): { tx: Transaction; clientAccountID: string } => {
277
- let transaction: Transaction;
278
- try {
279
- transaction = new Transaction(challengeTx, networkPassphrase);
280
- } catch {
281
- try {
282
- // eslint-disable-next-line no-new
283
- new FeeBumpTransaction(challengeTx, networkPassphrase);
284
- } catch {
285
- throw new Error(
286
- "Invalid challenge: unable to deserialize challengeTx transaction string",
287
- );
288
- }
289
- throw new Error(
290
- "Invalid challenge: expected a Transaction but received a FeeBumpTransaction",
291
- );
292
- }
293
-
294
- // verify sequence number
295
- const sequence = Number.parseInt(transaction.sequence, 10);
296
- if (sequence !== 0) {
297
- throw new Error("The transaction sequence number should be zero");
298
- }
299
-
300
- // verify operations
301
- if (transaction.operations.length < 1) {
302
- throw new Error("The transaction should contain at least one operation");
303
- }
304
-
305
- const [operation, ...subsequentOperations] = transaction.operations;
306
-
307
- if (!operation.source) {
308
- throw new Error(
309
- "The transaction's operation should contain a source account",
310
- );
311
- }
312
- const clientAccountID: string = operation.source;
313
-
314
- // verify memo
315
- if (transaction.memo.type !== "none") {
316
- if (clientAccountID.startsWith("M")) {
317
- throw new Error(
318
- "The transaction has a memo but the client account ID is a muxed account",
319
- );
320
- }
321
- if (transaction.memo.type !== "id") {
322
- throw new Error("The transaction's memo must be of type `id`");
323
- }
324
- }
325
-
326
- if (operation.type !== "manageData") {
327
- throw new Error("The transaction's operation type should be 'manageData'");
328
- }
329
-
330
- // verify timebounds
331
- if (!transaction.timeBounds) {
332
- throw new Error("The transaction requires timebounds");
333
- }
334
-
335
- if (Number.parseInt(transaction.timeBounds.maxTime, 10) === 0) {
336
- throw new Error("The transaction requires non-infinite timebounds");
337
- }
338
-
339
- const now = Math.floor(Date.now() / 1000);
340
- const gracePeriod = 60 * 5;
341
- const minTime = Number.parseInt(transaction.timeBounds.minTime, 10) || 0;
342
- const maxTime = Number.parseInt(transaction.timeBounds.maxTime, 10) || 0;
343
- if (now < minTime - gracePeriod || now > maxTime + gracePeriod) {
344
- throw new Error("The transaction has expired");
345
- }
346
-
347
- // verify nonce value
348
- if (operation.value === undefined || !operation.value) {
349
- throw new Error("The transaction's operation value should not be null");
350
- }
351
-
352
- if (Buffer.from(operation.value.toString(), "base64").length !== 48) {
353
- throw new Error(
354
- "The transaction's operation value should be a 64 bytes base64 random string",
355
- );
356
- }
357
-
358
- // verify home domain
359
- if (`${homeDomain} auth` !== operation.name) {
360
- throw new Error(
361
- "Invalid homeDomains: the transaction's operation key name " +
362
- "does not match the expected home domain",
363
- );
364
- }
365
-
366
- // verify subsequent operations are all manageData
367
- for (const op of subsequentOperations) {
368
- if (op.type !== "manageData") {
369
- throw new Error(
370
- "The transaction has operations that are not of type 'manageData'",
371
- );
372
- }
373
- if (op.name === "web_auth_domain") {
374
- if (op.value === undefined) {
375
- throw new Error("'web_auth_domain' operation value should not be null");
376
- }
377
- if (op.value.compare(Buffer.from(webAuthDomain)) !== 0) {
378
- throw new Error(
379
- `'web_auth_domain' operation value does not match ${webAuthDomain}`,
380
- );
381
- }
382
- }
383
- }
384
-
385
- return { tx: transaction, clientAccountID };
386
- };
387
-
388
244
  const createAuthSignToken = async (
389
245
  account: AccountKeypair,
390
246
  claims: AuthHeaderClaims,
@@ -280,6 +280,15 @@ export class Sep38PriceOnlyOneAmountError extends Error {
280
280
  }
281
281
  }
282
282
 
283
+ export class MissingSigningKeyError extends Error {
284
+ constructor() {
285
+ super(
286
+ "Anchor's stellar.toml does not contain a SIGNING_KEY, which is required for SEP-10 authentication",
287
+ );
288
+ Object.setPrototypeOf(this, MissingSigningKeyError.prototype);
289
+ }
290
+ }
291
+
283
292
  export class ChallengeValidationFailedError extends Error {
284
293
  constructor(cause: Error) {
285
294
  super(`SEP-10 challenge validation failed: ${cause.message}`);
@@ -76,7 +76,7 @@ export class Recovery extends AccountRecover {
76
76
  webAuthEndpoint: server.authEndpoint,
77
77
  homeDomain: server.homeDomain,
78
78
  httpClient: this.httpClient,
79
- ...(server.signingKey && { serverSigningKey: server.signingKey }),
79
+ serverSigningKey: server.signingKey,
80
80
  });
81
81
  }
82
82
 
@@ -63,7 +63,7 @@ export type RecoveryServer = {
63
63
  endpoint: string;
64
64
  authEndpoint: string;
65
65
  homeDomain: string;
66
- signingKey?: string;
66
+ signingKey: string;
67
67
  walletSigner?: WalletSigner;
68
68
  clientDomain?: string;
69
69
  };
package/test/auth.test.ts CHANGED
@@ -11,7 +11,6 @@ import {
11
11
  TransactionBuilder as SdkTransactionBuilder,
12
12
  Operation,
13
13
  BASE_FEE,
14
- xdr as StellarXdr,
15
14
  } from "@stellar/stellar-sdk";
16
15
  import { randomBytes } from "crypto";
17
16
  import axios from "axios";
@@ -30,6 +29,7 @@ import {
30
29
  ExpiredTokenError,
31
30
  ChallengeValidationFailedError,
32
31
  NetworkPassphraseMismatchError,
32
+ MissingSigningKeyError,
33
33
  } from "../src/walletSdk/Exceptions";
34
34
 
35
35
  const createToken = (payload: Record<string, unknown>): string => {
@@ -261,7 +261,7 @@ describe("Sep10 challenge validation", () => {
261
261
  token,
262
262
  responseNetworkPassphrase = networkPassphrase,
263
263
  }: {
264
- serverSigningKey?: string;
264
+ serverSigningKey: string;
265
265
  challengeXdr: string;
266
266
  token: string;
267
267
  responseNetworkPassphrase?: string;
@@ -282,7 +282,7 @@ describe("Sep10 challenge validation", () => {
282
282
  webAuthEndpoint,
283
283
  homeDomain,
284
284
  httpClient,
285
- ...(serverSigningKey ? { serverSigningKey } : {}),
285
+ serverSigningKey,
286
286
  });
287
287
 
288
288
  return { sep10, postStub };
@@ -618,301 +618,6 @@ describe("Sep10 challenge validation", () => {
618
618
  });
619
619
  });
620
620
 
621
- // ============================================================
622
- // WITHOUT serverSigningKey — uses local readChallengeTx
623
- // ============================================================
624
- describe("without serverSigningKey (local readChallengeTx)", () => {
625
- const authenticateWithoutKey = (
626
- challengeXdr: string,
627
- clientKeypair: Keypair,
628
- ) => {
629
- const accountKp = SigningKeypair.fromSecret(clientKeypair.secret());
630
- const token = createJwt(clientKeypair);
631
- const { sep10, postStub } = setupSep10({
632
- challengeXdr,
633
- token,
634
- });
635
- return { sep10, accountKp, postStub };
636
- };
637
-
638
- it("should accept a valid challenge", async () => {
639
- const { xdr, clientKeypair } = buildChallenge();
640
- const { sep10, accountKp } = authenticateWithoutKey(xdr, clientKeypair);
641
- const authToken = await sep10.authenticate({ accountKp });
642
- expect(authToken.account).toBe(clientKeypair.publicKey());
643
- });
644
-
645
- it("should reject invalid XDR", async () => {
646
- const clientKeypair = Keypair.random();
647
- const { sep10, accountKp, postStub } = authenticateWithoutKey(
648
- "not-valid-xdr",
649
- clientKeypair,
650
- );
651
- await expect(sep10.authenticate({ accountKp })).rejects.toThrow(
652
- ChallengeValidationFailedError,
653
- );
654
- expect(postStub.notCalled).toBe(true);
655
- });
656
-
657
- it("should reject a FeeBumpTransaction", async () => {
658
- const { xdr: innerXdr, serverKeypair, clientKeypair } = buildChallenge();
659
- const innerTx = new Transaction(innerXdr, networkPassphrase);
660
- const feeBump = SdkTransactionBuilder.buildFeeBumpTransaction(
661
- serverKeypair,
662
- BASE_FEE,
663
- innerTx,
664
- networkPassphrase,
665
- );
666
- feeBump.sign(serverKeypair);
667
-
668
- const { sep10, accountKp, postStub } = authenticateWithoutKey(
669
- feeBump.toXDR(),
670
- clientKeypair,
671
- );
672
- await expect(sep10.authenticate({ accountKp })).rejects.toThrow(
673
- ChallengeValidationFailedError,
674
- );
675
- expect(postStub.notCalled).toBe(true);
676
- });
677
-
678
- it("should reject non-zero sequence number", async () => {
679
- const { xdr, clientKeypair } = buildChallenge({ sequence: "99" });
680
- const { sep10, accountKp, postStub } = authenticateWithoutKey(
681
- xdr,
682
- clientKeypair,
683
- );
684
- await expect(sep10.authenticate({ accountKp })).rejects.toThrow(
685
- ChallengeValidationFailedError,
686
- );
687
- expect(postStub.notCalled).toBe(true);
688
- });
689
-
690
- it("should reject a challenge with no operations", async () => {
691
- const serverKeypair = Keypair.random();
692
- const clientKeypair = Keypair.random();
693
- const serverAccount = new Account(serverKeypair.publicKey(), "-1");
694
- const tx = new SdkTransactionBuilder(serverAccount, {
695
- fee: BASE_FEE,
696
- networkPassphrase,
697
- })
698
- .setTimeout(300)
699
- .build();
700
- tx.sign(serverKeypair);
701
-
702
- const { sep10, accountKp, postStub } = authenticateWithoutKey(
703
- tx.toXDR(),
704
- clientKeypair,
705
- );
706
- await expect(sep10.authenticate({ accountKp })).rejects.toThrow(
707
- ChallengeValidationFailedError,
708
- );
709
- expect(postStub.notCalled).toBe(true);
710
- });
711
-
712
- it("should reject first operation without source account", async () => {
713
- const { xdr, clientKeypair } = buildChallenge({
714
- omitFirstOpSource: true,
715
- });
716
- const { sep10, accountKp, postStub } = authenticateWithoutKey(
717
- xdr,
718
- clientKeypair,
719
- );
720
- await expect(sep10.authenticate({ accountKp })).rejects.toThrow(
721
- ChallengeValidationFailedError,
722
- );
723
- expect(postStub.notCalled).toBe(true);
724
- });
725
-
726
- it("should reject memo with muxed client account", async () => {
727
- const clientKeypair = Keypair.random();
728
- const baseAccount = new Account(clientKeypair.publicKey(), "0");
729
- const muxed = new MuxedAccount(baseAccount, "123");
730
-
731
- const { xdr } = buildChallenge({
732
- clientKeypair,
733
- clientSource: muxed.accountId(),
734
- memo: Memo.id("456"),
735
- });
736
- const { sep10, accountKp, postStub } = authenticateWithoutKey(
737
- xdr,
738
- clientKeypair,
739
- );
740
- await expect(sep10.authenticate({ accountKp })).rejects.toThrow(
741
- ChallengeValidationFailedError,
742
- );
743
- expect(postStub.notCalled).toBe(true);
744
- });
745
-
746
- it("should reject non-id memo type", async () => {
747
- const { xdr, clientKeypair } = buildChallenge({
748
- memo: Memo.text("test"),
749
- });
750
- const { sep10, accountKp, postStub } = authenticateWithoutKey(
751
- xdr,
752
- clientKeypair,
753
- );
754
- await expect(sep10.authenticate({ accountKp })).rejects.toThrow(
755
- ChallengeValidationFailedError,
756
- );
757
- expect(postStub.notCalled).toBe(true);
758
- });
759
-
760
- it("should reject first operation that is not manageData", async () => {
761
- const { xdr, clientKeypair } = buildChallenge({
762
- firstOpType: "payment",
763
- });
764
- const { sep10, accountKp, postStub } = authenticateWithoutKey(
765
- xdr,
766
- clientKeypair,
767
- );
768
- await expect(sep10.authenticate({ accountKp })).rejects.toThrow(
769
- ChallengeValidationFailedError,
770
- );
771
- expect(postStub.notCalled).toBe(true);
772
- });
773
-
774
- it("should reject infinite timebounds (maxTime=0)", async () => {
775
- const { xdr, clientKeypair } = buildChallenge({
776
- useExplicitTimebounds: true,
777
- minTime: 0,
778
- maxTime: 0,
779
- });
780
- const { sep10, accountKp, postStub } = authenticateWithoutKey(
781
- xdr,
782
- clientKeypair,
783
- );
784
- await expect(sep10.authenticate({ accountKp })).rejects.toThrow(
785
- ChallengeValidationFailedError,
786
- );
787
- expect(postStub.notCalled).toBe(true);
788
- });
789
-
790
- it("should reject expired timebounds", async () => {
791
- const now = Math.floor(Date.now() / 1000);
792
- const { xdr, clientKeypair } = buildChallenge({
793
- useExplicitTimebounds: true,
794
- minTime: now - 7200,
795
- maxTime: now - 3600,
796
- });
797
- const { sep10, accountKp, postStub } = authenticateWithoutKey(
798
- xdr,
799
- clientKeypair,
800
- );
801
- await expect(sep10.authenticate({ accountKp })).rejects.toThrow(
802
- ChallengeValidationFailedError,
803
- );
804
- expect(postStub.notCalled).toBe(true);
805
- });
806
-
807
- it("should reject missing nonce value", async () => {
808
- const { xdr, clientKeypair } = buildChallenge({ omitNonce: true });
809
- const { sep10, accountKp, postStub } = authenticateWithoutKey(
810
- xdr,
811
- clientKeypair,
812
- );
813
- await expect(sep10.authenticate({ accountKp })).rejects.toThrow(
814
- ChallengeValidationFailedError,
815
- );
816
- expect(postStub.notCalled).toBe(true);
817
- });
818
-
819
- it("should reject wrong nonce length", async () => {
820
- const { xdr, clientKeypair } = buildChallenge({
821
- nonce: randomBytes(16).toString("base64"),
822
- });
823
- const { sep10, accountKp, postStub } = authenticateWithoutKey(
824
- xdr,
825
- clientKeypair,
826
- );
827
- await expect(sep10.authenticate({ accountKp })).rejects.toThrow(
828
- ChallengeValidationFailedError,
829
- );
830
- expect(postStub.notCalled).toBe(true);
831
- });
832
-
833
- it("should reject wrong home domain", async () => {
834
- const { xdr, clientKeypair } = buildChallenge({
835
- challengeHomeDomain: "evil.example.com",
836
- });
837
- const { sep10, accountKp, postStub } = authenticateWithoutKey(
838
- xdr,
839
- clientKeypair,
840
- );
841
- await expect(sep10.authenticate({ accountKp })).rejects.toThrow(
842
- ChallengeValidationFailedError,
843
- );
844
- expect(postStub.notCalled).toBe(true);
845
- });
846
-
847
- it("should reject subsequent non-manageData operation", async () => {
848
- const serverKeypair = Keypair.random();
849
- const { xdr, clientKeypair } = buildChallenge({
850
- serverKeypair,
851
- additionalOps: [
852
- Operation.payment({
853
- destination: serverKeypair.publicKey(),
854
- asset: Asset.native(),
855
- amount: "1",
856
- }),
857
- ],
858
- });
859
- const { sep10, accountKp, postStub } = authenticateWithoutKey(
860
- xdr,
861
- clientKeypair,
862
- );
863
- await expect(sep10.authenticate({ accountKp })).rejects.toThrow(
864
- ChallengeValidationFailedError,
865
- );
866
- expect(postStub.notCalled).toBe(true);
867
- });
868
-
869
- it("should reject null web_auth_domain value", async () => {
870
- const { xdr, clientKeypair } = buildChallenge({
871
- webAuthDomainValue: null,
872
- });
873
- const { sep10, accountKp, postStub } = authenticateWithoutKey(
874
- xdr,
875
- clientKeypair,
876
- );
877
- await expect(sep10.authenticate({ accountKp })).rejects.toThrow(
878
- ChallengeValidationFailedError,
879
- );
880
- expect(postStub.notCalled).toBe(true);
881
- });
882
-
883
- it("should reject mismatched web_auth_domain", async () => {
884
- const { xdr, clientKeypair } = buildChallenge({
885
- webAuthDomainValue: "evil.example.com",
886
- });
887
- const { sep10, accountKp, postStub } = authenticateWithoutKey(
888
- xdr,
889
- clientKeypair,
890
- );
891
- await expect(sep10.authenticate({ accountKp })).rejects.toThrow(
892
- ChallengeValidationFailedError,
893
- );
894
- expect(postStub.notCalled).toBe(true);
895
- });
896
-
897
- it("should reject a challenge with missing timebounds", async () => {
898
- const { xdr: txXdr, clientKeypair } = buildChallenge();
899
-
900
- // Strip timebounds by setting preconditions to PRECOND_NONE in the XDR
901
- const envelope = StellarXdr.TransactionEnvelope.fromXDR(txXdr, "base64");
902
- envelope.v1().tx().cond(StellarXdr.Preconditions.precondNone());
903
- const noTimeboundsXdr = envelope.toXDR().toString("base64");
904
-
905
- const { sep10, accountKp, postStub } = authenticateWithoutKey(
906
- noTimeboundsXdr,
907
- clientKeypair,
908
- );
909
- await expect(sep10.authenticate({ accountKp })).rejects.toThrow(
910
- ChallengeValidationFailedError,
911
- );
912
- expect(postStub.notCalled).toBe(true);
913
- });
914
- });
915
-
916
621
  describe("network passphrase mismatch", () => {
917
622
  it("should reject when server returns a different network passphrase", async () => {
918
623
  const { xdr, serverKeypair, clientKeypair } = buildChallenge();
@@ -983,7 +688,7 @@ describe("Anchor.sep10() signing key handling", () => {
983
688
  sinon.restore();
984
689
  });
985
690
 
986
- it("should succeed when TOML has no SIGNING_KEY", async () => {
691
+ it("should throw MissingSigningKeyError when TOML has no SIGNING_KEY", async () => {
987
692
  sinon.stub(StellarToml.Resolver, "resolve").resolves({
988
693
  WEB_AUTH_ENDPOINT: "https://testanchor.stellar.org/auth",
989
694
  DOCUMENTATION: {},
@@ -1001,8 +706,7 @@ describe("Anchor.sep10() signing key handling", () => {
1001
706
  language: "en",
1002
707
  });
1003
708
 
1004
- const sep10 = await anchor.sep10();
1005
- expect(sep10).toBeDefined();
709
+ await expect(anchor.sep10()).rejects.toThrow(MissingSigningKeyError);
1006
710
  });
1007
711
 
1008
712
  it("should succeed when TOML has SIGNING_KEY", async () => {
@@ -6,14 +6,14 @@ let wallet;
6
6
  let stellar;
7
7
  let anchor;
8
8
  let accountKp;
9
- const anchorUrl = "https://anchor-sep-server-dev.stellar.org/";
9
+ const anchorUrl = "anchor-sep-server-dev.stellar.org";
10
10
 
11
11
  describe("Anchor Platform Integration Tests", () => {
12
12
  beforeAll(async () => {
13
13
  // Setup
14
14
  wallet = Wallet.TestNet();
15
15
  stellar = wallet.stellar();
16
- anchor = wallet.anchor({ homeDomain: anchorUrl, allowHttp: true });
16
+ anchor = wallet.anchor({ homeDomain: anchorUrl });
17
17
  accountKp = stellar.account().createKeypair();
18
18
  await stellar.fundTestnetAccount(accountKp.publicKey);
19
19
  }, 30000);
@@ -22,6 +22,7 @@ describe("Recovery Integration Tests", () => {
22
22
  endpoint: "http://localhost:8000",
23
23
  authEndpoint: "http://localhost:8001",
24
24
  homeDomain: "test-domain",
25
+ signingKey: "GA43H67KTOSLFDM5LPUSJGIJSPWV6WVQN6FUYQWZKWJE5EMHXWE5EGK5",
25
26
  };
26
27
 
27
28
  const server2Key: RecoveryServerKey = "server2";
@@ -29,6 +30,7 @@ describe("Recovery Integration Tests", () => {
29
30
  endpoint: "http://localhost:8002",
30
31
  authEndpoint: "http://localhost:8003",
31
32
  homeDomain: "test-domain",
33
+ signingKey: "GAZ2ITFWBXNT4SXSDEPM43IN72FQXOUCVXEXSHYX3VT2WZUI4E6UBSI2",
32
34
  };
33
35
 
34
36
  const servers: RecoveryServerMap = {