@imtbl/sdk 0.17.5 → 0.18.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.
package/dist/index.cjs CHANGED
@@ -2724,7 +2724,7 @@ class MultiRollupApiClients {
2724
2724
  }
2725
2725
 
2726
2726
  // eslint-disable-next-line @typescript-eslint/naming-convention
2727
- const defaultHeaders$1 = { 'x-sdk-version': 'ts-immutable-sdk-0.17.5' };
2727
+ const defaultHeaders$1 = { 'x-sdk-version': 'ts-immutable-sdk-0.18.0' };
2728
2728
  const createConfig = ({ basePath, headers, }) => {
2729
2729
  if (!basePath.trim()) {
2730
2730
  throw Error('basePath can not be empty');
@@ -2784,7 +2784,7 @@ class APIError extends Error {
2784
2784
 
2785
2785
  /* eslint-disable implicit-arrow-linebreak */
2786
2786
  const defaultHeaders = {
2787
- sdkVersion: 'ts-immutable-sdk-multi-rollup-api-client-0.17.5',
2787
+ sdkVersion: 'ts-immutable-sdk-multi-rollup-api-client-0.18.0',
2788
2788
  };
2789
2789
  /**
2790
2790
  * createAPIConfiguration to create a custom Configuration
@@ -3070,7 +3070,7 @@ const createImmutableXConfiguration = ({ basePath, chainID, coreContractAddress,
3070
3070
  chainID,
3071
3071
  coreContractAddress,
3072
3072
  registrationContractAddress,
3073
- sdkVersion: 'ts-immutable-sdk-0.17.5',
3073
+ sdkVersion: 'ts-immutable-sdk-0.18.0',
3074
3074
  });
3075
3075
  /**
3076
3076
  * Sets `sdkVersion` at the time of build
@@ -6802,6 +6802,8 @@ var globalAxios = axios;
6802
6802
  * https://openapi-generator.tech
6803
6803
  * Do not edit the class manually.
6804
6804
  */
6805
+ // Some imports not used depending on template conditions
6806
+ // @ts-ignore
6805
6807
  const BASE_PATH = "https://guardian.sandbox.imtbl.com".replace(/\/+$/, "");
6806
6808
  /**
6807
6809
  *
@@ -6829,10 +6831,10 @@ class BaseAPI {
6829
6831
  */
6830
6832
  class RequiredError extends Error {
6831
6833
  field;
6834
+ name = "RequiredError";
6832
6835
  constructor(field, msg) {
6833
6836
  super(msg);
6834
6837
  this.field = field;
6835
- this.name = "RequiredError";
6836
6838
  }
6837
6839
  }
6838
6840
 
@@ -6877,8 +6879,6 @@ const setBearerAuthToObject = async function (object, configuration) {
6877
6879
  }
6878
6880
  };
6879
6881
  function setFlattenedQueryParams(urlSearchParams, parameter, key = "") {
6880
- if (parameter == null)
6881
- return;
6882
6882
  if (typeof parameter === "object") {
6883
6883
  if (Array.isArray(parameter)) {
6884
6884
  parameter.forEach(item => setFlattenedQueryParams(urlSearchParams, item, key));
@@ -6936,6 +6936,208 @@ const createRequestFunction = function (axiosArgs, globalAxios, BASE_PATH, confi
6936
6936
  };
6937
6937
  };
6938
6938
 
6939
+ /* tslint:disable */
6940
+ /* eslint-disable */
6941
+ /**
6942
+ * Guardian
6943
+ * Guardian API
6944
+ *
6945
+ * The version of the OpenAPI document: 1.0.0
6946
+ * Contact: support@immutable.com
6947
+ *
6948
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
6949
+ * https://openapi-generator.tech
6950
+ * Do not edit the class manually.
6951
+ */
6952
+ /**
6953
+ * MessagesApi - axios parameter creator
6954
+ * @export
6955
+ */
6956
+ const MessagesApiAxiosParamCreator = function (configuration) {
6957
+ return {
6958
+ /**
6959
+ * Approve a pending evm message
6960
+ * @summary Approve a pending evm message
6961
+ * @param {string} messageID id for the message
6962
+ * @param {*} [options] Override http request option.
6963
+ * @throws {RequiredError}
6964
+ */
6965
+ approvePendingMessage: async (messageID, options = {}) => {
6966
+ // verify required parameter 'messageID' is not null or undefined
6967
+ assertParamExists('approvePendingMessage', 'messageID', messageID);
6968
+ const localVarPath = `/guardian/v1/messages/{messageID}/approve`
6969
+ .replace(`{${"messageID"}}`, encodeURIComponent(String(messageID)));
6970
+ // use dummy base URL string because the URL constructor only accepts absolute URLs.
6971
+ const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
6972
+ let baseOptions;
6973
+ if (configuration) {
6974
+ baseOptions = configuration.baseOptions;
6975
+ }
6976
+ const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options };
6977
+ const localVarHeaderParameter = {};
6978
+ const localVarQueryParameter = {};
6979
+ // authentication BearerAuth required
6980
+ // http bearer authentication required
6981
+ await setBearerAuthToObject(localVarHeaderParameter, configuration);
6982
+ setSearchParams(localVarUrlObj, localVarQueryParameter);
6983
+ let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
6984
+ localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers };
6985
+ return {
6986
+ url: toPathString(localVarUrlObj),
6987
+ options: localVarRequestOptions,
6988
+ };
6989
+ },
6990
+ /**
6991
+ * Check if a given message is valid for EVM
6992
+ * @summary Evaluate an evm message to sign
6993
+ * @param {MessageEvaluationRequest} messageEvaluationRequest Specifies the kind of transaction
6994
+ * @param {*} [options] Override http request option.
6995
+ * @throws {RequiredError}
6996
+ */
6997
+ evaluateMessage: async (messageEvaluationRequest, options = {}) => {
6998
+ // verify required parameter 'messageEvaluationRequest' is not null or undefined
6999
+ assertParamExists('evaluateMessage', 'messageEvaluationRequest', messageEvaluationRequest);
7000
+ const localVarPath = `/guardian/v1/messages/evaluate`;
7001
+ // use dummy base URL string because the URL constructor only accepts absolute URLs.
7002
+ const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
7003
+ let baseOptions;
7004
+ if (configuration) {
7005
+ baseOptions = configuration.baseOptions;
7006
+ }
7007
+ const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options };
7008
+ const localVarHeaderParameter = {};
7009
+ const localVarQueryParameter = {};
7010
+ // authentication BearerAuth required
7011
+ // http bearer authentication required
7012
+ await setBearerAuthToObject(localVarHeaderParameter, configuration);
7013
+ localVarHeaderParameter['Content-Type'] = 'application/json';
7014
+ setSearchParams(localVarUrlObj, localVarQueryParameter);
7015
+ let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
7016
+ localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers };
7017
+ localVarRequestOptions.data = serializeDataIfNeeded(messageEvaluationRequest, localVarRequestOptions, configuration);
7018
+ return {
7019
+ url: toPathString(localVarUrlObj),
7020
+ options: localVarRequestOptions,
7021
+ };
7022
+ },
7023
+ /**
7024
+ * Get an evm message by id
7025
+ * @summary Info for a specific evm message
7026
+ * @param {string} messageID The id of the evm message
7027
+ * @param {*} [options] Override http request option.
7028
+ * @throws {RequiredError}
7029
+ */
7030
+ getMessageByID: async (messageID, options = {}) => {
7031
+ // verify required parameter 'messageID' is not null or undefined
7032
+ assertParamExists('getMessageByID', 'messageID', messageID);
7033
+ const localVarPath = `/guardian/v1/messages/{messageID}`
7034
+ .replace(`{${"messageID"}}`, encodeURIComponent(String(messageID)));
7035
+ // use dummy base URL string because the URL constructor only accepts absolute URLs.
7036
+ const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
7037
+ let baseOptions;
7038
+ if (configuration) {
7039
+ baseOptions = configuration.baseOptions;
7040
+ }
7041
+ const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options };
7042
+ const localVarHeaderParameter = {};
7043
+ const localVarQueryParameter = {};
7044
+ // authentication BearerAuth required
7045
+ // http bearer authentication required
7046
+ await setBearerAuthToObject(localVarHeaderParameter, configuration);
7047
+ setSearchParams(localVarUrlObj, localVarQueryParameter);
7048
+ let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
7049
+ localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers };
7050
+ return {
7051
+ url: toPathString(localVarUrlObj),
7052
+ options: localVarRequestOptions,
7053
+ };
7054
+ },
7055
+ };
7056
+ };
7057
+ /**
7058
+ * MessagesApi - functional programming interface
7059
+ * @export
7060
+ */
7061
+ const MessagesApiFp = function (configuration) {
7062
+ const localVarAxiosParamCreator = MessagesApiAxiosParamCreator(configuration);
7063
+ return {
7064
+ /**
7065
+ * Approve a pending evm message
7066
+ * @summary Approve a pending evm message
7067
+ * @param {string} messageID id for the message
7068
+ * @param {*} [options] Override http request option.
7069
+ * @throws {RequiredError}
7070
+ */
7071
+ async approvePendingMessage(messageID, options) {
7072
+ const localVarAxiosArgs = await localVarAxiosParamCreator.approvePendingMessage(messageID, options);
7073
+ return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
7074
+ },
7075
+ /**
7076
+ * Check if a given message is valid for EVM
7077
+ * @summary Evaluate an evm message to sign
7078
+ * @param {MessageEvaluationRequest} messageEvaluationRequest Specifies the kind of transaction
7079
+ * @param {*} [options] Override http request option.
7080
+ * @throws {RequiredError}
7081
+ */
7082
+ async evaluateMessage(messageEvaluationRequest, options) {
7083
+ const localVarAxiosArgs = await localVarAxiosParamCreator.evaluateMessage(messageEvaluationRequest, options);
7084
+ return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
7085
+ },
7086
+ /**
7087
+ * Get an evm message by id
7088
+ * @summary Info for a specific evm message
7089
+ * @param {string} messageID The id of the evm message
7090
+ * @param {*} [options] Override http request option.
7091
+ * @throws {RequiredError}
7092
+ */
7093
+ async getMessageByID(messageID, options) {
7094
+ const localVarAxiosArgs = await localVarAxiosParamCreator.getMessageByID(messageID, options);
7095
+ return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
7096
+ },
7097
+ };
7098
+ };
7099
+ /**
7100
+ * MessagesApi - object-oriented interface
7101
+ * @export
7102
+ * @class MessagesApi
7103
+ * @extends {BaseAPI}
7104
+ */
7105
+ class MessagesApi extends BaseAPI {
7106
+ /**
7107
+ * Approve a pending evm message
7108
+ * @summary Approve a pending evm message
7109
+ * @param {MessagesApiApprovePendingMessageRequest} requestParameters Request parameters.
7110
+ * @param {*} [options] Override http request option.
7111
+ * @throws {RequiredError}
7112
+ * @memberof MessagesApi
7113
+ */
7114
+ approvePendingMessage(requestParameters, options) {
7115
+ return MessagesApiFp(this.configuration).approvePendingMessage(requestParameters.messageID, options).then((request) => request(this.axios, this.basePath));
7116
+ }
7117
+ /**
7118
+ * Check if a given message is valid for EVM
7119
+ * @summary Evaluate an evm message to sign
7120
+ * @param {MessagesApiEvaluateMessageRequest} requestParameters Request parameters.
7121
+ * @param {*} [options] Override http request option.
7122
+ * @throws {RequiredError}
7123
+ * @memberof MessagesApi
7124
+ */
7125
+ evaluateMessage(requestParameters, options) {
7126
+ return MessagesApiFp(this.configuration).evaluateMessage(requestParameters.messageEvaluationRequest, options).then((request) => request(this.axios, this.basePath));
7127
+ }
7128
+ /**
7129
+ * Get an evm message by id
7130
+ * @summary Info for a specific evm message
7131
+ * @param {MessagesApiGetMessageByIDRequest} requestParameters Request parameters.
7132
+ * @param {*} [options] Override http request option.
7133
+ * @throws {RequiredError}
7134
+ * @memberof MessagesApi
7135
+ */
7136
+ getMessageByID(requestParameters, options) {
7137
+ return MessagesApiFp(this.configuration).getMessageByID(requestParameters.messageID, options).then((request) => request(this.axios, this.basePath));
7138
+ }
7139
+ }
7140
+
6939
7141
  /* tslint:disable */
