@stellar/typescript-wallet-sdk 5.1.0 → 6.0.0-beta.1793996806758

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.
package/test/sep7.test.ts CHANGED
@@ -1,12 +1,17 @@
1
1
  import {
2
2
  Account,
3
+ Address,
3
4
  Asset,
4
5
  BASE_FEE,
5
6
  Keypair,
6
7
  Networks,
7
8
  Operation,
8
9
  StellarToml,
10
+ Transaction,
9
11
  TransactionBuilder,
12
+ nativeToScVal,
13
+ rpc,
14
+ xdr,
10
15
  } from "@stellar/stellar-sdk";
11
16
  import {
12
17
  NativeAssetId,
@@ -25,9 +30,19 @@ import {
25
30
  URI_REPLACE_MAX_LENGTH,
26
31
  } from "../src/walletSdk/Types";
27
32
  import {
33
+ Sep7ContractMemoError,
28
34
  Sep7InvalidUriError,
29
35
  Sep7LongMsgError,
30
36
  } from "../src/walletSdk/Exceptions";
37
+ import {
38
+ MUXED_CONTRACT_BAD_CHECKSUM,
39
+ MUXED_CONTRACT_MAX_ID,
40
+ SEP23_CONTRACT,
41
+ SEP23_MUXED_CONTRACT,
42
+ TESTNET_NATIVE_SAC,
43
+ TRANSFER_TO_MUXED_CONTRACT_XDR,
44
+ transferRecipient,
45
+ } from "./fixtures/muxedContract";
31
46
 
32
47
  const testKp1 = SigningKeypair.fromSecret(
33
48
  "SBKQDF56C5VY2YQTNQFGY7HM6R3V6QKDUEDXZQUCPQOP2EBZWG2QJ2JL",
@@ -700,7 +715,14 @@ describe("sep7Parser", () => {
700
715
  // With Soroban Contract destination
701
716
  expect(
702
717
  isValidSep7Uri(
703
- "web+stellar:pay?destination=CAPECFLUT6KHYOOWUQNP7KC6PTMICKANBURFWRMPZTXUEEKHN67B7UI2&amount=120.1234567&memo=skdjfasf&memo_type=MEMO_TEXT&msg=pay%20me%20with%20lumens",
718
+ "web+stellar:pay?destination=CAPECFLUT6KHYOOWUQNP7KC6PTMICKANBURFWRMPZTXUEEKHN67B7UI2&amount=120.1234567&msg=pay%20me%20with%20lumens",
719
+ ).result,
720
+ ).toBe(true);
721
+
722
+ // With Muxed Contract destination
723
+ expect(
724
+ isValidSep7Uri(
725
+ `web+stellar:pay?destination=${SEP23_MUXED_CONTRACT}&amount=120.1234567&msg=pay%20me%20with%20lumens`,
704
726
  ).result,
705
727
  ).toBe(true);
706
728
  });
@@ -857,7 +879,14 @@ describe("sep7Parser", () => {
857
879
  // With Soroban Contract destination
858
880
  expect(
859
881
  parseSep7Uri(
860
- "web+stellar:pay?destination=CAPECFLUT6KHYOOWUQNP7KC6PTMICKANBURFWRMPZTXUEEKHN67B7UI2&amount=120.123&asset_code=USD&asset_issuer=GCRCUE2C5TBNIPYHMEP7NK5RWTT2WBSZ75CMARH7GDOHDDCQH3XANFOB&memo=hasysda987fs&memo_type=MEMO_TEXT&callback=url%3Ahttps%3A%2F%2FsomeSigningService.com%2Fhasysda987fs%3Fasset%3DUSD",
882
+ "web+stellar:pay?destination=CAPECFLUT6KHYOOWUQNP7KC6PTMICKANBURFWRMPZTXUEEKHN67B7UI2&amount=120.123&asset_code=USD&asset_issuer=GCRCUE2C5TBNIPYHMEP7NK5RWTT2WBSZ75CMARH7GDOHDDCQH3XANFOB&callback=url%3Ahttps%3A%2F%2FsomeSigningService.com%2Fhasysda987fs%3Fasset%3DUSD",
883
+ ),
884
+ ).toBeInstanceOf(Sep7Pay);
885
+
886
+ // With Muxed Contract destination
887
+ expect(
888
+ parseSep7Uri(
889
+ `web+stellar:pay?destination=${SEP23_MUXED_CONTRACT}&amount=120.123&asset_code=USD&asset_issuer=GCRCUE2C5TBNIPYHMEP7NK5RWTT2WBSZ75CMARH7GDOHDDCQH3XANFOB&callback=url%3Ahttps%3A%2F%2FsomeSigningService.com%2Fhasysda987fs%3Fasset%3DUSD`,
861
890
  ),
862
891
  ).toBeInstanceOf(Sep7Pay);
863
892
  });
@@ -1067,3 +1096,191 @@ describe("SEP-7 byte encoding regressions", () => {
1067
1096
  expect(uri.getTransaction().toXdr()).toEqual(tx.toXdr());
1068
1097
  });
1069
1098
  });
