@stellar/typescript-wallet-sdk 3.0.0 → 3.0.1

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/CHANGELOG.MD CHANGED
@@ -1,3 +1,10 @@
1
+ # Release notes - Typescript Wallet SDK - 3.0.1
2
+
3
+ ### Fixed
4
+ * SEP-10: verify the auth server returns the same challenge body after `client_domain` re-signing, instead of trusting a server-supplied transaction (#237)
5
+ * `submitWithFeeIncrease`: forward `maxFee` across recursive retries so the cap is enforced on every retry, not just the first (#238)
6
+ * `submitTransaction`: replace the unbounded recursive 504 retry with a bounded equal-jitter exponential backoff loop, avoiding stack overflow during sustained Horizon outages (#238)
7
+
1
8
  # Release notes - Typescript Wallet SDK - 3.0.0
2
9
 
3
10
  ### BREAKING CHANGES
package/lib/bundle.js CHANGED
@@ -1857,9 +1857,9 @@ var Sep10 = /** @class */ (function () {
1857
1857
  Sep10.prototype.sign = function (_a) {
1858
1858
  var accountKp = _a.accountKp, challengeResponse = _a.challengeResponse, walletSigner = _a.walletSigner;
1859
1859
  return __awaiter(this, void 0, void 0, function () {
1860
- var networkPassphrase, webAuthDomain, transaction, _i, _b, op;
1861
- return __generator(this, function (_c) {
1862
- switch (_c.label) {
1860
+ var networkPassphrase, webAuthDomain, transaction, hasClientDomain, originalHash, returned;
1861
+ return __generator(this, function (_b) {
1862
+ switch (_b.label) {
1863
1863
  case 0:
1864
1864
  networkPassphrase = this.cfg.stellar.network;
1865
1865
  if (challengeResponse.network_passphrase &&
@@ -1874,24 +1874,26 @@ var Sep10 = /** @class */ (function () {
1874
1874
  throw new Exceptions_1.ChallengeValidationFailedError(e instanceof Error ? e : new Error(String(e)));
1875
1875
  }
1876
1876
  transaction = stellar_sdk_1.TransactionBuilder.fromXDR(challengeResponse.transaction, networkPassphrase);
1877
- _i = 0, _b = transaction.operations;
1878
- _c.label = 1;
1879
- case 1:
1880
- if (!(_i < _b.length)) return [3 /*break*/, 4];
1881
- op = _b[_i];
1882
- if (!(op.type === "manageData" && op.name === "client_domain")) return [3 /*break*/, 3];
1877
+ hasClientDomain = transaction.operations.some(function (op) { return op.type === "manageData" && op.name === "client_domain"; });
1878
+ if (!hasClientDomain) return [3 /*break*/, 2];
1879
+ originalHash = transaction.hash();
1883
1880
  return [4 /*yield*/, walletSigner.signWithDomainAccount({
1884
1881
  transactionXDR: challengeResponse.transaction,
1885
1882
  networkPassphrase: networkPassphrase,
1886
1883
  accountKp: accountKp,
1887
1884
  })];
1885
+ case 1:
1886
+ returned = _b.sent();
1887
+ // Transaction.hash() covers the envelope body but excludes signatures, so
1888
+ // a domain signer that only appends its signature preserves the hash. Any
1889
+ // change to the operations, source account, memo, or other body fields
1890
+ // changes the hash and is rejected here.
1891
+ if (!returned.hash().equals(originalHash)) {
1892
+ throw new Exceptions_1.DomainSigningModifiedError();
1893
+ }
1894
+ transaction = returned;
1895
+ _b.label = 2;
1888
1896
  case 2:
1889
- transaction = _c.sent();
1890
- _c.label = 3;
1891
- case 3:
1892
- _i++;
1893
- return [3 /*break*/, 1];
1894
- case 4:
1895
1897
  walletSigner.signWithClientAccount({ transaction: transaction, accountKp: accountKp });
1896
1898
  return [2 /*return*/, transaction];
1897
1899
  }
@@ -2232,7 +2234,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
2232
2234
  return (mod && mod.__esModule) ? mod : { "default": mod };
2233
2235
  };
2234
2236
  Object.defineProperty(exports, "__esModule", ({ value: true }));
2235
- exports.Sep7UriTypeNotSupportedError = exports.Sep7LongMsgError = exports.Sep7InvalidUriError = exports.AuthHeaderClientDomainRequiredError = exports.AuthHeaderSigningKeypairRequiredError = exports.DefaultSignerDomainAccountError = exports.SigningKeypairMissingSecretError = exports.InvalidJsonError = exports.UnknownAnchorTransactionError = exports.AllowHttpOnNonTestnetError = exports.ChallengeTxnInvalidSignatureError = exports.ChallengeTxnIncorrectSequenceError = exports.NetworkPassphraseMismatchError = exports.ChallengeValidationFailedError = exports.MissingSigningKeyError = exports.Sep38PriceOnlyOneAmountError = exports.NoAccountAndNoSponsorError = exports.DeviceKeyEqualsMasterKeyError = exports.NoAccountSignersError = exports.UnableToDeduceKeyError = exports.NoDeviceKeyForAccountError = exports.LostSignerKeyNotFound = exports.NotAllSignaturesFetchedError = exports.RecoveryIdentityNotFoundError = exports.RecoveryServerNotFoundError = exports.KYCServerNotFoundError = exports.CustomerNotFoundError = exports.Sep9InfoRequiredError = exports.WithdrawalTxMemoError = exports.PathPayOnlyOneAmountError = exports.WithdrawalTxMissingMemoError = exports.WithdrawalTxMissingDestinationError = exports.WithdrawalTxNotPendingUserTransferStartError = exports.OperationsLimitExceededError = exports.SignerRequiredError = exports.TransactionSubmitWithFeeIncreaseFailedError = exports.ExpiredTokenError = exports.InvalidTokenError = exports.MissingTokenError = exports.InsufficientStartingBalanceError = exports.TransactionSubmitFailedError = exports.AccountDoesNotExistError = exports.InvalidTransactionsResponseError = exports.InvalidTransactionResponseError = exports.MissingTransactionIdError = exports.ClientDomainWithMemoError = exports.InvalidMemoError = exports.AssetNotSupportedError = exports.ServerRequestFailedError = void 0;
2237
+ exports.Sep7UriTypeNotSupportedError = exports.Sep7LongMsgError = exports.Sep7InvalidUriError = exports.AuthHeaderClientDomainRequiredError = exports.AuthHeaderSigningKeypairRequiredError = exports.DomainSigningModifiedError = exports.DefaultSignerDomainAccountError = exports.SigningKeypairMissingSecretError = exports.InvalidJsonError = exports.UnknownAnchorTransactionError = exports.AllowHttpOnNonTestnetError = exports.ChallengeTxnInvalidSignatureError = exports.ChallengeTxnIncorrectSequenceError = exports.NetworkPassphraseMismatchError = exports.ChallengeValidationFailedError = exports.MissingSigningKeyError = exports.Sep38PriceOnlyOneAmountError = exports.NoAccountAndNoSponsorError = exports.DeviceKeyEqualsMasterKeyError = exports.NoAccountSignersError = exports.UnableToDeduceKeyError = exports.NoDeviceKeyForAccountError = exports.LostSignerKeyNotFound = exports.NotAllSignaturesFetchedError = exports.RecoveryIdentityNotFoundError = exports.RecoveryServerNotFoundError = exports.KYCServerNotFoundError = exports.CustomerNotFoundError = exports.Sep9InfoRequiredError = exports.WithdrawalTxMemoError = exports.PathPayOnlyOneAmountError = exports.WithdrawalTxMissingMemoError = exports.WithdrawalTxMissingDestinationError = exports.WithdrawalTxNotPendingUserTransferStartError = exports.OperationsLimitExceededError = exports.SignerRequiredError = exports.TransactionSubmitWithFeeIncreaseFailedError = exports.ExpiredTokenError = exports.InvalidTokenError = exports.MissingTokenError = exports.InsufficientStartingBalanceError = exports.TransactionSubmitFailedError = exports.AccountDoesNotExistError = exports.InvalidTransactionsResponseError = exports.InvalidTransactionResponseError = exports.MissingTransactionIdError = exports.ClientDomainWithMemoError = exports.InvalidMemoError = exports.AssetNotSupportedError = exports.ServerRequestFailedError = void 0;
2236
2238
  var axios_1 = __importDefault(__webpack_require__(/*! axios */ "../../node_modules/axios/dist/node/axios.cjs"));
2237
2239
  var Utils_1 = __webpack_require__(/*! ../Utils */ "./src/walletSdk/Utils/index.ts");
2238
2240
  var ServerRequestFailedError = /** @class */ (function (_super) {
@@ -2686,6 +2688,16 @@ var DefaultSignerDomainAccountError = /** @class */ (function (_super) {
2686
2688
  return DefaultSignerDomainAccountError;
2687
2689
  }(Error));
2688
2690
  exports.DefaultSignerDomainAccountError = DefaultSignerDomainAccountError;
2691
+ var DomainSigningModifiedError = /** @class */ (function (_super) {
2692
+ __extends(DomainSigningModifiedError, _super);
2693
+ function DomainSigningModifiedError() {
2694
+ var _this = _super.call(this, "Domain signer returned a transaction whose body differs from the original challenge. Only the client_domain signature should be added.") || this;
2695
+ Object.setPrototypeOf(_this, DomainSigningModifiedError.prototype);
2696
+ return _this;
2697
+ }
2698
+ return DomainSigningModifiedError;
2699
+ }(Error));
2700
+ exports.DomainSigningModifiedError = DomainSigningModifiedError;
2689
2701
  var AuthHeaderSigningKeypairRequiredError = /** @class */ (function (_super) {
2690
2702
  __extends(AuthHeaderSigningKeypairRequiredError, _super);
2691
2703
  function AuthHeaderSigningKeypairRequiredError() {
@@ -3013,6 +3025,12 @@ var TransactionBuilder_1 = __webpack_require__(/*! ./Transaction/TransactionBuil
3013
3025
  var Exceptions_1 = __webpack_require__(/*! ../Exceptions */ "./src/walletSdk/Exceptions/index.ts");
3014
3026
  var getResultCode_1 = __webpack_require__(/*! ../Utils/getResultCode */ "./src/walletSdk/Utils/getResultCode.ts");
3015
3027
  var Account_1 = __webpack_require__(/*! ./Account */ "./src/walletSdk/Horizon/Account.ts");
3028
+ var SUBMIT_504_MAX_RETRIES = 5;
3029
+ var SUBMIT_504_BASE_DELAY_MS = 1000;
3030
+ var SUBMIT_504_MAX_DELAY_MS = 30000;
3031
+ var sleep = function (ms) {
3032
+ return new Promise(function (resolve) { return setTimeout(resolve, ms); });
3033
+ };
3016
3034
  /**
3017
3035
  * Interaction with the Stellar Network.
3018
3036
  * Do not create this object directly, use the Wallet class.
@@ -3089,37 +3107,63 @@ var Stellar = /** @class */ (function () {
3089
3107
  return stellar_sdk_1.TransactionBuilder.buildFeeBumpTransaction(feeAddress.keypair, (baseFee || this.cfg.stellar.baseFee).toString(), transaction, transaction.networkPassphrase);
3090
3108
  };
3091
3109
  /**
3092
- * Submits a signed transaction to the server. If the submission fails with status
3093
- * 504 indicating a timeout error, it will automatically retry.
3110
+ * Submits a signed transaction to Horizon.
3111
+ *
3112
+ * On HTTP 504 (timeout), retries with exponential backoff up to
3113
+ * {@link SUBMIT_504_MAX_RETRIES} times. Any non-504 error is rethrown
3114
+ * immediately without retrying.
3115
+ *
3094
3116
  * @param {Transaction|FeeBumpTransaction} signedTransaction - The signed transaction to submit.
3095
- * @returns {boolean} `true` if the transaction was successfully submitted.
3096
- * @throws {TransactionSubmitFailedError} If the transaction submission fails.
3117
+ * @returns {boolean} `true` if Horizon confirmed the submission as successful.
3118
+ * @throws {TransactionSubmitFailedError} If Horizon responded with a non-successful
3119
+ * submission result (the transaction reached Horizon but was rejected).
3120
+ * @throws The underlying 504 error if every retry attempt timed out. In this
3121
+ * case the transaction's on-chain status is **indeterminate** — Horizon may
3122
+ * have ingested it on the final attempt without responding in time. Callers
3123
+ * should poll the transaction hash to determine the actual outcome rather
3124
+ * than resubmit blindly; resubmitting a signed transaction with the same
3125
+ * sequence number will fail with `tx_bad_seq` once the original lands.
3097
3126
  */
3098
3127
  Stellar.prototype.submitTransaction = function (signedTransaction) {
3128
+ var _a;
3099
3129
  return __awaiter(this, void 0, void 0, function () {
3100
- var response, e_2;
3101
- return __generator(this, function (_a) {
3102
- switch (_a.label) {
3130
+ var lastError, attempt, response, e_2, cappedDelay, half;
3131
+ return __generator(this, function (_b) {
3132
+ switch (_b.label) {
3103
3133
  case 0:
3104
- _a.trys.push([0, 2, , 5]);
3105
- return [4 /*yield*/, this.server.submitTransaction(signedTransaction)];
3134
+ attempt = 0;
3135
+ _b.label = 1;
3106
3136
  case 1:
3107
- response = _a.sent();
3137
+ if (!(attempt <= SUBMIT_504_MAX_RETRIES)) return [3 /*break*/, 7];
3138
+ _b.label = 2;
3139
+ case 2:
3140
+ _b.trys.push([2, 4, , 6]);
3141
+ return [4 /*yield*/, this.server.submitTransaction(signedTransaction)];
3142
+ case 3:
3143
+ response = _b.sent();
3108
3144
  if (!response.successful) {
3109
3145
  throw new Exceptions_1.TransactionSubmitFailedError(response);
3110
3146
  }
3111
3147
  return [2 /*return*/, true];
3112
- case 2:
3113
- e_2 = _a.sent();
3114
- if (!(e_2.response.status === 504)) return [3 /*break*/, 4];
3115
- return [4 /*yield*/, this.submitTransaction(signedTransaction)];
3116
- case 3:
3117
- // in case of 504, keep retrying this tx until submission succeeds or we get a different error
3118
- // https://developers.stellar.org/api/errors/http-status-codes/horizon-specific/timeout
3119
- // https://developers.stellar.org/docs/encyclopedia/error-handling#timeouts
3120
- return [2 /*return*/, _a.sent()];
3121
- case 4: throw e_2;
3122
- case 5: return [2 /*return*/];
3148
+ case 4:
3149
+ e_2 = _b.sent();
3150
+ if (((_a = e_2 === null || e_2 === void 0 ? void 0 : e_2.response) === null || _a === void 0 ? void 0 : _a.status) !== 504) {
3151
+ throw e_2;
3152
+ }
3153
+ lastError = e_2;
3154
+ if (attempt === SUBMIT_504_MAX_RETRIES) {
3155
+ return [3 /*break*/, 7];
3156
+ }
3157
+ cappedDelay = Math.min(SUBMIT_504_BASE_DELAY_MS * Math.pow(2, attempt), SUBMIT_504_MAX_DELAY_MS);
3158
+ half = cappedDelay / 2;
3159
+ return [4 /*yield*/, sleep(half + Math.random() * half)];
3160
+ case 5:
3161
+ _b.sent();
3162
+ return [3 /*break*/, 6];
3163
+ case 6:
3164
+ attempt++;
3165
+ return [3 /*break*/, 1];
3166
+ case 7: throw lastError;
3123
3167
  }
3124
3168
  });
3125
3169
  });
@@ -3191,6 +3235,7 @@ var Stellar = /** @class */ (function () {
3191
3235
  signerFunction: signerFunction,
3192
3236
  baseFee: newFee,
3193
3237
  memo: memo,
3238
+ maxFee: maxFee,
3194
3239
  })];
3195
3240
  }
3196
3241
  throw e_3;
@@ -82427,7 +82472,7 @@ function decode(arr) {
82427
82472
  /***/ ((module) => {
82428
82473
 
82429
82474
  "use strict";
82430
- module.exports = JSON.parse('{"name":"@stellar/typescript-wallet-sdk","version":"3.0.0","engines":{"node":">=20"},"browser":"./lib/bundle_browser.js","main":"./lib/bundle.js","types":"./lib/index.d.ts","license":"Apache-2.0","private":false,"devDependencies":{"@babel/preset-env":"^7.20.2","@babel/preset-typescript":"^7.23.3","@stellar/prettier-config":"^1.0.1","@stellar/tsconfig":"^1.0.2","@types/jest":"^29.4.0","@types/lodash":"^4.14.194","@types/sinon":"^10.0.15","@typescript-eslint/eslint-plugin":"^6.7.5","@typescript-eslint/parser":"^6.7.5","babel-jest":"^29.4.1","crypto-browserify":"^3.12.0","dotenv":"^16.3.1","eslint":"^8.51.0","eslint-config-prettier":"^9.0.0","eslint-plugin-jsdoc":"^46.8.2","express":"^4.19.2","husky":"^8.0.0","jest":"^29.4.1","lint-staged":"^14.0.1","npm-run-all":"^4.1.5","playwright":"^1.43.1","prettier":"^2.0.5","pretty-quick":"^2.0.1","process":"^0.11.10","sinon":"^15.1.0","stream-browserify":"^3.0.0","ts-jest":"^29.0.5","ts-loader":"^9.4.2","ts-node":"^10.9.1","tslib":"^2.5.0","typescript":"^5.0.4","webpack":"^5.83.1","webpack-cli":"^5.1.1"},"dependencies":{"@stablelib/base64":"^2.0.0","@stablelib/utf8":"^2.0.0","@stellar/stellar-sdk":"15.0.1","axios":"^1.4.0","base64url":"^3.0.1","https-browserify":"^1.0.0","jws":"^4.0.0","lodash":"^4.17.21","query-string":"^7.1.3","stream-http":"^3.2.0","tweetnacl":"^1.0.3","url":"^0.11.0","util":"^0.12.5","utility-types":"^3.10.0","vm-browserify":"^1.1.2"},"scripts":{"test":"jest --watchAll","test:ci":"jest --ci","test:e2e:ci":"jest --config jest.e2e.config.js --ci","test:recovery:ci":"jest --config jest.integration.config.js recovery.test.ts --ci","test:anchorplatform:ci":"yarn jest --config jest.integration.config.js anchorplatform.test.ts --ci","build:web":"webpack --config webpack.config.js","build:node":"webpack --env NODE=true --config webpack.config.js","build":"run-p build:web build:node","example:sep10Server":"ts-node examples/sep10/sep10Server.ts","example:sep10Wallet":"ts-node examples/sep10/sep10Wallet.ts","example:sep24":"ts-node examples/sep24/sep24.ts","example:sep12":"ts-node examples/sep12/sep12.ts"}}');
82475
+ module.exports = JSON.parse('{"name":"@stellar/typescript-wallet-sdk","version":"3.0.1","engines":{"node":">=20"},"browser":"./lib/bundle_browser.js","main":"./lib/bundle.js","types":"./lib/index.d.ts","license":"Apache-2.0","private":false,"devDependencies":{"@babel/preset-env":"^7.20.2","@babel/preset-typescript":"^7.23.3","@stellar/prettier-config":"^1.0.1","@stellar/tsconfig":"^1.0.2","@types/jest":"^29.4.0","@types/lodash":"^4.14.194","@types/sinon":"^10.0.15","@typescript-eslint/eslint-plugin":"^6.7.5","@typescript-eslint/parser":"^6.7.5","babel-jest":"^29.4.1","crypto-browserify":"^3.12.0","dotenv":"^16.3.1","eslint":"^8.51.0","eslint-config-prettier":"^9.0.0","eslint-plugin-jsdoc":"^46.8.2","express":"^4.19.2","husky":"^8.0.0","jest":"^29.4.1","lint-staged":"^14.0.1","npm-run-all":"^4.1.5","playwright":"^1.43.1","prettier":"^2.0.5","pretty-quick":"^2.0.1","process":"^0.11.10","sinon":"^15.1.0","stream-browserify":"^3.0.0","ts-jest":"^29.0.5","ts-loader":"^9.4.2","ts-node":"^10.9.1","tslib":"^2.5.0","typescript":"^5.0.4","webpack":"^5.83.1","webpack-cli":"^5.1.1"},"dependencies":{"@stablelib/base64":"^2.0.0","@stablelib/utf8":"^2.0.0","@stellar/stellar-sdk":"15.0.1","axios":"^1.4.0","base64url":"^3.0.1","https-browserify":"^1.0.0","jws":"^4.0.0","lodash":"^4.17.21","query-string":"^7.1.3","stream-http":"^3.2.0","tweetnacl":"^1.0.3","url":"^0.11.0","util":"^0.12.5","utility-types":"^3.10.0","vm-browserify":"^1.1.2"},"scripts":{"test":"jest --watchAll","test:ci":"jest --ci","test:e2e:ci":"jest --config jest.e2e.config.js --ci","test:recovery:ci":"jest --config jest.integration.config.js recovery.test.ts --ci","test:anchorplatform:ci":"yarn jest --config jest.integration.config.js anchorplatform.test.ts --ci","build:web":"webpack --config webpack.config.js","build:node":"webpack --env NODE=true --config webpack.config.js","build":"run-p build:web build:node","example:sep10Server":"ts-node examples/sep10/sep10Server.ts","example:sep10Wallet":"ts-node examples/sep10/sep10Wallet.ts","example:sep24":"ts-node examples/sep24/sep24.ts","example:sep12":"ts-node examples/sep12/sep12.ts"}}');
82431
82476
 
82432
82477
  /***/ }),
82433
82478