@imtbl/sdk 0.1.9-alpha.3 → 0.1.9

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/dist/passport.js CHANGED
@@ -21,7 +21,7 @@ const createImmutableXConfiguration = ({ basePath, chainID, coreContractAddress,
21
21
  chainID,
22
22
  coreContractAddress,
23
23
  registrationContractAddress,
24
- sdkVersion: 'ts-immutable-sdk-0.1.9-alpha.3',
24
+ sdkVersion: 'ts-immutable-sdk-0.0.0',
25
25
  });
26
26
  /**
27
27
  * Sets `sdkVersion` at the time of build
@@ -524,69 +524,6 @@ class ImmutableXClient {
524
524
  }
525
525
  }
526
526
 
527
- // used to sign message with L1 keys. Used for registration
528
- function serializeEthSignature(sig) {
529
- // This is because golang appends a recovery param
530
- // https://github.com/ethers-io/ethers.js/issues/823
531
- return encUtils.addHexPrefix(encUtils.padLeft(sig.r.toString(16), 64)
532
- + encUtils.padLeft(sig.s.toString(16), 64)
533
- + encUtils.padLeft(sig.recoveryParam?.toString(16) || '', 2));
534
- }
535
- function importRecoveryParam(v) {
536
- const isValidBigNumber = new BN(v, 16).cmp(new BN(27)) !== -1
537
- ? new BN(v, 16).sub(new BN(27)).toNumber()
538
- : new BN(v, 16).toNumber();
539
- return v.trim()
540
- ? isValidBigNumber
541
- : undefined;
542
- }
543
- // used chained with serializeEthSignature. serializeEthSignature(deserializeSignature(...))
544
- function deserializeSignature(sig, size = 64) {
545
- const removedHexPrefixSig = encUtils.removeHexPrefix(sig);
546
- return {
547
- r: new BN(removedHexPrefixSig.substring(0, size), 'hex'),
548
- s: new BN(removedHexPrefixSig.substring(size, size * 2), 'hex'),
549
- recoveryParam: importRecoveryParam(removedHexPrefixSig.substring(size * 2, size * 2 + 2)),
550
- };
551
- }
552
- async function signRaw(payload, signer) {
553
- const signature = deserializeSignature(await signer.signMessage(payload));
554
- return serializeEthSignature(signature);
555
- }
556
-
557
- /**
558
- * Helper method to convert token type to a SignableToken type
559
- * @param token - the token type to convert to a SignableToken type
560
- * @returns the converted SignableToken
561
- */
562
- function convertToSignableToken(token) {
563
- switch (token.type) {
564
- case 'ERC721':
565
- return {
566
- type: 'ERC721',
567
- data: {
568
- token_id: token.tokenId,
569
- token_address: token.tokenAddress,
570
- },
571
- };
572
- case 'ERC20':
573
- return {
574
- type: 'ERC20',
575
- data: {
576
- token_address: token.tokenAddress,
577
- },
578
- };
579
- case 'ETH':
580
- default:
581
- return {
582
- type: 'ETH',
583
- data: {
584
- decimals: 18,
585
- },
586
- };
587
- }
588
- }
589
-
590
527
  function bind(fn, thisArg) {
591
528
  return function wrap() {
592
529
  return fn.apply(thisArg, arguments);
@@ -3798,7 +3735,7 @@ var globalAxios = axios;
3798
3735
  /* tslint:disable */
3799
3736
  /* eslint-disable */
3800
3737
  /**
3801
- * Swagger Guardian
3738
+ * Guardian
3802
3739
  * Guardian API
3803
3740
  *
3804
3741
  * The version of the OpenAPI document: 1.0.0
@@ -3808,7 +3745,7 @@ var globalAxios = axios;
3808
3745
  * https://openapi-generator.tech
3809
3746
  * Do not edit the class manually.
3810
3747
  */
3811
- const BASE_PATH = "http://guardian.sandbox.imtbl.com".replace(/\/+$/, "");
3748
+ const BASE_PATH = "https://guardian.sandbox.imtbl.com".replace(/\/+$/, "");
3812
3749
  /**
3813
3750
  *
3814
3751
  * @export
@@ -3845,7 +3782,7 @@ class RequiredError extends Error {
3845
3782
  /* tslint:disable */
3846
3783
  /* eslint-disable */
3847
3784
  /**
3848
- * Swagger Guardian
3785
+ * Guardian
3849
3786
  * Guardian API
3850
3787
  *
3851
3788
  * The version of the OpenAPI document: 1.0.0
@@ -3911,6 +3848,19 @@ const setSearchParams = function (url, ...objects) {
3911
3848
  setFlattenedQueryParams(searchParams, objects);
3912
3849
  url.search = searchParams.toString();
3913
3850
  };
3851
+ /**
3852
+ *
3853
+ * @export
3854
+ */
3855
+ const serializeDataIfNeeded = function (value, requestOptions, configuration) {
3856
+ const nonString = typeof value !== 'string';
3857
+ const needsSerialization = nonString && configuration && configuration.isJsonMime
3858
+ ? configuration.isJsonMime(requestOptions.headers['Content-Type'])
3859
+ : nonString;
3860
+ return needsSerialization
3861
+ ? JSON.stringify(value !== undefined ? value : {})
3862
+ : (value || "");
3863
+ };
3914
3864
  /**
3915
3865
  *
3916
3866
  * @export
@@ -3932,7 +3882,7 @@ const createRequestFunction = function (axiosArgs, globalAxios, BASE_PATH, confi
3932
3882
  /* tslint:disable */
3933
3883
  /* eslint-disable */
3934
3884
  /**
3935
- * Swagger Guardian
3885
+ * Guardian
3936
3886
  * Guardian API
3937
3887
  *
3938
3888
  * The version of the OpenAPI document: 1.0.0
@@ -3943,22 +3893,25 @@ const createRequestFunction = function (axiosArgs, globalAxios, BASE_PATH, confi
3943
3893
  * Do not edit the class manually.
3944
3894
  */
3945
3895
  /**
3946
- * StarkexTransactionsApi - axios parameter creator
3896
+ * TransactionsApi - axios parameter creator
3947
3897
  * @export
3948
3898
  */
3949
- const StarkexTransactionsApiAxiosParamCreator = function (configuration) {
3899
+ const TransactionsApiAxiosParamCreator = function (configuration) {
3950
3900
  return {
3951
3901
  /**
3952
- * Check if it is a valid transaction by payload hash
3953
- * @summary Evaluate if it is an valid transaction
3902
+ * Approve a pending transaction
3903
+ * @summary Approve a pending transaction given chain
3954
3904
  * @param {string} payloadHash Hash for the payload
3905
+ * @param {TransactionApprovalRequest} transactionApprovalRequest request body for approving a pending transactio
3955
3906
  * @param {*} [options] Override http request option.
3956
3907
  * @throws {RequiredError}
3957
3908
  */
3958
- evaluateStarkexTransaction: async (payloadHash, options = {}) => {
3909
+ approvePendingTransaction: async (payloadHash, transactionApprovalRequest, options = {}) => {
3959
3910
  // verify required parameter 'payloadHash' is not null or undefined
3960
- assertParamExists('evaluateStarkexTransaction', 'payloadHash', payloadHash);
3961
- const localVarPath = `/guardian/v1/starkex/evaluate/{payloadHash}`
3911
+ assertParamExists('approvePendingTransaction', 'payloadHash', payloadHash);
3912
+ // verify required parameter 'transactionApprovalRequest' is not null or undefined
3913
+ assertParamExists('approvePendingTransaction', 'transactionApprovalRequest', transactionApprovalRequest);
3914
+ const localVarPath = `/guardian/v1/transactions/{payloadHash}/approve`
3962
3915
  .replace(`{${"payloadHash"}}`, encodeURIComponent(String(payloadHash)));
3963
3916
  // use dummy base URL string because the URL constructor only accepts absolute URLs.
3964
3917
  const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
@@ -3972,80 +3925,58 @@ const StarkexTransactionsApiAxiosParamCreator = function (configuration) {
3972
3925
  // authentication BearerAuth required
3973
3926
  // http bearer authentication required
3974
3927
  await setBearerAuthToObject(localVarHeaderParameter, configuration);
3928
+ localVarHeaderParameter['Content-Type'] = 'application/json';
3975
3929
  setSearchParams(localVarUrlObj, localVarQueryParameter);
3976
3930
  let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
3977
3931
  localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers };
3932
+ localVarRequestOptions.data = serializeDataIfNeeded(transactionApprovalRequest, localVarRequestOptions, configuration);
3978
3933
  return {
3979
3934
  url: toPathString(localVarUrlObj),
3980
3935
  options: localVarRequestOptions,
3981
3936
  };
3982
3937
  },
3983
- };
3984
- };
3985
- /**
3986
- * StarkexTransactionsApi - functional programming interface
3987
- * @export
3988
- */
3989
- const StarkexTransactionsApiFp = function (configuration) {
3990
- const localVarAxiosParamCreator = StarkexTransactionsApiAxiosParamCreator(configuration);
3991
- return {
3992
3938
  /**
3993
- * Check if it is a valid transaction by payload hash
3994
- * @summary Evaluate if it is an valid transaction
3995
- * @param {string} payloadHash Hash for the payload
3939
+ * Check if the transaction is valid by transaction ID for both StarkEx and EVM
3940
+ * @summary Evaluate a transaction
3941
+ * @param {string} id Transaction identifier: payloadHash on StarkEx or EVM ID
3942
+ * @param {TransactionEvaluationRequest} transactionEvaluationRequest Specifies the kind of transaction
3996
3943
  * @param {*} [options] Override http request option.
3997
3944
  * @throws {RequiredError}
3998
3945
  */
3999
- async evaluateStarkexTransaction(payloadHash, options) {
4000
- const localVarAxiosArgs = await localVarAxiosParamCreator.evaluateStarkexTransaction(payloadHash, options);
4001
- return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
3946
+ evaluateTransaction: async (id, transactionEvaluationRequest, options = {}) => {
3947
+ // verify required parameter 'id' is not null or undefined
3948
+ assertParamExists('evaluateTransaction', 'id', id);
3949
+ // verify required parameter 'transactionEvaluationRequest' is not null or undefined
3950
+ assertParamExists('evaluateTransaction', 'transactionEvaluationRequest', transactionEvaluationRequest);
3951
+ const localVarPath = `/guardian/v1/transactions/{id}/evaluate`
3952
+ .replace(`{${"id"}}`, encodeURIComponent(String(id)));
3953
+ // use dummy base URL string because the URL constructor only accepts absolute URLs.
3954
+ const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
3955
+ let baseOptions;
3956
+ if (configuration) {
3957
+ baseOptions = configuration.baseOptions;
3958
+ }
3959
+ const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options };
3960
+ const localVarHeaderParameter = {};
3961
+ const localVarQueryParameter = {};
3962
+ // authentication BearerAuth required
3963
+ // http bearer authentication required
3964
+ await setBearerAuthToObject(localVarHeaderParameter, configuration);
3965
+ localVarHeaderParameter['Content-Type'] = 'application/json';
3966
+ setSearchParams(localVarUrlObj, localVarQueryParameter);
3967
+ let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
3968
+ localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers };
3969
+ localVarRequestOptions.data = serializeDataIfNeeded(transactionEvaluationRequest, localVarRequestOptions, configuration);
3970
+ return {
3971
+ url: toPathString(localVarUrlObj),
3972
+ options: localVarRequestOptions,
3973
+ };
4002
3974
  },
4003
- };
4004
- };
4005
- /**
4006
- * StarkexTransactionsApi - object-oriented interface
4007
- * @export
4008
- * @class StarkexTransactionsApi
4009
- * @extends {BaseAPI}
4010
- */
4011
- class StarkexTransactionsApi extends BaseAPI {
4012
- /**
4013
- * Check if it is a valid transaction by payload hash
4014
- * @summary Evaluate if it is an valid transaction
4015
- * @param {StarkexTransactionsApiEvaluateStarkexTransactionRequest} requestParameters Request parameters.
4016
- * @param {*} [options] Override http request option.
4017
- * @throws {RequiredError}
4018
- * @memberof StarkexTransactionsApi
4019
- */
4020
- evaluateStarkexTransaction(requestParameters, options) {
4021
- return StarkexTransactionsApiFp(this.configuration).evaluateStarkexTransaction(requestParameters.payloadHash, options).then((request) => request(this.axios, this.basePath));
4022
- }
4023
- }
4024
-
4025
- /* tslint:disable */
4026
- /* eslint-disable */
4027
- /**
4028
- * Swagger Guardian
4029
- * Guardian API
4030
- *
4031
- * The version of the OpenAPI document: 1.0.0
4032
- * Contact: support@immutable.com
4033
- *
4034
- * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
4035
- * https://openapi-generator.tech
4036
- * Do not edit the class manually.
4037
- */
4038
- /**
4039
- * TransactionsApi - axios parameter creator
4040
- * @export
4041
- */
4042
- const TransactionsApiAxiosParamCreator = function (configuration) {
4043
- return {
4044
3975
  /**
4045
3976
  * Get a transaction by payload hash
4046
3977
  * @summary Info for a specific transaction
4047
3978
  * @param {string} transactionID The id of the starkex transaction to retrieve
4048
- * @param {string} chainType roll up type
3979
+ * @param {'starkex' | 'evm'} chainType roll up type
4049
3980
  * @param {number} [chainID] ID of evm chain
4050
3981
  * @param {*} [options] Override http request option.
4051
3982
  * @throws {RequiredError}
@@ -4092,11 +4023,35 @@ const TransactionsApiAxiosParamCreator = function (configuration) {
4092
4023
  const TransactionsApiFp = function (configuration) {
4093
4024
  const localVarAxiosParamCreator = TransactionsApiAxiosParamCreator(configuration);
4094
4025
  return {
4026
+ /**
4027
+ * Approve a pending transaction
4028
+ * @summary Approve a pending transaction given chain
4029
+ * @param {string} payloadHash Hash for the payload
4030
+ * @param {TransactionApprovalRequest} transactionApprovalRequest request body for approving a pending transactio
4031
+ * @param {*} [options] Override http request option.
4032
+ * @throws {RequiredError}
4033
+ */
4034
+ async approvePendingTransaction(payloadHash, transactionApprovalRequest, options) {
4035
+ const localVarAxiosArgs = await localVarAxiosParamCreator.approvePendingTransaction(payloadHash, transactionApprovalRequest, options);
4036
+ return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
4037
+ },
4038
+ /**
4039
+ * Check if the transaction is valid by transaction ID for both StarkEx and EVM
4040
+ * @summary Evaluate a transaction
4041
+ * @param {string} id Transaction identifier: payloadHash on StarkEx or EVM ID
4042
+ * @param {TransactionEvaluationRequest} transactionEvaluationRequest Specifies the kind of transaction
4043
+ * @param {*} [options] Override http request option.
4044
+ * @throws {RequiredError}
4045
+ */
4046
+ async evaluateTransaction(id, transactionEvaluationRequest, options) {
4047
+ const localVarAxiosArgs = await localVarAxiosParamCreator.evaluateTransaction(id, transactionEvaluationRequest, options);
4048
+ return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
4049
+ },
4095
4050
  /**
4096
4051
  * Get a transaction by payload hash
4097
4052
  * @summary Info for a specific transaction
4098
4053
  * @param {string} transactionID The id of the starkex transaction to retrieve
4099
- * @param {string} chainType roll up type
4054
+ * @param {'starkex' | 'evm'} chainType roll up type
4100
4055
  * @param {number} [chainID] ID of evm chain
4101
4056
  * @param {*} [options] Override http request option.
4102
4057
  * @throws {RequiredError}
@@ -4114,6 +4069,28 @@ const TransactionsApiFp = function (configuration) {
4114
4069
  * @extends {BaseAPI}
4115
4070
  */
4116
4071
  class TransactionsApi extends BaseAPI {
4072
+ /**
4073
+ * Approve a pending transaction
4074
+ * @summary Approve a pending transaction given chain
4075
+ * @param {TransactionsApiApprovePendingTransactionRequest} requestParameters Request parameters.
4076
+ * @param {*} [options] Override http request option.
4077
+ * @throws {RequiredError}
4078
+ * @memberof TransactionsApi
4079
+ */
4080
+ approvePendingTransaction(requestParameters, options) {
4081
+ return TransactionsApiFp(this.configuration).approvePendingTransaction(requestParameters.payloadHash, requestParameters.transactionApprovalRequest, options).then((request) => request(this.axios, this.basePath));
4082
+ }
4083
+ /**
4084
+ * Check if the transaction is valid by transaction ID for both StarkEx and EVM
4085
+ * @summary Evaluate a transaction
4086
+ * @param {TransactionsApiEvaluateTransactionRequest} requestParameters Request parameters.
4087
+ * @param {*} [options] Override http request option.
4088
+ * @throws {RequiredError}
4089
+ * @memberof TransactionsApi
4090
+ */
4091
+ evaluateTransaction(requestParameters, options) {
4092
+ return TransactionsApiFp(this.configuration).evaluateTransaction(requestParameters.id, requestParameters.transactionEvaluationRequest, options).then((request) => request(this.axios, this.basePath));
4093
+ }
4117
4094
  /**
4118
4095
  * Get a transaction by payload hash
4119
4096
  * @summary Info for a specific transaction
@@ -4130,7 +4107,7 @@ class TransactionsApi extends BaseAPI {
4130
4107
  /* tslint:disable */
4131
4108
  /* eslint-disable */
4132
4109
  /**
4133
- * Swagger Guardian
4110
+ * Guardian
4134
4111
  * Guardian API
4135
4112
  *
4136
4113
  * The version of the OpenAPI document: 1.0.0
@@ -4215,6 +4192,69 @@ class Configuration {
4215
4192
  }
4216
4193
  }
4217
4194
 
4195
+ // used to sign message with L1 keys. Used for registration
4196
+ function serializeEthSignature(sig) {
4197
+ // This is because golang appends a recovery param
4198
+ // https://github.com/ethers-io/ethers.js/issues/823
4199
+ return encUtils.addHexPrefix(encUtils.padLeft(sig.r.toString(16), 64)
4200
+ + encUtils.padLeft(sig.s.toString(16), 64)
4201
+ + encUtils.padLeft(sig.recoveryParam?.toString(16) || '', 2));
4202
+ }
4203
+ function importRecoveryParam(v) {
4204
+ const isValidBigNumber = new BN(v, 16).cmp(new BN(27)) !== -1
4205
+ ? new BN(v, 16).sub(new BN(27)).toNumber()
4206
+ : new BN(v, 16).toNumber();
4207
+ return v.trim()
4208
+ ? isValidBigNumber
4209
+ : undefined;
4210
+ }
4211
+ // used chained with serializeEthSignature. serializeEthSignature(deserializeSignature(...))
4212
+ function deserializeSignature(sig, size = 64) {
4213
+ const removedHexPrefixSig = encUtils.removeHexPrefix(sig);
4214
+ return {
4215
+ r: new BN(removedHexPrefixSig.substring(0, size), 'hex'),
4216
+ s: new BN(removedHexPrefixSig.substring(size, size * 2), 'hex'),
4217
+ recoveryParam: importRecoveryParam(removedHexPrefixSig.substring(size * 2, size * 2 + 2)),
4218
+ };
4219
+ }
4220
+ async function signRaw(payload, signer) {
4221
+ const signature = deserializeSignature(await signer.signMessage(payload));
4222
+ return serializeEthSignature(signature);
4223
+ }
4224
+
4225
+ /**
4226
+ * Helper method to convert token type to a SignableToken type
4227
+ * @param token - the token type to convert to a SignableToken type
4228
+ * @returns the converted SignableToken
4229
+ */
4230
+ function convertToSignableToken(token) {
4231
+ switch (token.type) {
4232
+ case 'ERC721':
4233
+ return {
4234
+ type: 'ERC721',
4235
+ data: {
4236
+ token_id: token.tokenId,
4237
+ token_address: token.tokenAddress,
4238
+ },
4239
+ };
4240
+ case 'ERC20':
4241
+ return {
4242
+ type: 'ERC20',
4243
+ data: {
4244
+ token_address: token.tokenAddress,
4245
+ },
4246
+ };
4247
+ case 'ETH':
4248
+ default:
4249
+ return {
4250
+ type: 'ETH',
4251
+ data: {
4252
+ decimals: 18,
4253
+ },
4254
+ };
4255
+ }
4256
+ }
4257
+
4218
4258
  var PassportErrorType;
4219
4259
  (function (PassportErrorType) {
4220
4260
  PassportErrorType["AUTHENTICATION_ERROR"] = "AUTHENTICATION_ERROR";
@@ -4373,209 +4413,130 @@ const getStarkSigner = async (signer) => withPassportError(async () => {
4373
4413
  return createStarkSigner(privateKey);
4374
4414
  }, PassportErrorType.WALLET_CONNECTION_ERROR);
4375
4415
 
4376
- async function exchangeTransfer({ user, starkSigner, request, exchangesApi, }) {
4377
- return withPassportError(async () => {
4378
- const { ethAddress } = user.imx;
4379
- const transferAmount = request.amount;
4380
- const signableResult = await exchangesApi.getExchangeSignableTransfer({
4381
- id: request.transactionID,
4382
- getSignableTransferRequest: {
4383
- sender: ethAddress,
4384
- token: convertToSignableToken(request),
4385
- amount: transferAmount,
4386
- receiver: request.receiver,
4387
- },
4388
- });
4389
- const starkAddress = await starkSigner.getAddress();
4390
- const { payload_hash: payloadHash } = signableResult.data;
4391
- const starkSignature = await starkSigner.signMessage(payloadHash);
4392
- const transferSigningParams = {
4393
- sender_stark_key: signableResult.data.sender_stark_key || starkAddress,
4394
- sender_vault_id: signableResult.data.sender_vault_id,
4395
- receiver_stark_key: signableResult.data.receiver_stark_key,
4396
- receiver_vault_id: signableResult.data.receiver_vault_id,
4397
- asset_id: signableResult.data.asset_id,
4398
- amount: signableResult.data.amount,
4399
- nonce: signableResult.data.nonce,
4400
- expiration_timestamp: signableResult.data.expiration_timestamp,
4401
- stark_signature: starkSignature,
4402
- };
4403
- const headers = {
4404
- // eslint-disable-next-line @typescript-eslint/naming-convention
4405
- Authorization: `Bearer ${user.accessToken}`,
4406
- };
4407
- const response = await exchangesApi.createExchangeTransfer({
4408
- id: request.transactionID,
4409
- createTransferRequest: transferSigningParams,
4410
- }, { headers });
4411
- return {
4412
- sent_signature: response?.data.sent_signature,
4413
- status: response?.data.status?.toString(),
4414
- time: response?.data.time,
4415
- transfer_id: response?.data.transfer_id,
4416
- };
4417
- }, PassportErrorType.EXCHANGE_TRANSFER_ERROR);
4418
- }
4419
-
4420
- var ReceiveMessage;
4421
- (function (ReceiveMessage) {
4422
- ReceiveMessage["CONFIRMATION_WINDOW_READY"] = "confirmation_window_ready";
4423
- ReceiveMessage["TRANSACTION_CONFIRMED"] = "transaction_confirmed";
4424
- ReceiveMessage["TRANSACTION_ERROR"] = "transaction_error";
4425
- })(ReceiveMessage || (ReceiveMessage = {}));
4426
- var SendMessage;
4427
- (function (SendMessage) {
4428
- SendMessage["TRANSACTION_START"] = "transaction_start";
4429
- })(SendMessage || (SendMessage = {}));
4430
- var TransactionTypes;
4431
- (function (TransactionTypes) {
4432
- TransactionTypes["cancelOrder"] = "delete:v1/orders";
4433
- TransactionTypes["createOrder"] = "post:v1/orders";
4434
- TransactionTypes["createTrade"] = "post:v1/trades";
4435
- TransactionTypes["createTransfer"] = "post:v1/transfers";
4436
- TransactionTypes["createBatchTransfer"] = "post:v2/transfers";
4437
- })(TransactionTypes || (TransactionTypes = {}));
4438
- const PASSPORT_EVENT_TYPE = 'imx_passport_confirmation';
4439
-
4440
- const openPopupCenter = ({ url, title, width, height, }) => {
4441
- const left = Math.max(0, Math.round(window.screenX + (window.outerWidth - width) / 2));
4442
- const top = Math.max(0, Math.round(window.screenY + (window.outerHeight - height) / 2));
4443
- const newWindow = window.open(url, title, `
4444
- scrollbars=yes,
4445
- width=${width},
4446
- height=${height},
4447
- top=${top},
4448
- left=${left}
4449
- `);
4450
- if (!newWindow) {
4451
- throw new Error('Failed to open confirmation screen');
4416
+ const POLL_INTERVAL = 1 * 1000; // every 1 second
4417
+ const MAX_RETRIES = 3;
4418
+ const wait = (ms) => new Promise((resolve) => {
4419
+ setTimeout(() => resolve(), ms);
4420
+ });
4421
+ const retryWithDelay = async (fn, options) => {
4422
+ const { retries = MAX_RETRIES, interval = POLL_INTERVAL, finalErr = Error('Retry failed'), finallyFn = () => { }, } = options || {};
4423
+ try {
4424
+ return await fn();
4425
+ }
4426
+ catch (err) {
4427
+ if (retries <= 0) {
4428
+ return Promise.reject(finalErr);
4429
+ }
4430
+ await wait(interval);
4431
+ return retryWithDelay(fn, { retries: retries - 1, finalErr, finallyFn });
4432
+ }
4433
+ finally {
4434
+ if (retries <= 0) {
4435
+ finallyFn();
4436
+ }
4452
4437
  }
4453
- newWindow.focus();
4454
- return newWindow;
4455
4438
  };
4456
4439
 
4457
- const CONFIRMATION_WINDOW_TITLE = 'Confirm this transaction';
4458
- const CONFIRMATION_WINDOW_HEIGHT = 380;
4459
- const CONFIRMATION_WINDOW_WIDTH = 480;
4460
- const CONFIRMATION_WINDOW_CLOSED_POLLING_DURATION = 1000;
4461
- class ConfirmationScreen {
4462
- config;
4463
- confirmationWindow;
4464
- constructor(config) {
4465
- this.config = config;
4466
- }
4467
- postMessage(destinationWindow, accessToken, message) {
4468
- destinationWindow.postMessage({
4469
- eventType: PASSPORT_EVENT_TYPE,
4440
+ class GuardianClient {
4441
+ transactionAPI;
4442
+ confirmationScreen;
4443
+ imxEtherAddress;
4444
+ constructor({ imxPublicApiDomain, accessToken, confirmationScreen, imxEtherAddress, }) {
4445
+ this.confirmationScreen = confirmationScreen;
4446
+ this.transactionAPI = new TransactionsApi(new Configuration({
4470
4447
  accessToken,
4471
- ...message,
4472
- }, this.config.passportDomain);
4448
+ basePath: imxPublicApiDomain,
4449
+ }));
4450
+ this.imxEtherAddress = imxEtherAddress;
4473
4451
  }
4474
- startTransaction(accessToken, transaction, popupOptions) {
4475
- return new Promise((resolve, reject) => {
4476
- const messageHandler = ({ data, origin }) => {
4477
- if (origin !== this.config.passportDomain
4478
- || data.eventType !== PASSPORT_EVENT_TYPE) {
4479
- return;
4480
- }
4481
- switch (data.messageType) {
4482
- case ReceiveMessage.CONFIRMATION_WINDOW_READY: {
4483
- // TODO: remove once fixed
4484
- // eslint-disable-next-line @typescript-eslint/no-use-before-define
4485
- this.postMessage(confirmationWindow, accessToken, {
4486
- messageType: SendMessage.TRANSACTION_START,
4487
- messageData: transaction,
4488
- });
4489
- break;
4490
- }
4491
- case ReceiveMessage.TRANSACTION_CONFIRMED: {
4492
- resolve({ confirmed: true });
4493
- break;
4494
- }
4495
- case ReceiveMessage.TRANSACTION_ERROR: {
4496
- reject(new Error('Transaction error'));
4497
- break;
4498
- }
4499
- default:
4500
- reject(new Error('Unsupported message type'));
4501
- }
4502
- };
4503
- window.addEventListener('message', messageHandler);
4504
- const confirmationWindow = openPopupCenter({
4505
- url: `${this.config.passportDomain}/transaction-confirmation`,
4506
- title: CONFIRMATION_WINDOW_TITLE,
4507
- width: popupOptions?.width || CONFIRMATION_WINDOW_WIDTH,
4508
- height: popupOptions?.height || CONFIRMATION_WINDOW_HEIGHT,
4509
- });
4510
- // https://stackoverflow.com/questions/9388380/capture-the-close-event-of-popup-window-in-javascript/48240128#48240128
4511
- const timer = setInterval(() => {
4512
- if (confirmationWindow.closed) {
4513
- clearInterval(timer);
4514
- window.removeEventListener('message', messageHandler);
4515
- resolve({ confirmed: false });
4516
- }
4517
- }, CONFIRMATION_WINDOW_CLOSED_POLLING_DURATION);
4518
- });
4452
+ loading(popupWindowSize) {
4453
+ this.confirmationScreen.loading(popupWindowSize);
4519
4454
  }
4520
- startGuardianTransaction(transactionId) {
4521
- return new Promise((resolve, reject) => {
4522
- const messageHandler = ({ data, origin }) => {
4523
- if (origin !== this.config.passportDomain
4524
- || data.eventType !== PASSPORT_EVENT_TYPE) {
4525
- return;
4526
- }
4527
- switch (data.messageType) {
4528
- case ReceiveMessage.CONFIRMATION_WINDOW_READY: {
4529
- break;
4530
- }
4531
- case ReceiveMessage.TRANSACTION_CONFIRMED: {
4532
- resolve({ confirmed: true });
4533
- break;
4534
- }
4535
- case ReceiveMessage.TRANSACTION_ERROR: {
4536
- reject(new Error('Transaction error'));
4537
- break;
4538
- }
4539
- default:
4540
- reject(new Error('Unsupported message type'));
4541
- }
4542
- };
4543
- window.addEventListener('message', messageHandler);
4544
- if (!this.confirmationWindow) {
4545
- resolve({ confirmed: false });
4546
- return;
4547
- }
4548
- // eslint-disable-next-line max-len
4549
- this.confirmationWindow.location.href = `${this.config.passportDomain}/transaction-confirmation/transaction.html?transactionId=${transactionId}&chainType=starkex`;
4550
- // https://stackoverflow.com/questions/9388380/capture-the-close-event-of-popup-window-in-javascript/48240128#48240128
4551
- const timer = setInterval(() => {
4552
- if (this.confirmationWindow?.closed) {
4553
- clearInterval(timer);
4554
- window.removeEventListener('message', messageHandler);
4555
- resolve({ confirmed: false });
4556
- }
4557
- }, CONFIRMATION_WINDOW_CLOSED_POLLING_DURATION);
4455
+ async validate({ payloadHash }) {
4456
+ const finallyFn = () => {
4457
+ this.confirmationScreen.closeWindow();
4458
+ };
4459
+ const transactionRes = await retryWithDelay(async () => this.transactionAPI.getTransactionByID({
4460
+ transactionID: payloadHash,
4461
+ chainType: 'starkex',
4462
+ }), { finallyFn });
4463
+ if (!transactionRes.data.id) {
4464
+ throw new Error("Transaction doesn't exists");
4465
+ }
4466
+ const evaluateStarkexRes = await this.transactionAPI.evaluateTransaction({
4467
+ id: payloadHash,
4468
+ transactionEvaluationRequest: {
4469
+ chainType: 'starkex',
4470
+ },
4558
4471
  });
4472
+ const { confirmationRequired } = evaluateStarkexRes.data;
4473
+ if (confirmationRequired) {
4474
+ const confirmationResult = await this.confirmationScreen.startGuardianTransaction(payloadHash, this.imxEtherAddress);
4475
+ if (!confirmationResult.confirmed) {
4476
+ throw new Error('Transaction rejected by user');
4477
+ }
4478
+ }
4479
+ else {
4480
+ this.confirmationScreen.closeWindow();
4481
+ }
4559
4482
  }
4560
- loading(popupOptions) {
4561
- this.confirmationWindow = openPopupCenter({
4562
- url: `${this.config.passportDomain}/transaction-confirmation/loading.html`,
4563
- title: CONFIRMATION_WINDOW_TITLE,
4564
- width: popupOptions?.width || CONFIRMATION_WINDOW_WIDTH,
4565
- height: popupOptions?.height || CONFIRMATION_WINDOW_HEIGHT,
4483
+ }
4484
+
4485
+ async function exchangeTransfer({ user, starkSigner, request, exchangesApi, }) {
4486
+ return withPassportError(async () => {
4487
+ const { ethAddress } = user.imx;
4488
+ const transferAmount = request.amount;
4489
+ const signableResult = await exchangesApi.getExchangeSignableTransfer({
4490
+ id: request.transactionID,
4491
+ getSignableTransferRequest: {
4492
+ sender: ethAddress,
4493
+ token: convertToSignableToken(request),
4494
+ amount: transferAmount,
4495
+ receiver: request.receiver,
4496
+ },
4566
4497
  });
4567
- }
4568
- closeWindow() {
4569
- this.confirmationWindow?.close();
4570
- }
4498
+ const starkAddress = await starkSigner.getAddress();
4499
+ const { payload_hash: payloadHash } = signableResult.data;
4500
+ const starkSignature = await starkSigner.signMessage(payloadHash);
4501
+ const transferSigningParams = {
4502
+ sender_stark_key: signableResult.data.sender_stark_key || starkAddress,
4503
+ sender_vault_id: signableResult.data.sender_vault_id,
4504
+ receiver_stark_key: signableResult.data.receiver_stark_key,
4505
+ receiver_vault_id: signableResult.data.receiver_vault_id,
4506
+ asset_id: signableResult.data.asset_id,
4507
+ amount: signableResult.data.amount,
4508
+ nonce: signableResult.data.nonce,
4509
+ expiration_timestamp: signableResult.data.expiration_timestamp,
4510
+ stark_signature: starkSignature,
4511
+ };
4512
+ const headers = {
4513
+ // eslint-disable-next-line @typescript-eslint/naming-convention
4514
+ Authorization: `Bearer ${user.accessToken}`,
4515
+ };
4516
+ const response = await exchangesApi.createExchangeTransfer({
4517
+ id: request.transactionID,
4518
+ createTransferRequest: transferSigningParams,
4519
+ }, { headers });
4520
+ return {
4521
+ sent_signature: response?.data.sent_signature,
4522
+ status: response?.data.status?.toString(),
4523
+ time: response?.data.time,
4524
+ transfer_id: response?.data.transfer_id,
4525
+ };
4526
+ }, PassportErrorType.EXCHANGE_TRANSFER_ERROR);
4571
4527
  }
4572
4528
 
4573
4529
  const ERC721$1 = 'ERC721';
4574
- async function createOrder({ starkSigner, user, request, ordersApi, confirmationScreen, }) {
4530
+ async function createOrder({ starkSigner, user, request, ordersApi, guardianClient, }) {
4575
4531
  return withPassportError(async () => {
4532
+ guardianClient.loading();
4576
4533
  const { ethAddress } = user.imx;
4577
4534
  const amountSell = request.sell.type === ERC721$1 ? '1' : request.sell.amount;
4578
4535
  const amountBuy = request.buy.type === ERC721$1 ? '1' : request.buy.amount;
4536
+ const headers = {
4537
+ // eslint-disable-next-line @typescript-eslint/naming-convention
4538
+ Authorization: `Bearer ${user.accessToken}`,
4539
+ };
4579
4540
  const getSignableOrderRequestV3 = {
4580
4541
  user: ethAddress,
4581
4542
  amount_buy: amountBuy,
@@ -4587,14 +4548,10 @@ async function createOrder({ starkSigner, user, request, ordersApi, confirmation
4587
4548
  };
4588
4549
  const getSignableOrderResponse = await ordersApi.getSignableOrder({
4589
4550
  getSignableOrderRequestV3,
4551
+ }, { headers });
4552
+ await guardianClient.validate({
4553
+ payloadHash: getSignableOrderResponse.data.payload_hash,
4590
4554
  });
4591
- const confirmationResult = await confirmationScreen.startTransaction(user.accessToken, {
4592
- transactionType: TransactionTypes.createOrder,
4593
- transactionData: getSignableOrderRequestV3,
4594
- });
4595
- if (!confirmationResult.confirmed) {
4596
- throw new Error('Transaction rejected by user');
4597
- }
4598
4555
  const { payload_hash: payloadHash } = getSignableOrderResponse.data;
4599
4556
  const starkSignature = await starkSigner.signMessage(payloadHash);
4600
4557
  const signableResultData = getSignableOrderResponse.data;
@@ -4614,11 +4571,7 @@ async function createOrder({ starkSigner, user, request, ordersApi, confirmation
4614
4571
  vault_id_sell: signableResultData.vault_id_sell,
4615
4572
  },
4616
4573
  };
4617
- const headers = {
4618
- // eslint-disable-next-line @typescript-eslint/naming-convention
4619
- Authorization: `Bearer ${user.accessToken}`,
4620
- };
4621
- const createOrderResponse = await ordersApi.createOrder(orderParams, {
4574
+ const createOrderResponse = await ordersApi.createOrderV3(orderParams, {
4622
4575
  headers,
4623
4576
  });
4624
4577
  return {
@@ -4626,28 +4579,25 @@ async function createOrder({ starkSigner, user, request, ordersApi, confirmation
4626
4579
  };
4627
4580
  }, PassportErrorType.CREATE_ORDER_ERROR);
4628
4581
  }
4629
- async function cancelOrder({ user, starkSigner, request, ordersApi, confirmationScreen, }) {
4582
+ async function cancelOrder({ user, starkSigner, request, ordersApi, guardianClient, }) {
4630
4583
  return withPassportError(async () => {
4584
+ guardianClient.loading();
4631
4585
  const getSignableCancelOrderRequest = {
4632
4586
  order_id: request.order_id,
4633
4587
  };
4634
- const getSignableCancelOrderResponse = await ordersApi.getSignableCancelOrder({
4635
- getSignableCancelOrderRequest,
4636
- });
4637
- const confirmationResult = await confirmationScreen.startTransaction(user.accessToken, {
4638
- transactionType: TransactionTypes.cancelOrder,
4639
- transactionData: getSignableCancelOrderRequest,
4640
- });
4641
- if (!confirmationResult.confirmed) {
4642
- throw new Error('Transaction rejected by user');
4643
- }
4644
- const { payload_hash: payloadHash } = getSignableCancelOrderResponse.data;
4645
- const starkSignature = await starkSigner.signMessage(payloadHash);
4646
4588
  const headers = {
4647
4589
  // eslint-disable-next-line @typescript-eslint/naming-convention
4648
4590
  Authorization: `Bearer ${user.accessToken}`,
4649
4591
  };
4650
- const cancelOrderResponse = await ordersApi.cancelOrder({
4592
+ const getSignableCancelOrderResponse = await ordersApi.getSignableCancelOrderV3({
4593
+ getSignableCancelOrderRequest,
4594
+ }, { headers });
4595
+ await guardianClient.validate({
4596
+ payloadHash: getSignableCancelOrderResponse.data.payload_hash,
4597
+ });
4598
+ const { payload_hash: payloadHash } = getSignableCancelOrderResponse.data;
4599
+ const starkSignature = await starkSigner.signMessage(payloadHash);
4600
+ const cancelOrderResponse = await ordersApi.cancelOrderV3({
4651
4601
  id: request.order_id.toString(),
4652
4602
  cancelOrderRequest: {
4653
4603
  order_id: request.order_id,
@@ -4687,8 +4637,9 @@ async function registerPassport({ ethSigner, starkSigner, usersApi }, authorizat
4687
4637
  }, PassportErrorType.USER_REGISTRATION_ERROR);
4688
4638
  }
4689
4639
 
4690
- async function createTrade({ request, tradesApi, user, starkSigner, confirmationScreen, }) {
4640
+ async function createTrade({ request, tradesApi, user, starkSigner, guardianClient, }) {
4691
4641
  return withPassportError(async () => {
4642
+ guardianClient.loading();
4692
4643
  const { ethAddress } = user.imx;
4693
4644
  const getSignableTradeRequest = {
4694
4645
  expiration_timestamp: request.expiration_timestamp,
@@ -4696,16 +4647,14 @@ async function createTrade({ request, tradesApi, user, starkSigner, confirmation
4696
4647
  order_id: request.order_id,
4697
4648
  user: ethAddress,
4698
4649
  };
4650
+ // eslint-disable-next-line @typescript-eslint/naming-convention
4651
+ const headers = { Authorization: `Bearer ${user.accessToken}` };
4699
4652
  const getSignableTradeResponse = await tradesApi.getSignableTrade({
4700
4653
  getSignableTradeRequest,
4654
+ }, { headers });
4655
+ await guardianClient.validate({
4656
+ payloadHash: getSignableTradeResponse.data.payload_hash,
4701
4657
  });
4702
- const confirmationResult = await confirmationScreen.startTransaction(user.accessToken, {
4703
- transactionType: TransactionTypes.createTrade,
4704
- transactionData: getSignableTradeRequest,
4705
- });
4706
- if (!confirmationResult.confirmed) {
4707
- throw new Error('Transaction rejected by user');
4708
- }
4709
4658
  const { payload_hash: payloadHash } = getSignableTradeResponse.data;
4710
4659
  const starkSignature = await starkSigner.signMessage(payloadHash);
4711
4660
  const { data: signableResultData } = getSignableTradeResponse;
@@ -4727,8 +4676,6 @@ async function createTrade({ request, tradesApi, user, starkSigner, confirmation
4727
4676
  vault_id_sell: signableResultData.vault_id_sell,
4728
4677
  },
4729
4678
  };
4730
- // eslint-disable-next-line @typescript-eslint/naming-convention
4731
- const headers = { Authorization: `Bearer ${user.accessToken}` };
4732
4679
  const { data: createTradeResponse } = await tradesApi.createTradeV3(tradeParams, {
4733
4680
  headers,
4734
4681
  });
@@ -4736,67 +4683,10 @@ async function createTrade({ request, tradesApi, user, starkSigner, confirmation
4736
4683
  }, PassportErrorType.CREATE_TRADE_ERROR);
4737
4684
  }
4738
4685
 
4739
- const POLL_INTERVAL = 1 * 1000; // every 1 second
4740
- const MAX_RETRIES = 3;
4741
- const wait = (ms) => new Promise((resolve) => {
4742
- setTimeout(() => resolve(), ms);
4743
- });
4744
- const retryWithDelay = async (fn, options) => {
4745
- const { retries = MAX_RETRIES, interval = POLL_INTERVAL, finalErr = Error('Retry failed'), finallyFn = () => { }, } = options || {};
4746
- try {
4747
- return await fn();
4748
- }
4749
- catch (err) {
4750
- if (retries <= 0) {
4751
- return Promise.reject(finalErr);
4752
- }
4753
- await wait(interval);
4754
- return retryWithDelay(fn, { retries: retries - 1, finalErr, finallyFn });
4755
- }
4756
- finally {
4757
- if (retries <= 0) {
4758
- finallyFn();
4759
- }
4760
- }
4761
- };
4762
-
4763
4686
  const ERC721 = 'ERC721';
4764
- const transferWithGuardian = async ({ accessToken, imxPublicApiDomain, payloadHash, confirmationScreen, }) => {
4765
- confirmationScreen.loading();
4766
- const transactionAPI = new TransactionsApi(new Configuration({
4767
- accessToken,
4768
- basePath: imxPublicApiDomain,
4769
- }));
4770
- const starkExTransactionApi = new StarkexTransactionsApi(new Configuration({
4771
- accessToken,
4772
- basePath: imxPublicApiDomain,
4773
- }));
4774
- const finallyFn = () => {
4775
- confirmationScreen.closeWindow();
4776
- };
4777
- const transactionRes = await retryWithDelay(async () => transactionAPI.getTransactionByID({
4778
- transactionID: payloadHash,
4779
- chainType: 'starkex',
4780
- }), { finallyFn });
4781
- if (!transactionRes.data.id) {
4782
- throw new Error("Transaction doesn't exists");
4783
- }
4784
- const evaluateStarkexRes = await starkExTransactionApi.evaluateStarkexTransaction({
4785
- payloadHash,
4786
- });
4787
- const { confirmationRequired } = evaluateStarkexRes.data;
4788
- if (confirmationRequired) {
4789
- const confirmationResult = await confirmationScreen.startGuardianTransaction(payloadHash);
4790
- if (!confirmationResult.confirmed) {
4791
- throw new Error('Transaction rejected by user');
4792
- }
4793
- }
4794
- else {
4795
- confirmationScreen.closeWindow();
4796
- }
4797
- };
4798
- async function transfer({ request, transfersApi, starkSigner, user, imxPublicApiDomain, confirmationScreen, }) {
4687
+ async function transfer({ request, transfersApi, starkSigner, user, guardianClient, }) {
4799
4688
  return withPassportError(async () => {
4689
+ guardianClient.loading();
4800
4690
  const transferAmount = request.type === ERC721 ? '1' : request.amount;
4801
4691
  const getSignableTransferRequest = {
4802
4692
  sender: user.imx.ethAddress,
@@ -4810,11 +4700,8 @@ async function transfer({ request, transfersApi, starkSigner, user, imxPublicApi
4810
4700
  const signableResult = await transfersApi.getSignableTransferV1({
4811
4701
  getSignableTransferRequest,
4812
4702
  }, { headers });
4813
- await transferWithGuardian({
4814
- imxPublicApiDomain,
4815
- accessToken: user.accessToken,
4703
+ await guardianClient.validate({
4816
4704
  payloadHash: signableResult.data.payload_hash,
4817
- confirmationScreen,
4818
4705
  });
4819
4706
  const signableResultData = signableResult.data;
4820
4707
  const { payload_hash: payloadHash } = signableResultData;
@@ -4843,8 +4730,10 @@ async function transfer({ request, transfersApi, starkSigner, user, imxPublicApi
4843
4730
  };
4844
4731
  }, PassportErrorType.TRANSFER_ERROR);
4845
4732
  }
4846
- async function batchNftTransfer({ user, starkSigner, request, transfersApi, confirmationScreen, }) {
4733
+ async function batchNftTransfer({ user, starkSigner, request, transfersApi, guardianClient, }) {
4847
4734
  return withPassportError(async () => {
4735
+ const popupWindowSize = { width: 480, height: 784 };
4736
+ guardianClient.loading(popupWindowSize);
4848
4737
  const { ethAddress } = user.imx;
4849
4738
  const signableRequests = request.map((nftTransfer) => ({
4850
4739
  amount: '1',
@@ -4859,17 +4748,16 @@ async function batchNftTransfer({ user, starkSigner, request, transfersApi, conf
4859
4748
  sender_ether_key: ethAddress,
4860
4749
  signable_requests: signableRequests,
4861
4750
  };
4751
+ const headers = {
4752
+ // eslint-disable-next-line @typescript-eslint/naming-convention
4753
+ Authorization: `Bearer ${user.accessToken}`,
4754
+ };
4862
4755
  const signableResult = await transfersApi.getSignableTransfer({
4863
4756
  getSignableTransferRequestV2,
4757
+ }, { headers });
4758
+ await guardianClient.validate({
4759
+ payloadHash: signableResult.data.signable_responses[0]?.payload_hash,
4864
4760
  });
4865
- const popupWindowSize = { width: 480, height: 784 };
4866
- const confirmationResult = await confirmationScreen.startTransaction(user.accessToken, {
4867
- transactionType: TransactionTypes.createBatchTransfer,
4868
- transactionData: getSignableTransferRequestV2,
4869
- }, popupWindowSize);
4870
- if (!confirmationResult.confirmed) {
4871
- throw new Error('Transaction rejected by user');
4872
- }
4873
4761
  const requests = await Promise.all(signableResult.data.signable_responses.map(async (resp) => {
4874
4762
  const starkSignature = await starkSigner.signMessage(resp.payload_hash);
4875
4763
  return {
@@ -4887,10 +4775,6 @@ async function batchNftTransfer({ user, starkSigner, request, transfersApi, conf
4887
4775
  sender_stark_key: signableResult.data.sender_stark_key,
4888
4776
  requests,
4889
4777
  };
4890
- const headers = {
4891
- // eslint-disable-next-line @typescript-eslint/naming-convention
4892
- Authorization: `Bearer ${user.accessToken}`,
4893
- };
4894
4778
  const response = await transfersApi.createTransfer({
4895
4779
  createTransferRequestV2: transferSigningParams,
4896
4780
  }, { headers });
@@ -4905,13 +4789,18 @@ class PassportImxProvider {
4905
4789
  starkSigner;
4906
4790
  immutableXClient;
4907
4791
  confirmationScreen;
4908
- imxPublicApiDomain;
4792
+ guardianClient;
4909
4793
  constructor({ user, starkSigner, immutableXClient, imxPublicApiDomain, confirmationScreen, }) {
4910
4794
  this.user = user;
4911
4795
  this.starkSigner = starkSigner;
4912
4796
  this.immutableXClient = immutableXClient;
4913
- this.imxPublicApiDomain = imxPublicApiDomain;
4914
4797
  this.confirmationScreen = confirmationScreen;
4798
+ this.guardianClient = new GuardianClient({
4799
+ imxPublicApiDomain,
4800
+ accessToken: user.accessToken,
4801
+ confirmationScreen,
4802
+ imxEtherAddress: user.imx.ethAddress,
4803
+ });
4915
4804
  }
4916
4805
  async transfer(request) {
4917
4806
  return transfer({
@@ -4919,8 +4808,7 @@ class PassportImxProvider {
4919
4808
  user: this.user,
4920
4809
  starkSigner: this.starkSigner,
4921
4810
  transfersApi: this.immutableXClient.transfersApi,
4922
- confirmationScreen: this.confirmationScreen,
4923
- imxPublicApiDomain: this.imxPublicApiDomain,
4811
+ guardianClient: this.guardianClient,
4924
4812
  });
4925
4813
  }
4926
4814
  // TODO: Remove once implemented
@@ -4939,7 +4827,7 @@ class PassportImxProvider {
4939
4827
  user: this.user,
4940
4828
  starkSigner: this.starkSigner,
4941
4829
  ordersApi: this.immutableXClient.ordersApi,
4942
- confirmationScreen: this.confirmationScreen,
4830
+ guardianClient: this.guardianClient,
4943
4831
  });
4944
4832
  }
4945
4833
  cancelOrder(request) {
@@ -4948,7 +4836,7 @@ class PassportImxProvider {
4948
4836
  user: this.user,
4949
4837
  starkSigner: this.starkSigner,
4950
4838
  ordersApi: this.immutableXClient.ordersApi,
4951
- confirmationScreen: this.confirmationScreen,
4839
+ guardianClient: this.guardianClient,
4952
4840
  });
4953
4841
  }
4954
4842
  createTrade(request) {
@@ -4957,7 +4845,7 @@ class PassportImxProvider {
4957
4845
  user: this.user,
4958
4846
  starkSigner: this.starkSigner,
4959
4847
  tradesApi: this.immutableXClient.tradesApi,
4960
- confirmationScreen: this.confirmationScreen,
4848
+ guardianClient: this.guardianClient,
4961
4849
  });
4962
4850
  }
4963
4851
  batchNftTransfer(request) {
@@ -4966,7 +4854,7 @@ class PassportImxProvider {
4966
4854
  user: this.user,
4967
4855
  starkSigner: this.starkSigner,
4968
4856
  transfersApi: this.immutableXClient.transfersApi,
4969
- confirmationScreen: this.confirmationScreen,
4857
+ guardianClient: this.guardianClient,
4970
4858
  });
4971
4859
  }
4972
4860
  exchangeTransfer(request) {
@@ -5149,6 +5037,159 @@ class PassportConfiguration {
5149
5037
  }
5150
5038
  }
5151
5039
 
5040
+ var ReceiveMessage;
5041
+ (function (ReceiveMessage) {
5042
+ ReceiveMessage["CONFIRMATION_WINDOW_READY"] = "confirmation_window_ready";
5043
+ ReceiveMessage["TRANSACTION_CONFIRMED"] = "transaction_confirmed";
5044
+ ReceiveMessage["TRANSACTION_ERROR"] = "transaction_error";
5045
+ })(ReceiveMessage || (ReceiveMessage = {}));
5046
+ var SendMessage;
5047
+ (function (SendMessage) {
5048
+ SendMessage["TRANSACTION_START"] = "transaction_start";
5049
+ })(SendMessage || (SendMessage = {}));
5050
+ var TransactionTypes;
5051
+ (function (TransactionTypes) {
5052
+ TransactionTypes["cancelOrder"] = "delete:v1/orders";
5053
+ TransactionTypes["createOrder"] = "post:v1/orders";
5054
+ TransactionTypes["createTrade"] = "post:v1/trades";
5055
+ TransactionTypes["createTransfer"] = "post:v1/transfers";
5056
+ TransactionTypes["createBatchTransfer"] = "post:v2/transfers";
5057
+ })(TransactionTypes || (TransactionTypes = {}));
5058
+ const PASSPORT_EVENT_TYPE = 'imx_passport_confirmation';
5059
+
5060
+ const openPopupCenter = ({ url, title, width, height, }) => {
5061
+ const left = Math.max(0, Math.round(window.screenX + (window.outerWidth - width) / 2));
5062
+ const top = Math.max(0, Math.round(window.screenY + (window.outerHeight - height) / 2));
5063
+ const newWindow = window.open(url, title, `
5064
+ scrollbars=yes,
5065
+ width=${width},
5066
+ height=${height},
5067
+ top=${top},
5068
+ left=${left}
5069
+ `);
5070
+ if (!newWindow) {
5071
+ throw new Error('Failed to open confirmation screen');
5072
+ }
5073
+ newWindow.focus();
5074
+ return newWindow;
5075
+ };
5076
+
5077
+ const CONFIRMATION_WINDOW_TITLE = 'Confirm this transaction';
5078
+ const CONFIRMATION_WINDOW_HEIGHT = 380;
5079
+ const CONFIRMATION_WINDOW_WIDTH = 480;
5080
+ const CONFIRMATION_WINDOW_CLOSED_POLLING_DURATION = 1000;
5081
+ class ConfirmationScreen {
5082
+ config;
5083
+ confirmationWindow;
5084
+ constructor(config) {
5085
+ this.config = config;
5086
+ }
5087
+ postMessage(destinationWindow, accessToken, message) {
5088
+ destinationWindow.postMessage({
5089
+ eventType: PASSPORT_EVENT_TYPE,
5090
+ accessToken,
5091
+ ...message,
5092
+ }, this.config.passportDomain);
5093
+ }
5094
+ startTransaction(accessToken, transaction, popupOptions) {
5095
+ return new Promise((resolve, reject) => {
5096
+ const messageHandler = ({ data, origin }) => {
5097
+ if (origin !== this.config.passportDomain
5098
+ || data.eventType !== PASSPORT_EVENT_TYPE) {
5099
+ return;
5100
+ }
5101
+ switch (data.messageType) {
5102
+ case ReceiveMessage.CONFIRMATION_WINDOW_READY: {
5103
+ // TODO: remove once fixed
5104
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
5105
+ this.postMessage(confirmationWindow, accessToken, {
5106
+ messageType: SendMessage.TRANSACTION_START,
5107
+ messageData: transaction,
5108
+ });
5109
+ break;
5110
+ }
5111
+ case ReceiveMessage.TRANSACTION_CONFIRMED: {
5112
+ resolve({ confirmed: true });
5113
+ break;
5114
+ }
5115
+ case ReceiveMessage.TRANSACTION_ERROR: {
5116
+ reject(new Error('Transaction error'));
5117
+ break;
5118
+ }
5119
+ default:
5120
+ reject(new Error('Unsupported message type'));
5121
+ }
5122
+ };
5123
+ window.addEventListener('message', messageHandler);
5124
+ const confirmationWindow = openPopupCenter({
5125
+ url: `${this.config.passportDomain}/transaction-confirmation`,
5126
+ title: CONFIRMATION_WINDOW_TITLE,
5127
+ width: popupOptions?.width || CONFIRMATION_WINDOW_WIDTH,
5128
+ height: popupOptions?.height || CONFIRMATION_WINDOW_HEIGHT,
5129
+ });
5130
+ // https://stackoverflow.com/questions/9388380/capture-the-close-event-of-popup-window-in-javascript/48240128#48240128
5131
+ const timer = setInterval(() => {
5132
+ if (confirmationWindow.closed) {
5133
+ clearInterval(timer);
5134
+ window.removeEventListener('message', messageHandler);
5135
+ resolve({ confirmed: false });
5136
+ }
5137
+ }, CONFIRMATION_WINDOW_CLOSED_POLLING_DURATION);
5138
+ });
5139
+ }
5140
+ startGuardianTransaction(transactionId, imxEtherAddress) {
5141
+ return new Promise((resolve, reject) => {
5142
+ const messageHandler = ({ data, origin }) => {
5143
+ if (origin !== this.config.passportDomain
5144
+ || data.eventType !== PASSPORT_EVENT_TYPE) {
5145
+ return;
5146
+ }
5147
+ switch (data.messageType) {
5148
+ case ReceiveMessage.CONFIRMATION_WINDOW_READY: {
5149
+ break;
5150
+ }
5151
+ case ReceiveMessage.TRANSACTION_CONFIRMED: {
5152
+ resolve({ confirmed: true });
5153
+ break;
5154
+ }
5155
+ case ReceiveMessage.TRANSACTION_ERROR: {
5156
+ reject(new Error('Transaction error'));
5157
+ break;
5158
+ }
5159
+ default:
5160
+ reject(new Error('Unsupported message type'));
5161
+ }
5162
+ };
5163
+ window.addEventListener('message', messageHandler);
5164
+ if (!this.confirmationWindow) {
5165
+ resolve({ confirmed: false });
5166
+ return;
5167
+ }
5168
+ // eslint-disable-next-line max-len
5169
+ this.confirmationWindow.location.href = `${this.config.passportDomain}/transaction-confirmation/transaction.html?transactionId=${transactionId}&imxEtherAddress=${imxEtherAddress}&chainType=starkex`;
5170
+ // https://stackoverflow.com/questions/9388380/capture-the-close-event-of-popup-window-in-javascript/48240128#48240128
5171
+ const timer = setInterval(() => {
5172
+ if (this.confirmationWindow?.closed) {
5173
+ clearInterval(timer);
5174
+ window.removeEventListener('message', messageHandler);
5175
+ resolve({ confirmed: false });
5176
+ }
5177
+ }, CONFIRMATION_WINDOW_CLOSED_POLLING_DURATION);
5178
+ });
5179
+ }
5180
+ loading(popupOptions) {
5181
+ this.confirmationWindow = openPopupCenter({
5182
+ url: `${this.config.passportDomain}/transaction-confirmation/loading.html`,
5183
+ title: CONFIRMATION_WINDOW_TITLE,
5184
+ width: popupOptions?.width || CONFIRMATION_WINDOW_WIDTH,
5185
+ height: popupOptions?.height || CONFIRMATION_WINDOW_HEIGHT,
5186
+ });
5187
+ }
5188
+ closeWindow() {
5189
+ this.confirmationWindow?.close();
5190
+ }
5191
+ }
5192
+
5152
5193
  class Passport {
5153
5194
  authManager;
5154
5195
  config;