1099
+
1100
+ describe("SEP-7 with muxed contract (W) addresses", () => {
1101
+ it.each([
1102
+ ["mux ID 0", SEP23_MUXED_CONTRACT],
1103
+ ["the largest mux ID", MUXED_CONTRACT_MAX_ID],
1104
+ ])(
1105
+ "parses a 'pay' uri to a W address with %s and keeps the address as given",
1106
+ (_, destination) => {
1107
+ const uri = parseSep7Uri(
1108
+ `web+stellar:pay?destination=${destination}&amount=10&asset_code=USDC&asset_issuer=GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5`,
1109
+ );
1110
+
1111
+ expect(uri).toBeInstanceOf(Sep7Pay);
1112
+ expect((uri as Sep7Pay).destination).toBe(destination);
1113
+ },
1114
+ );
1115
+
1116
+ it("rejects a 'pay' uri to a W address whose checksum doesn't match", () => {
1117
+ expect(
1118
+ isValidSep7Uri(
1119
+ `web+stellar:pay?destination=${MUXED_CONTRACT_BAD_CHECKSUM}&amount=10`,
1120
+ ),
1121
+ ).toEqual({
1122
+ result: false,
1123
+ reason:
1124
+ "the provided 'destination' parameter is not a valid Stellar address",
1125
+ });
1126
+ });
1127
+
1128
+ it("parses a 'tx' uri whose transaction pays a W address", () => {
1129
+ const uri = `web+stellar:tx?xdr=${encodeURIComponent(
1130
+ TRANSFER_TO_MUXED_CONTRACT_XDR,
1131
+ )}&network_passphrase=${encodeURIComponent(Networks.TESTNET)}`;
1132
+
1133
+ expect(isValidSep7Uri(uri)).toEqual({ result: true });
1134
+
1135
+ const tx = (parseSep7Uri(uri) as Sep7Tx).getTransaction();
1136
+ expect(transferRecipient(tx)).toBe(MUXED_CONTRACT_MAX_ID);
1137
+ expect(tx.toXdr()).toBe(TRANSFER_TO_MUXED_CONTRACT_XDR);
1138
+ });
1139
+ });
1140
+
1141
+ // Runs on testnet, which needs Protocol 30 for a W address to go on chain. A
1142
+ // dapp builds the transfer, has RPC add its Soroban data and passes it to a
1143
+ // wallet as a 'tx' uri, which the wallet signs and submits.
1144
+ describe("SEP-7 'tx' uri for a transfer to a W address, on testnet", () => {
1145
+ it("is signed and submitted by a wallet, and the network keeps the W", async () => {
1146
+ const stellar = Wallet.TestNet().stellar();
1147
+ const sourceKp = stellar.account().createKeypair();
1148
+ await stellar.fundTestnetAccount(sourceKp.publicKey);
1149
+
1150
+ const txBuilder = await stellar.transaction({ sourceAddress: sourceKp });
1151
+ const transfer = txBuilder
1152
+ .addOperation(
1153
+ Operation.invokeContractFunction({
1154
+ contract: TESTNET_NATIVE_SAC,
1155
+ function: "transfer",
1156
+ args: [
1157
+ new Address(sourceKp.publicKey).toScVal(),
1158
+ new Address(MUXED_CONTRACT_MAX_ID).toScVal(),
1159
+ nativeToScVal(12345, { type: "i128" }),
1160
+ ],
1161
+ }),
1162
+ )
1163
+ .build();
1164
+ const prepared = await new rpc.Server(
1165
+ "https://soroban-testnet.stellar.org",
1166
+ ).prepareTransaction(transfer);
1167
+ const uri = Sep7Tx.forTransaction(prepared).toString();
1168
+
1169
+ expect(isValidSep7Uri(uri)).toEqual({ result: true });
1170
+ const tx = (parseSep7Uri(uri) as Sep7Tx).getTransaction();
1171
+ expect(transferRecipient(tx)).toBe(MUXED_CONTRACT_MAX_ID);
1172
+
1173
+ sourceKp.sign(tx);
1174
+ expect(await stellar.submitTransaction(tx)).toBe(true);
1175
+
1176
+ const record = await stellar.server
1177
+ .transactions()
1178
+ .transaction(xdr.encodeBytes(tx.hash(), "hex"))
1179
+ .call();
1180
+ const onChain = stellar.decodeTransaction(
1181
+ record.envelope_xdr,
1182
+ ) as Transaction;
1183
+ expect(transferRecipient(onChain)).toBe(MUXED_CONTRACT_MAX_ID);
1184
+ }, 60000);
1185
+ });
1186
+
1187
+ // A C or W address can only be paid with a Stellar Asset Contract transfer, and
1188
+ // that's a Soroban transaction, which can't carry a memo.
1189
+ describe("SEP-7 'pay' to a contract (C or W) address with a memo", () => {
1190
+ it.each([
1191
+ ["C", "a MEMO_TEXT", SEP23_CONTRACT, "&memo=skdjfasf&memo_type=MEMO_TEXT"],
1192
+ ["C", "a MEMO_ID", SEP23_CONTRACT, "&memo=1234&memo_type=MEMO_ID"],
1193
+ ["C", "an untyped", SEP23_CONTRACT, "&memo=skdjfasf"],
1194
+ [
1195
+ "W",
1196
+ "a MEMO_TEXT",
1197
+ SEP23_MUXED_CONTRACT,
1198
+ "&memo=skdjfasf&memo_type=MEMO_TEXT",
1199
+ ],
1200
+ ["W", "a MEMO_ID", SEP23_MUXED_CONTRACT, "&memo=1234&memo_type=MEMO_ID"],
1201
+ ["W", "an untyped", SEP23_MUXED_CONTRACT, "&memo=skdjfasf"],
1202
+ ])(
1203
+ "rejects a 'pay' uri to a %s address that has %s memo",
1204
+ (_, __, destination, memoParams) => {
1205
+ const uri = `web+stellar:pay?destination=${destination}&amount=10${memoParams}`;
1206
+
1207
+ expect(isValidSep7Uri(uri)).toEqual({
1208
+ result: false,
1209
+ reason:
1210
+ "the 'memo' parameter is not supported for a contract ('C') or muxed contract ('W') 'destination'",
1211
+ });
1212
+ expect(() => parseSep7Uri(uri)).toThrow(Sep7InvalidUriError);
1213
+ },
1214
+ );
1215
+ });
1216
+
1217
+ // Sep7Pay shouldn't build a uri that parseSep7Uri rejects.
1218
+ describe("Sep7Pay with a memo and a contract (C or W) destination", () => {
1219
+ const ACCOUNT = "GCALNQQBXAPZ2WIRSDDBMSTAKCUH5SG6U76YBFLQLIXJTF7FE5AX7AOO";
1220
+ const MUXED_ACCOUNT =
1221
+ "MA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJUAAAAAAAAAABUTGI4";
1222
+
1223
+ describe.each([
1224
+ ["C", SEP23_CONTRACT],
1225
+ ["W", SEP23_MUXED_CONTRACT],
1226
+ ])("to a %s address", (_, destination) => {
1227
+ it("the memo setter throws and leaves the uri unchanged", () => {
1228
+ const uri = Sep7Pay.forDestination(destination);
1229
+
1230
+ expect(() => {
1231
+ uri.memo = "skdjfasf";
1232
+ }).toThrow(Sep7ContractMemoError);
1233
+ expect(uri.toString()).toBe(`web+stellar:pay?destination=${destination}`);
1234
+ });
1235
+
1236
+ it("the destination setter throws on a uri that has a memo and leaves it unchanged", () => {
1237
+ const uri = Sep7Pay.forDestination(ACCOUNT);
1238
+ uri.memo = "skdjfasf";
1239
+
1240
+ expect(() => {
1241
+ uri.destination = destination;
1242
+ }).toThrow(Sep7ContractMemoError);
1243
+ expect(uri.toString()).toBe(
1244
+ `web+stellar:pay?destination=${ACCOUNT}&memo=skdjfasf`,
1245
+ );
1246
+ });
1247
+
1248
+ it("the constructor throws on a uri that has a memo", () => {
1249
+ expect(
1250
+ () =>
1251
+ new Sep7Pay(
1252
+ `web+stellar:pay?destination=${destination}&memo=skdjfasf`,
1253
+ ),
1254
+ ).toThrow(Sep7ContractMemoError);
1255
+ });
1256
+
1257
+ it("builds a uri that parses once the memo is cleared", () => {
1258
+ const uri = Sep7Pay.forDestination(ACCOUNT);
1259
+ uri.memo = "skdjfasf";
1260
+ uri.memo = undefined;
1261
+ uri.destination = destination;
1262
+ uri.amount = "10";
1263
+
1264
+ expect(() => {
1265
+ uri.memo = undefined;
1266
+ }).not.toThrow();
1267
+ expect(uri.toString()).toBe(
1268
+ `web+stellar:pay?destination=${destination}&amount=10`,
1269
+ );
1270
+ expect(parseSep7Uri(uri.toString())).toBeInstanceOf(Sep7Pay);
1271
+ });
1272
+ });
1273
+
1274
+ it.each([
1275
+ ["G", ACCOUNT],
1276
+ ["M", MUXED_ACCOUNT],
1277
+ ])("the memo setter accepts a %s destination", (_, destination) => {
1278
+ const uri = Sep7Pay.forDestination(destination);
1279
+ uri.memo = "skdjfasf";
1280
+
1281
+ expect(uri.toString()).toBe(
1282
+ `web+stellar:pay?destination=${destination}&memo=skdjfasf`,
1283
+ );
1284
+ expect(parseSep7Uri(uri.toString())).toBeInstanceOf(Sep7Pay);
1285
+ });
1286
+ });
@@ -277,6 +277,45 @@ describe("signChallengeTransaction validation", () => {
277
277
  ).rejects.toThrow(ChallengeValidationFailedError);
278
278
  });