6940
7142
  /* eslint-disable */
6941
7143
  /**
@@ -6959,7 +7161,7 @@ const TransactionsApiAxiosParamCreator = function (configuration) {
6959
7161
  * Approve a pending transaction
6960
7162
  * @summary Approve a pending transaction given chain
6961
7163
  * @param {string} payloadHash Hash for the payload
6962
- * @param {TransactionApprovalRequest} transactionApprovalRequest request body for approving a pending transactio
7164
+ * @param {TransactionApprovalRequest} transactionApprovalRequest request body for approving a pending transaction
6963
7165
  * @param {*} [options] Override http request option.
6964
7166
  * @throws {RequiredError}
6965
7167
  */
@@ -7084,7 +7286,7 @@ const TransactionsApiFp = function (configuration) {
7084
7286
  * Approve a pending transaction
7085
7287
  * @summary Approve a pending transaction given chain
7086
7288
  * @param {string} payloadHash Hash for the payload
7087
- * @param {TransactionApprovalRequest} transactionApprovalRequest request body for approving a pending transactio
7289
+ * @param {TransactionApprovalRequest} transactionApprovalRequest request body for approving a pending transaction
7088
7290
  * @param {*} [options] Override http request option.
7089
7291
  * @throws {RequiredError}
7090
7292
  */
@@ -7850,18 +8052,18 @@ const transformGuardianTransactions = (txs) => {
7850
8052
  };
7851
8053
  class GuardianClient {
7852
8054
  transactionAPI;
8055
+ messageAPI;
7853
8056
  confirmationScreen;
7854
8057
  // TODO: ID-977, make this rollup agnostic
7855
8058
  imxEtherAddress;
7856
8059
  crossSdkBridgeEnabled;
7857
8060
  constructor({ accessToken, confirmationScreen, imxEtherAddress, config, }) {
8061
+ const guardianConfiguration = new Configuration({ accessToken, basePath: config.imxPublicApiDomain });
7858
8062
  this.confirmationScreen = confirmationScreen;
7859
- this.transactionAPI = new TransactionsApi(new Configuration({
7860
- accessToken,
7861
- basePath: config.imxPublicApiDomain,
7862
- }));
8063
+ this.transactionAPI = new TransactionsApi(new Configuration(guardianConfiguration));
7863
8064
  this.imxEtherAddress = imxEtherAddress;
7864
8065
  this.crossSdkBridgeEnabled = config.crossSdkBridgeEnabled;
8066
+ this.messageAPI = new MessagesApi(guardianConfiguration);
7865
8067
  }
7866
8068
  /**
7867
8069
  * Open confirmation screen and close it automatically if the
@@ -7960,6 +8162,31 @@ class GuardianClient {
7960
8162
  this.confirmationScreen.closeWindow();
7961
8163
  }
7962
8164
  }
8165
+ async evaluateMessage({ chainID, payload, user }) {
8166
+ try {
8167
+ const messageEvalResponse = await this.messageAPI.evaluateMessage({ messageEvaluationRequest: { chainID, payload } }, { headers: { Authorization: `Bearer ${user.accessToken}` } });
8168
+ return messageEvalResponse.data;
8169
+ }
8170
+ catch (error) {
8171
+ const errorMessage = error instanceof Error ? error.message : String(error);
8172
+ throw new JsonRpcError(RpcErrorCode.INTERNAL_ERROR, `Message failed to validate with error: ${errorMessage}`);
8173
+ }
8174
+ }
8175
+ async validateMessage({ chainID, payload, user }) {
8176
+ const { messageId, confirmationRequired } = await this.evaluateMessage({ chainID, payload, user });
8177
+ if (confirmationRequired && this.crossSdkBridgeEnabled) {
8178
+ throw new JsonRpcError(RpcErrorCode.TRANSACTION_REJECTED, transactionRejectedCrossSdkBridgeError);
8179
+ }
8180
+ if (confirmationRequired && !!messageId) {
8181
+ const confirmationResult = await this.confirmationScreen.requestMessageConfirmation(messageId);
8182
+ if (!confirmationResult.confirmed) {
8183
+ throw new JsonRpcError(RpcErrorCode.TRANSACTION_REJECTED, 'Signature rejected by user');
8184
+ }
8185
+ }
8186
+ else {
8187
+ this.confirmationScreen.closeWindow();
8188
+ }
8189
+ }
7963
8190
  }
7964
8191
 
7965
8192
  var PassportEvents;
@@ -8587,6 +8814,8 @@ var ReceiveMessage;
8587
8814
  ReceiveMessage["CONFIRMATION_WINDOW_READY"] = "confirmation_window_ready";
8588
8815
  ReceiveMessage["TRANSACTION_CONFIRMED"] = "transaction_confirmed";
8589
8816
  ReceiveMessage["TRANSACTION_ERROR"] = "transaction_error";
8817
+ ReceiveMessage["MESSAGE_CONFIRMED"] = "message_confirmed";
8818
+ ReceiveMessage["MESSAGE_REJECTED"] = "message_rejected";
8590
8819
  })(ReceiveMessage || (ReceiveMessage = {}));
8591
8820
  const PASSPORT_EVENT_TYPE = 'imx_passport_confirmation';
8592
8821
 
@@ -8640,11 +8869,11 @@ class ConfirmationScreen {
8640
8869
  reject(new Error('Unsupported message type'));
8641
8870
  }
8642
8871
  };
8643
- window.addEventListener('message', messageHandler);
8644
8872
  if (!this.confirmationWindow) {
8645
8873
  resolve({ confirmed: false });
8646
8874
  return;
8647
8875
  }
8876
+ window.addEventListener('message', messageHandler);
8648
8877
  let href = '';
8649
8878
  if (chainType === TransactionApprovalRequestChainTypeEnum.Starkex) {
8650
8879
  // eslint-disable-next-line max-len
@@ -8654,15 +8883,39 @@ class ConfirmationScreen {
8654
8883
  // eslint-disable-next-line max-len
8655
8884
  href = `${this.config.passportDomain}/transaction-confirmation/zkevm?transactionId=${transactionId}&imxEtherAddress=${imxEtherAddress}&chainType=evm&chainId=${chainId}`;
8656
8885
  }
8657
- this.confirmationWindow.location.href = href;
8658
- // https://stackoverflow.com/questions/9388380/capture-the-close-event-of-popup-window-in-javascript/48240128#48240128
8659
- const timer = setInterval(() => {
8660
- if (this.confirmationWindow?.closed) {
8661
- clearInterval(timer);
8662
- window.removeEventListener('message', messageHandler);
8663
- resolve({ confirmed: false });
8886
+ this.showConfirmationScreen(href, messageHandler, resolve);
8887
+ });
8888
+ }
8889
+ requestMessageConfirmation(messageId) {
8890
+ return new Promise((resolve, reject) => {
8891
+ const messageHandler = ({ data, origin }) => {
8892
+ if (origin !== this.config.passportDomain
8893
+ || data.eventType !== PASSPORT_EVENT_TYPE) {
8894
+ return;
8895
+ }
8896
+ switch (data.messageType) {
8897
+ case ReceiveMessage.CONFIRMATION_WINDOW_READY: {
8898
+ break;
8899
+ }
8900
+ case ReceiveMessage.MESSAGE_CONFIRMED: {
8901
+ resolve({ confirmed: true });
8902
+ break;
8903
+ }
8904
+ case ReceiveMessage.MESSAGE_REJECTED: {
8905
+ reject(new Error('Message rejected'));
8906
+ break;
8907
+ }
8908
+ default:
8909
+ reject(new Error('Unsupported message type'));
8664
8910
  }
8665
- }, CONFIRMATION_WINDOW_CLOSED_POLLING_DURATION);
8911
+ };
8912
+ if (!this.confirmationWindow) {
8913
+ resolve({ confirmed: false });
8914
+ return;
8915
+ }
8916
+ window.addEventListener('message', messageHandler);
8917
+ const href = `${this.config.passportDomain}/transaction-confirmation/zkevm/message?messageID=${messageId}`;
8918
+ this.showConfirmationScreen(href, messageHandler, resolve);
8666
8919
  });
8667
8920
  }
8668
8921
  loading(popupOptions) {
@@ -8680,6 +8933,17 @@ class ConfirmationScreen {
8680
8933
  closeWindow() {
8681
8934
  this.confirmationWindow?.close();
8682
8935
  }
8936
+ showConfirmationScreen(href, messageHandler, resolve) {
8937
+ this.confirmationWindow.location.href = href;
8938
+ // https://stackoverflow.com/questions/9388380/capture-the-close-event-of-popup-window-in-javascript/48240128#48240128
8939
+ const timer = setInterval(() => {
8940
+ if (this.confirmationWindow?.closed) {
8941
+ clearInterval(timer);
8942
+ window.removeEventListener('message', messageHandler);
8943
+ resolve({ confirmed: false });
8944
+ }
8945
+ }, CONFIRMATION_WINDOW_CLOSED_POLLING_DURATION);
8946
+ }
8683
8947
  }
8684
8948
 
8685
8949
  var RelayerTransactionStatus;
@@ -8708,13 +8972,9 @@ class TypedEventEmitter {
8708
8972
  }
8709
8973
  }
8710
8974
 
8711
- // These are ignored by the Relayer but for consistency we set them to the
8712
- // appropriate values for a 1/1 wallet.
8713
- //
8714
- // Weight of a single signature in the multisig
8715
- const SIGNATURE_WEIGHT = 1;
8716
- // Total required weight in the multisig
8717
- const SIGNATURE_THRESHOLD = 1;
8975
+ const SIGNATURE_WEIGHT = 1; // Weight of a single signature in the multi-sig
8976
+ const TRANSACTION_SIGNATURE_THRESHOLD = 1; // Total required weight in the multi-sig for a transaction
8977
+ const EIP712_SIGNATURE_THRESHOLD = 2; // Total required weight in the multi-sig for data signing
8718
8978
  const ETH_SIGN_FLAG = '02';
8719
8979
  const ETH_SIGN_PREFIX = '\x19\x01';
8720
8980
  const META_TRANSACTIONS_TYPE = `tuple(
@@ -8747,11 +9007,12 @@ const getNonce = async (jsonRpcProvider, smartContractWalletAddress) => {
8747
9007
  }
8748
9008
  return 0;
8749
9009
  };
9010
+ const encodeMessageSubDigest = (chainId, walletAddress, digest) => (ethers.ethers.utils.solidityPack(['string', 'uint256', 'address', 'bytes32'], [ETH_SIGN_PREFIX, chainId, walletAddress, digest]));
8750
9011
  const getSignedMetaTransactions = async (metaTransactions, nonce, chainId, walletAddress, signer) => {
8751
9012
  const normalisedMetaTransactions = getNormalisedTransactions(metaTransactions);
8752
9013
  // Get the hash
8753
9014
  const digest = digestOfTransactionsAndNonce(nonce, normalisedMetaTransactions);
8754
- const completePayload = ethers.ethers.utils.solidityPack(['string', 'uint256', 'address', 'bytes32'], [ETH_SIGN_PREFIX, chainId, walletAddress, digest]);
9015
+ const completePayload = encodeMessageSubDigest(chainId, walletAddress, digest);
8755
9016
  const hash = ethers.ethers.utils.keccak256(completePayload);
8756
9017
  // Sign the digest
8757
9018
  const hashArray = ethers.ethers.utils.arrayify(hash);
@@ -8759,7 +9020,7 @@ const getSignedMetaTransactions = async (metaTransactions, nonce, chainId, walle
8759
9020
  const signedDigest = `${ethsigNoType}${ETH_SIGN_FLAG}`;
8760
9021
  // Add metadata
8761
9022
  const encodedSignature = config$1.encodeSignature({
8762
- threshold: SIGNATURE_THRESHOLD,
9023
+ threshold: TRANSACTION_SIGNATURE_THRESHOLD,
8763
9024
  signers: [
8764
9025
  {
8765
9026
  weight: SIGNATURE_WEIGHT,
@@ -8775,6 +9036,35 @@ const getSignedMetaTransactions = async (metaTransactions, nonce, chainId, walle
8775
9036
  encodedSignature,
8776
9037
  ]);
8777
9038
  };
9039
+ const decodeRelayerTypedDataSignature = (relayerSignature) => {
9040
+ const signatureWithThreshold = `0000${relayerSignature}`;
9041
+ return config$1.decodeSignature(signatureWithThreshold);
9042
+ };
9043
+ const getSignedTypedData = async (typedData, relayerSignature, chainId, walletAddress, signer) => {
9044
+ // Ethers auto-generates the EIP712Domain type in the TypedDataEncoder, and so it needs to be removed
9045
+ const types = { ...typedData.types };
9046
+ // @ts-ignore
9047
+ delete types.EIP712Domain;
9048
+ // eslint-disable-next-line no-underscore-dangle
9049
+ const digest = ethers.ethers.utils._TypedDataEncoder.hash(typedData.domain, types, typedData.message);
9050
+ const completePayload = encodeMessageSubDigest(chainId, walletAddress, digest);
9051
+ const hash = ethers.ethers.utils.keccak256(completePayload);
9052
+ // Sign the digest
9053
+ const hashArray = ethers.ethers.utils.arrayify(hash);
9054
+ const ethsigNoType = await signer.signMessage(hashArray);
9055
+ const signedDigest = `${ethsigNoType}${ETH_SIGN_FLAG}`;
9056
+ const { signers } = decodeRelayerTypedDataSignature(relayerSignature);
9057
+ return config$1.encodeSignature({
9058
+ threshold: EIP712_SIGNATURE_THRESHOLD,
9059
+ signers: [
9060
+ ...signers,
9061
+ {
9062
+ weight: SIGNATURE_WEIGHT,
9063
+ signature: signedDigest,
9064
+ },
9065
+ ],
9066
+ });
9067
+ };
8778
9068
  const getEip155ChainId = (chainId) => `eip155:${chainId}`;
8779
9069
 
8780
9070
  class RelayerClient {
@@ -8840,6 +9130,19 @@ class RelayerClient {
8840
9130
  const { result } = await this.postToRelayer(payload);
8841
9131
  return result;
8842
9132
  }
9133
+ async imSignTypedData(address, eip712Payload) {
9134
+ const { chainId } = await this.jsonRpcProvider.ready;
9135
+ const payload = {
9136
+ method: 'im_signTypedData',
9137
+ params: [{
9138
+ address,
9139
+ eip712Payload,
9140
+ chainId: getEip155ChainId(chainId),
9141
+ }],
9142
+ };
9143
+ const { result } = await this.postToRelayer(payload);
9144
+ return result;
9145
+ }
8843
9146
  }
8844
9147
 
8845
9148
  const MESSAGE_TO_SIGN = 'Only sign this message from Immutable Passport';
@@ -8980,6 +9283,60 @@ const sendTransaction = ({ params, magicProvider, jsonRpcProvider, relayerClient
8980
9283
  return relayerTransaction.hash;
8981
9284
  });
8982
9285
 
9286
+ const REQUIRED_TYPED_DATA_PROPERTIES = ['types', 'domain', 'primaryType', 'message'];
9287
+ const isValidTypedDataPayload = (typedData) => (REQUIRED_TYPED_DATA_PROPERTIES.every((key) => key in typedData));
9288
+ const transformTypedData = (typedData, chainId) => {
9289
+ let transformedTypedData;
9290
+ if (typeof typedData === 'string') {
9291
+ try {
9292
+ transformedTypedData = JSON.parse(typedData);
9293
+ }
9294
+ catch (err) {
9295
+ throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, `Failed to parse typed data JSON: ${err}`);
9296
+ }
9297
+ }
9298
+ else if (typeof typedData === 'object') {
9299
+ transformedTypedData = typedData;
9300
+ }
9301
+ else {
9302
+ throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, `Invalid typed data argument: ${typedData}`);
9303
+ }
9304
+ if (!isValidTypedDataPayload(transformedTypedData)) {
9305
+ throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, `Invalid typed data argument. The following properties are required: ${REQUIRED_TYPED_DATA_PROPERTIES.join(', ')}`);
9306
+ }
9307
+ const providedChainId = transformedTypedData.domain?.chainId;
9308
+ if (providedChainId) {
9309
+ // domain.chainId (if defined) can be a number, string, or hex value, but the relayer & guardian only accept a number.
9310
+ if (typeof providedChainId === 'string') {
9311
+ if (providedChainId.startsWith('0x')) {
9312
+ transformedTypedData.domain.chainId = parseInt(providedChainId, 16);
9313
+ }
9314
+ else {
9315
+ transformedTypedData.domain.chainId = parseInt(providedChainId, 10);
9316
+ }
9317
+ }
9318
+ if (transformedTypedData.domain.chainId !== chainId) {
9319
+ throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, `Invalid chainId, expected ${chainId}`);
9320
+ }
9321
+ }
9322
+ return transformedTypedData;
9323
+ };
9324
+ const signTypedDataV4 = async ({ params, method, magicProvider, jsonRpcProvider, relayerClient, guardianClient, user, }) => guardianClient
9325
+ .withConfirmationScreen({ width: 480, height: 730 })(async () => {
9326
+ const fromAddress = params[0];
9327
+ const typedDataParam = params[1];
9328
+ if (!fromAddress || !typedDataParam) {
9329
+ throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, `${method} requires an address and a typed data JSON`);
9330
+ }
9331
+ const { chainId } = await jsonRpcProvider.ready;
9332
+ const typedData = transformTypedData(typedDataParam, chainId);
9333
+ await guardianClient.validateMessage({ chainID: String(chainId), payload: typedData, user });
9334
+ const relayerSignature = await relayerClient.imSignTypedData(fromAddress, typedData);
9335
+ const magicWeb3Provider = new providers.Web3Provider(magicProvider);
9336
+ const signer = magicWeb3Provider.getSigner();
9337
+ return getSignedTypedData(typedData, relayerSignature, ethers.BigNumber.from(chainId), fromAddress, signer);
9338
+ });
9339
+
8983
9340
  class ZkEvmProvider {
8984
9341
  authManager;
8985
9342
  config;
@@ -9063,6 +9420,21 @@ class ZkEvmProvider {
9063
9420
  case 'eth_accounts': {
9064
9421
  return this.isLoggedIn() ? [this.user.zkEvm.ethAddress] : [];
9065
9422
  }
9423
+ case 'eth_signTypedData':
9424
+ case 'eth_signTypedData_v4': {
9425
+ if (!this.isLoggedIn()) {
9426
+ throw new JsonRpcError(ProviderErrorCode.UNAUTHORIZED, 'Unauthorised - call eth_requestAccounts first');
9427
+ }
9428
+ return signTypedDataV4({
9429
+ method: request.method,
9430
+ params: request.params || [],
9431
+ magicProvider: this.magicProvider,
9432
+ jsonRpcProvider: this.jsonRpcProvider,
9433
+ relayerClient: this.relayerClient,
9434
+ user: this.user,
9435
+ guardianClient: this.guardianClient,
9436
+ });
9437
+ }
9066
9438
  // Pass through methods
9067
9439
  case 'eth_gasPrice':
9068
9440
  case 'eth_getBalance':
@@ -29436,8 +29808,8 @@ const $7d1bfafb81e64d74$export$3a4140bd9e983e4e = async (provider, insufficientI
29436
29808
 
29437
29809
 
29438
29810
 
29439
- const $1fda5c40669a566d$export$1fac8e857d728583 = async ()=>true;
29440
- const $1fda5c40669a566d$export$2e83e9eeaf217e20 = async ()=>true;
29811
+ const $1fda5c40669a566d$export$1fac8e857d728583 = async ()=>false;
29812
+ const $1fda5c40669a566d$export$2e83e9eeaf217e20 = async ()=>false;
29441
29813
 
29442
29814
 
29443
29815
  const $7f2e17f026d4fc8d$var$isPassportProvider = (provider)=>(provider.provider?.isPassport === true) ?? false;
@@ -29620,6 +29992,24 @@ const $07ac9c0576988336$export$a3dd181de896b7c7 = async (config, readOnlyProvide
29620
29992
 
29621
29993
 
29622
29994
 
29995
+
29996
+ const $5a5ccedc98d53d25$var$filterTokens = (allowedTokens, balances)=>{
29997
+ if (balances && balances.success) return allowedTokens.filter((token)=>{
29998
+ if ("address" in token) return balances.balances.find((balance)=>balance.token.address === token.address && balance.balance.gt(0));
29999
+ return balances.balances.find((balance)=>!("address" in balance.token) && balance.balance.gt(0));
30000
+ });
30001
+ return [];
30002
+ };
30003
+ const $5a5ccedc98d53d25$export$d744af9f1c0712bc = async (config, tokenBalances, availableRoutingOptions)=>{
30004
+ if (availableRoutingOptions.bridge) {
30005
+ const allowedTokens = (await config.remote.getConfig("bridge"))?.tokens ?? [];
30006
+ const balances = tokenBalances.get(($4013c5c91bb535f6$export$9b794d067cdd1af6)(config));
30007
+ return $5a5ccedc98d53d25$var$filterTokens(allowedTokens, balances);
30008
+ }
30009
+ return [];
30010
+ };
30011
+
30012
+
29623
30013
  const $fa9ac5bfdbbf9dfa$export$9994ad18c2f0e665 = (balances, totalFees)=>{
29624
30014
  const balance = ($f730af3b727f04ac$export$22fea095b15361de)(balances);
29625
30015
  return balance.gte(totalFees);
@@ -29678,15 +30068,18 @@ const $fa9ac5bfdbbf9dfa$export$ddc7ba2b57d7c5fa = async (config, readOnlyProvide
29678
30068
  chainId: chainId.toString()
29679
30069
  });
29680
30070
  // If no balances on layer 1 then Bridge cannot be an option
29681
- if (tokenBalanceResult === undefined || tokenBalanceResult.success === false) throw new ($a8bc256d81a5e2c1$export$b722478a3cbfa3bc)("Error getting balances", ($a8bc256d81a5e2c1$export$e3dc0620abde7f5a).GET_BALANCE_ERROR, {
29682
- chainId: chainId.toString()
29683
- });
29684
- if (tokenBalanceResult.balances.length === 0) return undefined;
30071
+ if (tokenBalanceResult === undefined || tokenBalanceResult.success === false) return undefined;
30072
+ const allowedTokenList = await ($5a5ccedc98d53d25$export$d744af9f1c0712bc)(config, balances, availableRoutingOptions);
30073
+ if (allowedTokenList.length === 0) return undefined;
29685
30074
  const bridgeFeeEstimate = await $fa9ac5bfdbbf9dfa$export$da05aed50d75046(config, readOnlyProviders, feeEstimates);
29686
30075
  // If the user has no ETH to cover the bridge fees or approval fees then bridge cannot be an option
29687
30076
  if (!$fa9ac5bfdbbf9dfa$export$9994ad18c2f0e665(tokenBalanceResult, bridgeFeeEstimate)) return undefined;
29688
30077
  const l1address = await $fa9ac5bfdbbf9dfa$export$952cdf461a00a8c6(config, balanceRequirement);
29689
30078
  if (l1address === "") return undefined;
30079
+ // Ensure l1address is in the allowed token list
30080
+ if (l1address === ($823db9fb0ca4bc15$export$c37d8687c27b9660)) {
30081
+ if (!allowedTokenList.find((token)=>!("address" in token))) return undefined;
30082
+ } else if (!allowedTokenList.find((token)=>token.address === l1address)) return undefined;
29690
30083
  const gasForApproval = await ($07ac9c0576988336$export$a3dd181de896b7c7)(config, readOnlyProviders, l1provider, depositorAddress, l1address, balanceRequirement.delta.balance);
29691
30084
  if (!$fa9ac5bfdbbf9dfa$export$9994ad18c2f0e665(tokenBalanceResult, gasForApproval.add(bridgeFeeEstimate))) return undefined;
29692
30085
  // If the L1 representation of the requirement is ETH then find the ETH balance and check if the balance covers the delta
@@ -29742,7 +30135,6 @@ const $c16168a9c28ae4fd$export$92606e71d0a264ff = async (config, ownerAddress, b
29742
30135
  });
29743
30136
  }
29744
30137
  const tokenBalances = await ($33acec7b4a26c053$export$23ddeb2642d2f9d)(config, readOnlyProviders, ownerAddress, availableRoutingOptions);
29745
- // Get allowed tokens?
29746
30138
  // Bridge and swap fee cache
29747
30139
  const feeEstimates = new Map();
29748
30140
  // Ensures only 1 balance requirement is insufficient otherwise one bridge route cannot be recommended
@@ -30489,31 +30881,30 @@ var checkout_sdk = /*#__PURE__*/Object.freeze({
30489
30881
  function $parcel$export(e, n, v, s) {
30490
30882
  Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true});
30491
30883
  }
30492
- const $d663162fd5a0853f$export$38a083d9fb5551ca = "0.17.5";
30884
+ const $d663162fd5a0853f$export$38a083d9fb5551ca = "0.18.0";
30493
30885
  const $d663162fd5a0853f$export$83bf90b30cdfd29f = ()=>false;
30494
30886
  const $d663162fd5a0853f$export$1169f5475725171b = ()=>$d663162fd5a0853f$export$38a083d9fb5551ca;
30495
30887
 
30496
30888
 
30497
30889
  function $430e3eda76fa4d5f$export$46b1ae20f762ad4c(version) {
30498
30890
  const defaultPackageVersion = ($d663162fd5a0853f$export$1169f5475725171b)();
30499
- if (version === undefined) return defaultPackageVersion;
30500
- // Pre-production release
30501
- // TODO: https://immutable.atlassian.net/browse/WT-1501
30502
- if (version.major === undefined || version.minor === undefined || version.patch === undefined || version.prerelease === undefined) return defaultPackageVersion;
30503
- if (version.major < 0) return defaultPackageVersion;
30504
- if (version.minor < 0) return defaultPackageVersion;
30505
- if (version.patch < 0) return defaultPackageVersion;
30506
- if (version.prerelease !== "alpha") return defaultPackageVersion;
30891
+ if (version === undefined || version.major === undefined) return defaultPackageVersion;
30892
+ if (!Number.isInteger(version.major) || version.major < 0) return defaultPackageVersion;
30893
+ if (version.minor !== undefined && version.minor < 0) return defaultPackageVersion;
30894
+ if (version.patch !== undefined && version.patch < 0) return defaultPackageVersion;
30895
+ if (version.major === 0 && version.minor === undefined) return defaultPackageVersion;
30896
+ if (version.major === 0 && version.minor === 0 && version.patch === undefined) return defaultPackageVersion;
30897
+ if (version.major === 0 && version.minor === undefined && version.patch === undefined) return defaultPackageVersion;
30507
30898
  if (version.major === 0 && version.minor === 0 && version.patch === 0) return defaultPackageVersion;
30508
- let validatedVersion = defaultPackageVersion;
30509
- if (!Number.isNaN(version.major) && version.major >= 0) validatedVersion = version.major.toString();
30510
- if (!Number.isNaN(version.minor)) validatedVersion += `.${version.minor.toString()}`;
30511
- if (!Number.isNaN(version.patch)) validatedVersion += `.${version.patch.toString()}`;
30512
- // TODO: https://immutable.atlassian.net/browse/WT-1501
30513
- // Ensure this is gated by `version.prerelease !== undefined`
30514
- // once we go to prod with checkout.
30515
- validatedVersion += `-${version.prerelease}`;
30516
- if (version.build !== undefined && version.build > 0) validatedVersion += `.${version.build}`;
30899
+ let validatedVersion = version.major.toString();
30900
+ if (version.minor === undefined) return validatedVersion;
30901
+ if (Number.isInteger(version.minor)) validatedVersion += `.${version.minor.toString()}`;
30902
+ if (version.patch === undefined) return validatedVersion;
30903
+ if (Number.isInteger(version.patch)) validatedVersion += `.${version.patch.toString()}`;
30904
+ if (version.prerelease === undefined || version.prerelease !== "alpha") return validatedVersion;
30905
+ if (version.prerelease === "alpha") validatedVersion += `-${version.prerelease}`;
30906
+ if (version.build === undefined) return validatedVersion;
30907
+ if (Number.isInteger(version.build) && version.build >= 0) validatedVersion += `.${version.build.toString()}`;
30517
30908
  return validatedVersion;
30518
30909
  }
30519
30910
  function $430e3eda76fa4d5f$export$af210a0808087845(config) {