279
279
 
280
+ // WebAuth.readChallengeTx checks these since stellar-sdk 17.3. SEP-10
281
+ // requires the client_domain operation's source to be the client domain's
282
+ // signing key.
283
+ it.each([
284
+ ["has no source account", "none"],
285
+ ["uses the server account as its source", "server"],
286
+ ])(
287
+ "should reject a challenge whose client_domain operation %s",
288
+ async (_, clientDomainSource) => {
289
+ const challenge = TransactionBuilder.cloneFrom(
290
+ TransactionBuilder.fromXDR(
291
+ buildChallenge(anchorAKp, anchorA, accountKp.publicKey),
292
+ networkPassphrase,
293
+ ) as Transaction,
294
+ )
295
+ .addOperation(
296
+ Operation.manageData({
297
+ name: "client_domain",
298
+ value: "wallet.example.com",
299
+ source:
300
+ clientDomainSource === "server"
301
+ ? anchorAKp.publicKey()
302
+ : undefined,
303
+ }),
304
+ )
305
+ .build();
306
+ challenge.sign(anchorAKp);
307
+
308
+ const result = Server.signChallengeTransaction({
309
+ accountKp,
310
+ challengeTx: challenge.toXDR(),
311
+ networkPassphrase,
312
+ anchorDomain: anchorA,
313
+ });
314
+ await expect(result).rejects.toThrow(ChallengeValidationFailedError);
315
+ await expect(result).rejects.toThrow(/client_domain/);
316
+ },
317
+ );
318
+
280
319
  it("should accept an explicit homeDomain that differs from anchorDomain", async () => {
281
320
  const homeDomain = "wallet-home.example.com";
282
321
  const challengeTx = buildChallenge(
@@ -21,6 +21,11 @@ import {
21
21
  Assets,
22
22
  } from "../src/walletSdk/Asset";
23
23
  import { TransactionStatus, WithdrawTransaction } from "../src/walletSdk/Types";
24
+ import {
25
+ MUXED_CONTRACT_MAX_ID,
26
+ TRANSFER_TO_MUXED_CONTRACT_XDR,
27
+ transferRecipient,
28
+ } from "./fixtures/muxedContract";
24
29
  import {
25
30
  TransactionSubmitWithFeeIncreaseFailedError,
26
31
  WithdrawalTxMemoError,
@@ -496,6 +501,8 @@ let txnSourceKp;
496
501
  let sponsorKp;
497
502
  let newKp;
498
503
  describe("SponsoringBuilder", () => {
504
+ // One friendbot call can take 25 s or more on testnet, so this funds both
505
+ // accounts in parallel and allows 90 s.
499
506
  beforeAll(async () => {
500
507
  wal = Wallet.TestNet();
501
508
  stellar = wal.stellar();
@@ -503,13 +510,11 @@ describe("SponsoringBuilder", () => {
503
510
  txnSourceKp = new SigningKeypair(Keypair.random());
504
511
  sponsorKp = new SigningKeypair(Keypair.random());
505
512
  newKp = new SigningKeypair(Keypair.random());
506
- await axios.get(
507
- "https://friendbot.stellar.org/?addr=" + sponsorKp.publicKey,
508
- );
509
- await axios.get(
510
- "https://friendbot.stellar.org/?addr=" + txnSourceKp.publicKey,
511
- );
512
- }, 30000);
513
+ await Promise.all([
514
+ axios.get("https://friendbot.stellar.org/?addr=" + sponsorKp.publicKey),
515
+ axios.get("https://friendbot.stellar.org/?addr=" + txnSourceKp.publicKey),
516
+ ]);
517
+ }, 90000);
513
518
 
514
519
  it("should sponsor creating an account", async () => {
515
520
  const wal = Wallet.TestNet();
@@ -644,6 +649,8 @@ describe("Asset", () => {
644
649
  });
645
650
  });
646
651
 
652
+ // These tests wait on testnet, where one friendbot call can take 25 s or more,
653
+ // so they fund their accounts in parallel and allow 90 s.
647
654
  describe("Account Modifying", () => {
648
655
  it("should modify account ", async () => {
649
656
  const wallet = Wallet.TestNet();
@@ -651,10 +658,10 @@ describe("Account Modifying", () => {
651
658
 
652
659
  const sourceKp = new SigningKeypair(Keypair.random());
653
660
  const otherKp = new SigningKeypair(Keypair.random());
654
- await axios.get(
655
- "https://friendbot.stellar.org/?addr=" + sourceKp.publicKey,
656
- );
657
- await axios.get("https://friendbot.stellar.org/?addr=" + otherKp.publicKey);
661
+ await Promise.all([
662
+ axios.get("https://friendbot.stellar.org/?addr=" + sourceKp.publicKey),
663
+ axios.get("https://friendbot.stellar.org/?addr=" + otherKp.publicKey),
664
+ ]);
658
665
 
659
666
  // Add account signer
660
667
  let txBuilder = await stellar.transaction({
@@ -718,7 +725,7 @@ describe("Account Modifying", () => {
718
725
 
719
726
  resp = await stellar.server.loadAccount(sourceKp.publicKey);
720
727
  expect(resp.signers[0].weight).toBe(0);
721
- }, 45000);
728
+ }, 90000);
722
729
 
723
730
  it("should merge account", async () => {
724
731
  const wallet = Wallet.TestNet();
@@ -727,8 +734,10 @@ describe("Account Modifying", () => {
727
734
 
728
735
  const accountKp = account.createKeypair();
729
736
  const sourceKp = account.createKeypair();
730
- await stellar.fundTestnetAccount(accountKp.publicKey);
731
- await stellar.fundTestnetAccount(sourceKp.publicKey);
737
+ await Promise.all([
738
+ stellar.fundTestnetAccount(accountKp.publicKey),
739
+ stellar.fundTestnetAccount(sourceKp.publicKey),
740
+ ]);
732
741
 
733
742
  const txBuilder = await stellar.transaction({
734
743
  sourceAddress: accountKp,
@@ -753,7 +762,7 @@ describe("Account Modifying", () => {
753
762
  expect(found).toBeFalsy();
754
763
  const accResp = await stellar.server.loadAccount(accountKp.publicKey);
755
764
  expect(parseInt(accResp.balances[0].balance)).toBeGreaterThan(19998);
756
- }, 30000);
765
+ }, 90000);
757
766
  });
758
767
 
759
768
  // Hermetic (no network): stellar-sdk v16 tightened Memo validation, so a
@@ -818,3 +827,14 @@ describe("transferWithdrawalTransaction memo validation", () => {
818
827
  ).toThrow(WithdrawalTxMemoError);
819
828
  });
820
829
  });
830
+
831
+ describe("decodeTransaction with a muxed contract (W) address", () => {
832
+ it("decodes a transfer to a W address and re-encodes it unchanged", () => {
833
+ const tx = Wallet.TestNet()
834
+ .stellar()
835
+ .decodeTransaction(TRANSFER_TO_MUXED_CONTRACT_XDR) as Transaction;
836
+
837
+ expect(transferRecipient(tx)).toBe(MUXED_CONTRACT_MAX_ID);
838
+ expect(tx.toXdr()).toBe(TRANSFER_TO_MUXED_CONTRACT_XDR);
839
+ });
840
+ });
@@ -19,6 +19,7 @@ import {
19
19
  } from "../src";
20
20
  import { IssuedAssetId, NativeAssetId } from "../src/walletSdk/Asset";
21
21
  import { PathPayBoundRequiredError } from "../src/walletSdk/Exceptions";
22
+ import { MUXED_CONTRACT_MAX_ID } from "./fixtures/muxedContract";
22
23
 
23
24
  describe("Muxed Transactions", () => {
24
25
  let wallet: Wallet;
@@ -424,3 +425,45 @@ describe("Path Payment bounds", () => {
424
425
  expect(op.destMin).toBe("0.9000000");
425
426
  });
426
427
  });
428
+
429
+ // A muxed contract (W) address can only receive a Stellar Asset Contract
430
+ // transfer, so no classic operation may take one as its destination.
431
+ describe("classic operations to a muxed contract (W) address", () => {
432
+ const newBuilder = () =>
433
+ new TransactionBuilder(
434
+ new Config({
435
+ stellarConfiguration: StellarConfiguration.TestNet(),
436
+ applicationConfiguration: new ApplicationConfiguration(),
437
+ }),
438
+ new Account(Keypair.random().publicKey(), "0"),
439
+ );
440
+
441
+ it.each([
442
+ [
443
+ "transfer",
444
+ (builder: TransactionBuilder) =>
445
+ builder.transfer(MUXED_CONTRACT_MAX_ID, new NativeAssetId(), "1"),
446
+ ],
447
+ [
448
+ "pathPay",
449
+ (builder: TransactionBuilder) =>
450
+ builder.pathPay({
451
+ destinationAddress: MUXED_CONTRACT_MAX_ID,
452
+ sendAsset: new NativeAssetId(),
453
+ destAsset: new IssuedAssetId(
454
+ "USDC",
455
+ "GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5",
456
+ ),
457
+ sendAmount: "5",
458
+ destMin: "4.9",
459
+ }),
460
+ ],
461
+ [
462
+ "accountMerge",
463
+ (builder: TransactionBuilder) =>
464
+ builder.accountMerge(MUXED_CONTRACT_MAX_ID),
465
+ ],
466
+ ])("%s refuses a W destination", (_, addOperation) => {
467
+ expect(() => addOperation(newBuilder())).toThrow("destination is invalid");
468
+ });
469
+ });
@@ -2033,6 +2033,7 @@ describe("AuthHeaderSigner", () => {
2033
2033
  beforeAll(() => {
2034
2034
  jest.resetAllMocks();
2035
2035
  });
2036
+ // One friendbot call can take 25 s or more on testnet, so this allows 90 s.
2036
2037
  it("full sep-10 auth using header token should work", async () => {
2037
2038
  const wallet = Wallet.TestNet();
2038
2039
  const accountKp = wallet.stellar().account().createKeypair();
@@ -2054,7 +2055,7 @@ describe("AuthHeaderSigner", () => {
2054
2055
  });
2055
2056
 
2056
2057
  expect(authToken).toBeTruthy();
2057
- }, 30000);
2058
+ }, 90000);
2058
2059
 
2059
2060
  it("should match example implementation generated JWT", async () => {
2060
2061
  const generatedAuthToken =