@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.js CHANGED
@@ -11,7 +11,7 @@ import * as encUtils from 'enc-utils';
11
11
  import { Web3Provider, JsonRpcProvider } from '@ethersproject/providers';
12
12
  import { EventEmitter } from 'events';
13
13
  import { walletContracts } from '@0xsequence/abi';
14
- import { encodeSignature } from '@0xsequence/config';
14
+ import { encodeSignature, decodeSignature } from '@0xsequence/config';
15
15
  import FormData$2 from 'form-data';
16
16
  import { Seaport as Seaport$1 } from '@opensea/seaport-js';
17
17
  import { parseUnits } from '@ethersproject/units';
@@ -2702,7 +2702,7 @@ class MultiRollupApiClients {
2702
2702
  }
2703
2703
 
2704
2704
  // eslint-disable-next-line @typescript-eslint/naming-convention
2705
- const defaultHeaders$1 = { 'x-sdk-version': 'ts-immutable-sdk-0.17.5' };
2705
+ const defaultHeaders$1 = { 'x-sdk-version': 'ts-immutable-sdk-0.18.0' };
2706
2706
  const createConfig = ({ basePath, headers, }) => {
2707
2707
  if (!basePath.trim()) {
2708
2708
  throw Error('basePath can not be empty');
@@ -2762,7 +2762,7 @@ class APIError extends Error {
2762
2762
 
2763
2763
  /* eslint-disable implicit-arrow-linebreak */
2764
2764
  const defaultHeaders = {
2765
- sdkVersion: 'ts-immutable-sdk-multi-rollup-api-client-0.17.5',
2765
+ sdkVersion: 'ts-immutable-sdk-multi-rollup-api-client-0.18.0',
2766
2766
  };
2767
2767
  /**
2768
2768
  * createAPIConfiguration to create a custom Configuration
@@ -3048,7 +3048,7 @@ const createImmutableXConfiguration = ({ basePath, chainID, coreContractAddress,
3048
3048
  chainID,
3049
3049
  coreContractAddress,
3050
3050
  registrationContractAddress,
3051
- sdkVersion: 'ts-immutable-sdk-0.17.5',
3051
+ sdkVersion: 'ts-immutable-sdk-0.18.0',
3052
3052
  });
3053
3053
  /**
3054
3054
  * Sets `sdkVersion` at the time of build
@@ -6780,6 +6780,8 @@ var globalAxios = axios;
6780
6780
  * https://openapi-generator.tech
6781
6781
  * Do not edit the class manually.
6782
6782
  */
6783
+ // Some imports not used depending on template conditions
6784
+ // @ts-ignore
6783
6785
  const BASE_PATH = "https://guardian.sandbox.imtbl.com".replace(/\/+$/, "");
6784
6786
  /**
6785
6787
  *
@@ -6807,10 +6809,10 @@ class BaseAPI {
6807
6809
  */
6808
6810
  class RequiredError extends Error {
6809
6811
  field;
6812
+ name = "RequiredError";
6810
6813
  constructor(field, msg) {
6811
6814
  super(msg);
6812
6815
  this.field = field;
6813
- this.name = "RequiredError";
6814
6816
  }
6815
6817
  }
6816
6818
 
@@ -6855,8 +6857,6 @@ const setBearerAuthToObject = async function (object, configuration) {
6855
6857
  }
6856
6858
  };
6857
6859
  function setFlattenedQueryParams(urlSearchParams, parameter, key = "") {
6858
- if (parameter == null)
6859
- return;
6860
6860
  if (typeof parameter === "object") {
6861
6861
  if (Array.isArray(parameter)) {
6862
6862
  parameter.forEach(item => setFlattenedQueryParams(urlSearchParams, item, key));
@@ -6914,6 +6914,208 @@ const createRequestFunction = function (axiosArgs, globalAxios, BASE_PATH, confi
6914
6914
  };
6915
6915
  };
6916
6916
 
6917
+ /* tslint:disable */
6918
+ /* eslint-disable */
6919
+ /**
6920
+ * Guardian
6921
+ * Guardian API
6922
+ *
6923
+ * The version of the OpenAPI document: 1.0.0
6924
+ * Contact: support@immutable.com
6925
+ *
6926
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
6927
+ * https://openapi-generator.tech
6928
+ * Do not edit the class manually.
6929
+ */
6930
+ /**
6931
+ * MessagesApi - axios parameter creator
6932
+ * @export
6933
+ */
6934
+ const MessagesApiAxiosParamCreator = function (configuration) {
6935
+ return {
6936
+ /**
6937
+ * Approve a pending evm message
6938
+ * @summary Approve a pending evm message
6939
+ * @param {string} messageID id for the message
6940
+ * @param {*} [options] Override http request option.
6941
+ * @throws {RequiredError}
6942
+ */
6943
+ approvePendingMessage: async (messageID, options = {}) => {
6944
+ // verify required parameter 'messageID' is not null or undefined
6945
+ assertParamExists('approvePendingMessage', 'messageID', messageID);
6946
+ const localVarPath = `/guardian/v1/messages/{messageID}/approve`
6947
+ .replace(`{${"messageID"}}`, encodeURIComponent(String(messageID)));
6948
+ // use dummy base URL string because the URL constructor only accepts absolute URLs.
6949
+ const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
6950
+ let baseOptions;
6951
+ if (configuration) {
6952
+ baseOptions = configuration.baseOptions;
6953
+ }
6954
+ const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options };
6955
+ const localVarHeaderParameter = {};
6956
+ const localVarQueryParameter = {};
6957
+ // authentication BearerAuth required
6958
+ // http bearer authentication required
6959
+ await setBearerAuthToObject(localVarHeaderParameter, configuration);
6960
+ setSearchParams(localVarUrlObj, localVarQueryParameter);
6961
+ let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
6962
+ localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers };
6963
+ return {
6964
+ url: toPathString(localVarUrlObj),
6965
+ options: localVarRequestOptions,
6966
+ };
6967
+ },
6968
+ /**
6969
+ * Check if a given message is valid for EVM
6970
+ * @summary Evaluate an evm message to sign
6971
+ * @param {MessageEvaluationRequest} messageEvaluationRequest Specifies the kind of transaction
6972
+ * @param {*} [options] Override http request option.
6973
+ * @throws {RequiredError}
6974
+ */
6975
+ evaluateMessage: async (messageEvaluationRequest, options = {}) => {
6976
+ // verify required parameter 'messageEvaluationRequest' is not null or undefined
6977
+ assertParamExists('evaluateMessage', 'messageEvaluationRequest', messageEvaluationRequest);
6978
+ const localVarPath = `/guardian/v1/messages/evaluate`;
6979
+ // use dummy base URL string because the URL constructor only accepts absolute URLs.
6980
+ const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
6981
+ let baseOptions;
6982
+ if (configuration) {
6983
+ baseOptions = configuration.baseOptions;
6984
+ }
6985
+ const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options };
6986
+ const localVarHeaderParameter = {};
6987
+ const localVarQueryParameter = {};
6988
+ // authentication BearerAuth required
6989
+ // http bearer authentication required
6990
+ await setBearerAuthToObject(localVarHeaderParameter, configuration);
6991
+ localVarHeaderParameter['Content-Type'] = 'application/json';
6992
+ setSearchParams(localVarUrlObj, localVarQueryParameter);
6993
+ let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
6994
+ localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers };
6995
+ localVarRequestOptions.data = serializeDataIfNeeded(messageEvaluationRequest, localVarRequestOptions, configuration);
6996
+ return {
6997
+ url: toPathString(localVarUrlObj),
6998
+ options: localVarRequestOptions,
6999
+ };
7000
+ },
7001
+ /**
7002
+ * Get an evm message by id
7003
+ * @summary Info for a specific evm message
7004
+ * @param {string} messageID The id of the evm message
7005
+ * @param {*} [options] Override http request option.
7006
+ * @throws {RequiredError}
7007
+ */
7008
+ getMessageByID: async (messageID, options = {}) => {
7009
+ // verify required parameter 'messageID' is not null or undefined
7010
+ assertParamExists('getMessageByID', 'messageID', messageID);
7011
+ const localVarPath = `/guardian/v1/messages/{messageID}`
7012
+ .replace(`{${"messageID"}}`, encodeURIComponent(String(messageID)));
7013
+ // use dummy base URL string because the URL constructor only accepts absolute URLs.
7014
+ const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
7015
+ let baseOptions;
7016
+ if (configuration) {
7017
+ baseOptions = configuration.baseOptions;
7018
+ }
7019
+ const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options };
7020
+ const localVarHeaderParameter = {};
7021
+ const localVarQueryParameter = {};
7022
+ // authentication BearerAuth required
7023
+ // http bearer authentication required
7024
+ await setBearerAuthToObject(localVarHeaderParameter, configuration);
7025
+ setSearchParams(localVarUrlObj, localVarQueryParameter);
7026
+ let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
7027
+ localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers };
7028
+ return {
7029
+ url: toPathString(localVarUrlObj),
7030
+ options: localVarRequestOptions,
7031
+ };
7032
+ },
7033
+ };
7034
+ };
7035
+ /**
7036
+ * MessagesApi - functional programming interface
7037
+ * @export
7038
+ */
7039
+ const MessagesApiFp = function (configuration) {
7040
+ const localVarAxiosParamCreator = MessagesApiAxiosParamCreator(configuration);
7041
+ return {
7042
+ /**
7043
+ * Approve a pending evm message
7044
+ * @summary Approve a pending evm message
7045
+ * @param {string} messageID id for the message
7046
+ * @param {*} [options] Override http request option.
7047
+ * @throws {RequiredError}
7048
+ */
7049
+ async approvePendingMessage(messageID, options) {
7050
+ const localVarAxiosArgs = await localVarAxiosParamCreator.approvePendingMessage(messageID, options);
7051
+ return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
7052
+ },
7053
+ /**
7054
+ * Check if a given message is valid for EVM
7055
+ * @summary Evaluate an evm message to sign
7056
+ * @param {MessageEvaluationRequest} messageEvaluationRequest Specifies the kind of transaction
7057
+ * @param {*} [options] Override http request option.
7058
+ * @throws {RequiredError}
7059
+ */
7060
+ async evaluateMessage(messageEvaluationRequest, options) {
7061
+ const localVarAxiosArgs = await localVarAxiosParamCreator.evaluateMessage(messageEvaluationRequest, options);
7062
+ return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
7063
+ },
7064
+ /**
7065
+ * Get an evm message by id
7066
+ * @summary Info for a specific evm message
7067
+ * @param {string} messageID The id of the evm message
7068
+ * @param {*} [options] Override http request option.
7069
+ * @throws {RequiredError}
7070
+ */
7071
+ async getMessageByID(messageID, options) {
7072
+ const localVarAxiosArgs = await localVarAxiosParamCreator.getMessageByID(messageID, options);
7073
+ return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
7074
+ },
7075
+ };
7076
+ };
7077
+ /**
7078
+ * MessagesApi - object-oriented interface
7079
+ * @export
7080
+ * @class MessagesApi
7081
+ * @extends {BaseAPI}
7082
+ */
7083
+ class MessagesApi extends BaseAPI {
7084
+ /**
7085
+ * Approve a pending evm message
7086
+ * @summary Approve a pending evm message
7087
+ * @param {MessagesApiApprovePendingMessageRequest} requestParameters Request parameters.
7088
+ * @param {*} [options] Override http request option.
7089
+ * @throws {RequiredError}
7090
+ * @memberof MessagesApi
7091
+ */
7092
+ approvePendingMessage(requestParameters, options) {
7093
+ return MessagesApiFp(this.configuration).approvePendingMessage(requestParameters.messageID, options).then((request) => request(this.axios, this.basePath));
7094
+ }
7095
+ /**
7096
+ * Check if a given message is valid for EVM
7097
+ * @summary Evaluate an evm message to sign
7098
+ * @param {MessagesApiEvaluateMessageRequest} requestParameters Request parameters.
7099
+ * @param {*} [options] Override http request option.
7100
+ * @throws {RequiredError}
7101
+ * @memberof MessagesApi
7102
+ */
7103
+ evaluateMessage(requestParameters, options) {
7104
+ return MessagesApiFp(this.configuration).evaluateMessage(requestParameters.messageEvaluationRequest, options).then((request) => request(this.axios, this.basePath));
7105
+ }
7106
+ /**
7107
+ * Get an evm message by id
7108
+ * @summary Info for a specific evm message
7109
+ * @param {MessagesApiGetMessageByIDRequest} requestParameters Request parameters.
7110
+ * @param {*} [options] Override http request option.
7111
+ * @throws {RequiredError}
7112
+ * @memberof MessagesApi
7113
+ */
7114
+ getMessageByID(requestParameters, options) {
7115
+ return MessagesApiFp(this.configuration).getMessageByID(requestParameters.messageID, options).then((request) => request(this.axios, this.basePath));
7116
+ }
7117
+ }
7118
+
6917
7119
  /* tslint:disable */
6918
7120
  /* eslint-disable */
6919
7121
  /**
@@ -6937,7 +7139,7 @@ const TransactionsApiAxiosParamCreator = function (configuration) {
6937
7139
  * Approve a pending transaction
6938
7140
  * @summary Approve a pending transaction given chain
6939
7141
  * @param {string} payloadHash Hash for the payload
6940
- * @param {TransactionApprovalRequest} transactionApprovalRequest request body for approving a pending transactio
7142
+ * @param {TransactionApprovalRequest} transactionApprovalRequest request body for approving a pending transaction
6941
7143
  * @param {*} [options] Override http request option.
6942
7144
  * @throws {RequiredError}
6943
7145
  */
@@ -7062,7 +7264,7 @@ const TransactionsApiFp = function (configuration) {
7062
7264
  * Approve a pending transaction
7063
7265
  * @summary Approve a pending transaction given chain
7064
7266
  * @param {string} payloadHash Hash for the payload
7065
- * @param {TransactionApprovalRequest} transactionApprovalRequest request body for approving a pending transactio
7267
+ * @param {TransactionApprovalRequest} transactionApprovalRequest request body for approving a pending transaction
7066
7268
  * @param {*} [options] Override http request option.
7067
7269
  * @throws {RequiredError}
7068
7270
  */
@@ -7828,18 +8030,18 @@ const transformGuardianTransactions = (txs) => {
7828
8030
  };
7829
8031
  class GuardianClient {
7830
8032
  transactionAPI;
8033
+ messageAPI;
7831
8034
  confirmationScreen;
7832
8035
  // TODO: ID-977, make this rollup agnostic
7833
8036
  imxEtherAddress;
7834
8037
  crossSdkBridgeEnabled;
7835
8038
  constructor({ accessToken, confirmationScreen, imxEtherAddress, config, }) {
8039
+ const guardianConfiguration = new Configuration({ accessToken, basePath: config.imxPublicApiDomain });
7836
8040
  this.confirmationScreen = confirmationScreen;
7837
- this.transactionAPI = new TransactionsApi(new Configuration({
7838
- accessToken,
7839
- basePath: config.imxPublicApiDomain,
7840
- }));
8041
+ this.transactionAPI = new TransactionsApi(new Configuration(guardianConfiguration));
7841
8042
  this.imxEtherAddress = imxEtherAddress;
7842
8043
  this.crossSdkBridgeEnabled = config.crossSdkBridgeEnabled;
8044
+ this.messageAPI = new MessagesApi(guardianConfiguration);
7843
8045
  }
7844
8046
  /**
7845
8047
  * Open confirmation screen and close it automatically if the
@@ -7938,6 +8140,31 @@ class GuardianClient {
7938
8140
  this.confirmationScreen.closeWindow();
7939
8141
  }
7940
8142
  }
8143
+ async evaluateMessage({ chainID, payload, user }) {
8144
+ try {
8145
+ const messageEvalResponse = await this.messageAPI.evaluateMessage({ messageEvaluationRequest: { chainID, payload } }, { headers: { Authorization: `Bearer ${user.accessToken}` } });
8146
+ return messageEvalResponse.data;
8147
+ }
8148
+ catch (error) {
8149
+ const errorMessage = error instanceof Error ? error.message : String(error);
8150
+ throw new JsonRpcError(RpcErrorCode.INTERNAL_ERROR, `Message failed to validate with error: ${errorMessage}`);
8151
+ }
8152
+ }
8153
+ async validateMessage({ chainID, payload, user }) {
8154
+ const { messageId, confirmationRequired } = await this.evaluateMessage({ chainID, payload, user });
8155
+ if (confirmationRequired && this.crossSdkBridgeEnabled) {
8156
+ throw new JsonRpcError(RpcErrorCode.TRANSACTION_REJECTED, transactionRejectedCrossSdkBridgeError);
8157
+ }
8158
+ if (confirmationRequired && !!messageId) {
8159
+ const confirmationResult = await this.confirmationScreen.requestMessageConfirmation(messageId);
8160
+ if (!confirmationResult.confirmed) {
8161
+ throw new JsonRpcError(RpcErrorCode.TRANSACTION_REJECTED, 'Signature rejected by user');
8162
+ }
8163
+ }
8164
+ else {
8165
+ this.confirmationScreen.closeWindow();
8166
+ }
8167
+ }
7941
8168
  }
7942
8169
 
7943
8170
  var PassportEvents;
@@ -8565,6 +8792,8 @@ var ReceiveMessage;
8565
8792
  ReceiveMessage["CONFIRMATION_WINDOW_READY"] = "confirmation_window_ready";
8566
8793
  ReceiveMessage["TRANSACTION_CONFIRMED"] = "transaction_confirmed";
8567
8794
  ReceiveMessage["TRANSACTION_ERROR"] = "transaction_error";
8795
+ ReceiveMessage["MESSAGE_CONFIRMED"] = "message_confirmed";
8796
+ ReceiveMessage["MESSAGE_REJECTED"] = "message_rejected";
8568
8797
  })(ReceiveMessage || (ReceiveMessage = {}));
8569
8798
  const PASSPORT_EVENT_TYPE = 'imx_passport_confirmation';
8570
8799
 
@@ -8618,11 +8847,11 @@ class ConfirmationScreen {
8618
8847
  reject(new Error('Unsupported message type'));
8619
8848
  }
8620
8849
  };
8621
- window.addEventListener('message', messageHandler);
8622
8850
  if (!this.confirmationWindow) {
8623
8851
  resolve({ confirmed: false });
8624
8852
  return;
8625
8853
  }
8854
+ window.addEventListener('message', messageHandler);
8626
8855
  let href = '';
8627
8856
  if (chainType === TransactionApprovalRequestChainTypeEnum.Starkex) {
8628
8857
  // eslint-disable-next-line max-len
@@ -8632,15 +8861,39 @@ class ConfirmationScreen {
8632
8861
  // eslint-disable-next-line max-len
8633
8862
  href = `${this.config.passportDomain}/transaction-confirmation/zkevm?transactionId=${transactionId}&imxEtherAddress=${imxEtherAddress}&chainType=evm&chainId=${chainId}`;
8634
8863
  }
8635
- this.confirmationWindow.location.href = href;
8636
- // https://stackoverflow.com/questions/9388380/capture-the-close-event-of-popup-window-in-javascript/48240128#48240128
8637
- const timer = setInterval(() => {
8638
- if (this.confirmationWindow?.closed) {
8639
- clearInterval(timer);
8640
- window.removeEventListener('message', messageHandler);
8641
- resolve({ confirmed: false });
8864
+ this.showConfirmationScreen(href, messageHandler, resolve);
8865
+ });
8866
+ }
8867
+ requestMessageConfirmation(messageId) {
8868
+ return new Promise((resolve, reject) => {
8869
+ const messageHandler = ({ data, origin }) => {
8870
+ if (origin !== this.config.passportDomain
8871
+ || data.eventType !== PASSPORT_EVENT_TYPE) {
8872
+ return;
8873
+ }
8874
+ switch (data.messageType) {
8875
+ case ReceiveMessage.CONFIRMATION_WINDOW_READY: {
8876
+ break;
8877
+ }
8878
+ case ReceiveMessage.MESSAGE_CONFIRMED: {
8879
+ resolve({ confirmed: true });
8880
+ break;
8881
+ }
8882
+ case ReceiveMessage.MESSAGE_REJECTED: {
8883
+ reject(new Error('Message rejected'));
8884
+ break;
8885
+ }
8886
+ default:
8887
+ reject(new Error('Unsupported message type'));
8642
8888
  }
8643
- }, CONFIRMATION_WINDOW_CLOSED_POLLING_DURATION);
8889
+ };
8890
+ if (!this.confirmationWindow) {
8891
+ resolve({ confirmed: false });
8892
+ return;
8893
+ }
8894
+ window.addEventListener('message', messageHandler);
8895
+ const href = `${this.config.passportDomain}/transaction-confirmation/zkevm/message?messageID=${messageId}`;
8896
+ this.showConfirmationScreen(href, messageHandler, resolve);
8644
8897
  });
8645
8898
  }
8646
8899
  loading(popupOptions) {
@@ -8658,6 +8911,17 @@ class ConfirmationScreen {
8658
8911
  closeWindow() {
8659
8912
  this.confirmationWindow?.close();
8660
8913
  }
8914
+ showConfirmationScreen(href, messageHandler, resolve) {
8915
+ this.confirmationWindow.location.href = href;
8916
+ // https://stackoverflow.com/questions/9388380/capture-the-close-event-of-popup-window-in-javascript/48240128#48240128
8917
+ const timer = setInterval(() => {
8918
+ if (this.confirmationWindow?.closed) {
8919
+ clearInterval(timer);
8920
+ window.removeEventListener('message', messageHandler);
8921
+ resolve({ confirmed: false });
8922
+ }
8923
+ }, CONFIRMATION_WINDOW_CLOSED_POLLING_DURATION);
8924
+ }
8661
8925
  }
8662
8926
 
8663
8927
  var RelayerTransactionStatus;
@@ -8686,13 +8950,9 @@ class TypedEventEmitter {
8686
8950
  }
8687
8951
  }
8688
8952
 
8689
- // These are ignored by the Relayer but for consistency we set them to the
8690
- // appropriate values for a 1/1 wallet.
8691
- //
8692
- // Weight of a single signature in the multisig
8693
- const SIGNATURE_WEIGHT = 1;
8694
- // Total required weight in the multisig
8695
- const SIGNATURE_THRESHOLD = 1;
8953
+ const SIGNATURE_WEIGHT = 1; // Weight of a single signature in the multi-sig
8954
+ const TRANSACTION_SIGNATURE_THRESHOLD = 1; // Total required weight in the multi-sig for a transaction
8955
+ const EIP712_SIGNATURE_THRESHOLD = 2; // Total required weight in the multi-sig for data signing
8696
8956
  const ETH_SIGN_FLAG = '02';
8697
8957
  const ETH_SIGN_PREFIX = '\x19\x01';
8698
8958
  const META_TRANSACTIONS_TYPE = `tuple(
@@ -8725,11 +8985,12 @@ const getNonce = async (jsonRpcProvider, smartContractWalletAddress) => {
8725
8985
  }
8726
8986
  return 0;
8727
8987
  };
8988
+ const encodeMessageSubDigest = (chainId, walletAddress, digest) => (ethers.utils.solidityPack(['string', 'uint256', 'address', 'bytes32'], [ETH_SIGN_PREFIX, chainId, walletAddress, digest]));
8728
8989
  const getSignedMetaTransactions = async (metaTransactions, nonce, chainId, walletAddress, signer) => {
8729
8990
  const normalisedMetaTransactions = getNormalisedTransactions(metaTransactions);
8730
8991
  // Get the hash
8731
8992
  const digest = digestOfTransactionsAndNonce(nonce, normalisedMetaTransactions);
8732
- const completePayload = ethers.utils.solidityPack(['string', 'uint256', 'address', 'bytes32'], [ETH_SIGN_PREFIX, chainId, walletAddress, digest]);
8993
+ const completePayload = encodeMessageSubDigest(chainId, walletAddress, digest);
8733
8994
  const hash = ethers.utils.keccak256(completePayload);
8734
8995
  // Sign the digest
8735
8996
  const hashArray = ethers.utils.arrayify(hash);
@@ -8737,7 +8998,7 @@ const getSignedMetaTransactions = async (metaTransactions, nonce, chainId, walle
8737
8998
  const signedDigest = `${ethsigNoType}${ETH_SIGN_FLAG}`;
8738
8999
  // Add metadata
8739
9000
  const encodedSignature = encodeSignature({
8740
- threshold: SIGNATURE_THRESHOLD,
9001
+ threshold: TRANSACTION_SIGNATURE_THRESHOLD,
8741
9002
  signers: [
8742
9003
  {
8743
9004
  weight: SIGNATURE_WEIGHT,
@@ -8753,6 +9014,35 @@ const getSignedMetaTransactions = async (metaTransactions, nonce, chainId, walle
8753
9014
  encodedSignature,
8754
9015
  ]);
8755
9016
  };
9017
+ const decodeRelayerTypedDataSignature = (relayerSignature) => {
9018
+ const signatureWithThreshold = `0000${relayerSignature}`;
9019
+ return decodeSignature(signatureWithThreshold);
9020
+ };
9021
+ const getSignedTypedData = async (typedData, relayerSignature, chainId, walletAddress, signer) => {
9022
+ // Ethers auto-generates the EIP712Domain type in the TypedDataEncoder, and so it needs to be removed
9023
+ const types = { ...typedData.types };
9024
+ // @ts-ignore
9025
+ delete types.EIP712Domain;
9026
+ // eslint-disable-next-line no-underscore-dangle
9027
+ const digest = ethers.utils._TypedDataEncoder.hash(typedData.domain, types, typedData.message);
9028
+ const completePayload = encodeMessageSubDigest(chainId, walletAddress, digest);
9029
+ const hash = ethers.utils.keccak256(completePayload);
9030
+ // Sign the digest
9031
+ const hashArray = ethers.utils.arrayify(hash);
9032
+ const ethsigNoType = await signer.signMessage(hashArray);
9033
+ const signedDigest = `${ethsigNoType}${ETH_SIGN_FLAG}`;
9034
+ const { signers } = decodeRelayerTypedDataSignature(relayerSignature);
9035
+ return encodeSignature({
9036
+ threshold: EIP712_SIGNATURE_THRESHOLD,
9037
+ signers: [
9038
+ ...signers,
9039
+ {
9040
+ weight: SIGNATURE_WEIGHT,
9041
+ signature: signedDigest,
9042
+ },
9043
+ ],
9044
+ });
9045
+ };
8756
9046
  const getEip155ChainId = (chainId) => `eip155:${chainId}`;
8757
9047
 
8758
9048
  class RelayerClient {
@@ -8818,6 +9108,19 @@ class RelayerClient {
8818
9108
  const { result } = await this.postToRelayer(payload);
8819
9109
  return result;
8820
9110
  }
9111
+ async imSignTypedData(address, eip712Payload) {
9112
+ const { chainId } = await this.jsonRpcProvider.ready;
9113
+ const payload = {
9114
+ method: 'im_signTypedData',
9115
+ params: [{
9116
+ address,
9117
+ eip712Payload,
9118
+ chainId: getEip155ChainId(chainId),
9119
+ }],
9120
+ };
9121
+ const { result } = await this.postToRelayer(payload);
9122
+ return result;
9123
+ }
8821
9124
  }
8822
9125
 
8823
9126
  const MESSAGE_TO_SIGN = 'Only sign this message from Immutable Passport';
@@ -8958,6 +9261,60 @@ const sendTransaction = ({ params, magicProvider, jsonRpcProvider, relayerClient
8958
9261
  return relayerTransaction.hash;
8959
9262
  });
8960
9263
 
9264
+ const REQUIRED_TYPED_DATA_PROPERTIES = ['types', 'domain', 'primaryType', 'message'];
9265
+ const isValidTypedDataPayload = (typedData) => (REQUIRED_TYPED_DATA_PROPERTIES.every((key) => key in typedData));
9266
+ const transformTypedData = (typedData, chainId) => {
9267
+ let transformedTypedData;
9268
+ if (typeof typedData === 'string') {
9269
+ try {
9270
+ transformedTypedData = JSON.parse(typedData);
9271
+ }
9272
+ catch (err) {
9273
+ throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, `Failed to parse typed data JSON: ${err}`);
9274
+ }
9275
+ }
9276
+ else if (typeof typedData === 'object') {
9277
+ transformedTypedData = typedData;
9278
+ }
9279
+ else {
9280
+ throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, `Invalid typed data argument: ${typedData}`);
9281
+ }
9282
+ if (!isValidTypedDataPayload(transformedTypedData)) {
9283
+ throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, `Invalid typed data argument. The following properties are required: ${REQUIRED_TYPED_DATA_PROPERTIES.join(', ')}`);
9284
+ }
9285
+ const providedChainId = transformedTypedData.domain?.chainId;
9286
+ if (providedChainId) {
9287
+ // domain.chainId (if defined) can be a number, string, or hex value, but the relayer & guardian only accept a number.
9288
+ if (typeof providedChainId === 'string') {
9289
+ if (providedChainId.startsWith('0x')) {
9290
+ transformedTypedData.domain.chainId = parseInt(providedChainId, 16);
9291
+ }
9292
+ else {
9293
+ transformedTypedData.domain.chainId = parseInt(providedChainId, 10);
9294
+ }
9295
+ }
9296
+ if (transformedTypedData.domain.chainId !== chainId) {
9297
+ throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, `Invalid chainId, expected ${chainId}`);
9298
+ }
9299
+ }
9300
+ return transformedTypedData;
9301
+ };
9302
+ const signTypedDataV4 = async ({ params, method, magicProvider, jsonRpcProvider, relayerClient, guardianClient, user, }) => guardianClient
9303
+ .withConfirmationScreen({ width: 480, height: 730 })(async () => {
9304
+ const fromAddress = params[0];
9305
+ const typedDataParam = params[1];
9306
+ if (!fromAddress || !typedDataParam) {
9307
+ throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, `${method} requires an address and a typed data JSON`);
9308
+ }
9309
+ const { chainId } = await jsonRpcProvider.ready;
9310
+ const typedData = transformTypedData(typedDataParam, chainId);
9311
+ await guardianClient.validateMessage({ chainID: String(chainId), payload: typedData, user });
9312
+ const relayerSignature = await relayerClient.imSignTypedData(fromAddress, typedData);
9313
+ const magicWeb3Provider = new Web3Provider(magicProvider);
9314
+ const signer = magicWeb3Provider.getSigner();
9315
+ return getSignedTypedData(typedData, relayerSignature, BigNumber$1.from(chainId), fromAddress, signer);
9316
+ });
9317
+
8961
9318
  class ZkEvmProvider {
8962
9319
  authManager;
8963
9320
  config;
@@ -9041,6 +9398,21 @@ class ZkEvmProvider {
9041
9398
  case 'eth_accounts': {
9042
9399
  return this.isLoggedIn() ? [this.user.zkEvm.ethAddress] : [];
9043
9400
  }
9401
+ case 'eth_signTypedData':
9402
+ case 'eth_signTypedData_v4': {
9403
+ if (!this.isLoggedIn()) {
9404
+ throw new JsonRpcError(ProviderErrorCode.UNAUTHORIZED, 'Unauthorised - call eth_requestAccounts first');
9405
+ }
9406
+ return signTypedDataV4({
9407
+ method: request.method,
9408
+ params: request.params || [],
9409
+ magicProvider: this.magicProvider,
9410
+ jsonRpcProvider: this.jsonRpcProvider,
9411
+ relayerClient: this.relayerClient,
9412
+ user: this.user,
9413
+ guardianClient: this.guardianClient,
9414
+ });
9415
+ }
9044
9416
  // Pass through methods
9045
9417
  case 'eth_gasPrice':
9046
9418
  case 'eth_getBalance':
@@ -29414,8 +29786,8 @@ const $7d1bfafb81e64d74$export$3a4140bd9e983e4e = async (provider, insufficientI
29414
29786
 
29415
29787
 
29416
29788
 
29417
- const $1fda5c40669a566d$export$1fac8e857d728583 = async ()=>true;
29418
- const $1fda5c40669a566d$export$2e83e9eeaf217e20 = async ()=>true;
29789
+ const $1fda5c40669a566d$export$1fac8e857d728583 = async ()=>false;
29790
+ const $1fda5c40669a566d$export$2e83e9eeaf217e20 = async ()=>false;
29419
29791
 
29420
29792
 
29421
29793
  const $7f2e17f026d4fc8d$var$isPassportProvider = (provider)=>(provider.provider?.isPassport === true) ?? false;
@@ -29598,6 +29970,24 @@ const $07ac9c0576988336$export$a3dd181de896b7c7 = async (config, readOnlyProvide
29598
29970
 
29599
29971
 
29600
29972
 
29973
+
29974
+ const $5a5ccedc98d53d25$var$filterTokens = (allowedTokens, balances)=>{
29975
+ if (balances && balances.success) return allowedTokens.filter((token)=>{
29976
+ if ("address" in token) return balances.balances.find((balance)=>balance.token.address === token.address && balance.balance.gt(0));
29977
+ return balances.balances.find((balance)=>!("address" in balance.token) && balance.balance.gt(0));
29978
+ });
29979
+ return [];
29980
+ };
29981
+ const $5a5ccedc98d53d25$export$d744af9f1c0712bc = async (config, tokenBalances, availableRoutingOptions)=>{
29982
+ if (availableRoutingOptions.bridge) {
29983
+ const allowedTokens = (await config.remote.getConfig("bridge"))?.tokens ?? [];
29984
+ const balances = tokenBalances.get(($4013c5c91bb535f6$export$9b794d067cdd1af6)(config));
29985
+ return $5a5ccedc98d53d25$var$filterTokens(allowedTokens, balances);
29986
+ }
29987
+ return [];
29988
+ };
29989
+
29990
+
29601
29991
  const $fa9ac5bfdbbf9dfa$export$9994ad18c2f0e665 = (balances, totalFees)=>{
29602
29992
  const balance = ($f730af3b727f04ac$export$22fea095b15361de)(balances);
29603
29993
  return balance.gte(totalFees);
@@ -29656,15 +30046,18 @@ const $fa9ac5bfdbbf9dfa$export$ddc7ba2b57d7c5fa = async (config, readOnlyProvide
29656
30046
  chainId: chainId.toString()
29657
30047
  });
29658
30048
  // If no balances on layer 1 then Bridge cannot be an option
29659
- if (tokenBalanceResult === undefined || tokenBalanceResult.success === false) throw new ($a8bc256d81a5e2c1$export$b722478a3cbfa3bc)("Error getting balances", ($a8bc256d81a5e2c1$export$e3dc0620abde7f5a).GET_BALANCE_ERROR, {
29660
- chainId: chainId.toString()
29661
- });
29662
- if (tokenBalanceResult.balances.length === 0) return undefined;
30049
+ if (tokenBalanceResult === undefined || tokenBalanceResult.success === false) return undefined;
30050
+ const allowedTokenList = await ($5a5ccedc98d53d25$export$d744af9f1c0712bc)(config, balances, availableRoutingOptions);
30051
+ if (allowedTokenList.length === 0) return undefined;
29663
30052
  const bridgeFeeEstimate = await $fa9ac5bfdbbf9dfa$export$da05aed50d75046(config, readOnlyProviders, feeEstimates);
29664
30053
  // If the user has no ETH to cover the bridge fees or approval fees then bridge cannot be an option
29665
30054
  if (!$fa9ac5bfdbbf9dfa$export$9994ad18c2f0e665(tokenBalanceResult, bridgeFeeEstimate)) return undefined;
29666
30055
  const l1address = await $fa9ac5bfdbbf9dfa$export$952cdf461a00a8c6(config, balanceRequirement);
29667
30056
  if (l1address === "") return undefined;
30057
+ // Ensure l1address is in the allowed token list
30058
+ if (l1address === ($823db9fb0ca4bc15$export$c37d8687c27b9660)) {
30059
+ if (!allowedTokenList.find((token)=>!("address" in token))) return undefined;
30060
+ } else if (!allowedTokenList.find((token)=>token.address === l1address)) return undefined;
29668
30061
  const gasForApproval = await ($07ac9c0576988336$export$a3dd181de896b7c7)(config, readOnlyProviders, l1provider, depositorAddress, l1address, balanceRequirement.delta.balance);
29669
30062
  if (!$fa9ac5bfdbbf9dfa$export$9994ad18c2f0e665(tokenBalanceResult, gasForApproval.add(bridgeFeeEstimate))) return undefined;
29670
30063
  // If the L1 representation of the requirement is ETH then find the ETH balance and check if the balance covers the delta
@@ -29720,7 +30113,6 @@ const $c16168a9c28ae4fd$export$92606e71d0a264ff = async (config, ownerAddress, b
29720
30113
  });
29721
30114
  }
29722
30115
  const tokenBalances = await ($33acec7b4a26c053$export$23ddeb2642d2f9d)(config, readOnlyProviders, ownerAddress, availableRoutingOptions);
29723
- // Get allowed tokens?
29724
30116
  // Bridge and swap fee cache
29725
30117
  const feeEstimates = new Map();
29726
30118
  // Ensures only 1 balance requirement is insufficient otherwise one bridge route cannot be recommended
@@ -30467,31 +30859,30 @@ var checkout_sdk = /*#__PURE__*/Object.freeze({
30467
30859
  function $parcel$export(e, n, v, s) {
30468
30860
  Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true});
30469
30861
  }
30470
- const $d663162fd5a0853f$export$38a083d9fb5551ca = "0.17.5";
30862
+ const $d663162fd5a0853f$export$38a083d9fb5551ca = "0.18.0";
30471
30863
  const $d663162fd5a0853f$export$83bf90b30cdfd29f = ()=>false;
30472
30864
  const $d663162fd5a0853f$export$1169f5475725171b = ()=>$d663162fd5a0853f$export$38a083d9fb5551ca;
30473
30865
 
30474
30866
 
30475
30867
  function $430e3eda76fa4d5f$export$46b1ae20f762ad4c(version) {
30476
30868
  const defaultPackageVersion = ($d663162fd5a0853f$export$1169f5475725171b)();
30477
- if (version === undefined) return defaultPackageVersion;
30478
- // Pre-production release
30479
- // TODO: https://immutable.atlassian.net/browse/WT-1501
30480
- if (version.major === undefined || version.minor === undefined || version.patch === undefined || version.prerelease === undefined) return defaultPackageVersion;
30481
- if (version.major < 0) return defaultPackageVersion;
30482
- if (version.minor < 0) return defaultPackageVersion;
30483
- if (version.patch < 0) return defaultPackageVersion;
30484
- if (version.prerelease !== "alpha") return defaultPackageVersion;
30869
+ if (version === undefined || version.major === undefined) return defaultPackageVersion;
30870
+ if (!Number.isInteger(version.major) || version.major < 0) return defaultPackageVersion;
30871
+ if (version.minor !== undefined && version.minor < 0) return defaultPackageVersion;
30872
+ if (version.patch !== undefined && version.patch < 0) return defaultPackageVersion;
30873
+ if (version.major === 0 && version.minor === undefined) return defaultPackageVersion;
30874
+ if (version.major === 0 && version.minor === 0 && version.patch === undefined) return defaultPackageVersion;
30875
+ if (version.major === 0 && version.minor === undefined && version.patch === undefined) return defaultPackageVersion;
30485
30876
  if (version.major === 0 && version.minor === 0 && version.patch === 0) return defaultPackageVersion;
30486
- let validatedVersion = defaultPackageVersion;
30487
- if (!Number.isNaN(version.major) && version.major >= 0) validatedVersion = version.major.toString();
30488
- if (!Number.isNaN(version.minor)) validatedVersion += `.${version.minor.toString()}`;
30489
- if (!Number.isNaN(version.patch)) validatedVersion += `.${version.patch.toString()}`;
30490
- // TODO: https://immutable.atlassian.net/browse/WT-1501
30491
- // Ensure this is gated by `version.prerelease !== undefined`
30492
- // once we go to prod with checkout.
30493
- validatedVersion += `-${version.prerelease}`;
30494
- if (version.build !== undefined && version.build > 0) validatedVersion += `.${version.build}`;
30877
+ let validatedVersion = version.major.toString();
30878
+ if (version.minor === undefined) return validatedVersion;
30879
+ if (Number.isInteger(version.minor)) validatedVersion += `.${version.minor.toString()}`;
30880
+ if (version.patch === undefined) return validatedVersion;
30881
+ if (Number.isInteger(version.patch)) validatedVersion += `.${version.patch.toString()}`;
30882
+ if (version.prerelease === undefined || version.prerelease !== "alpha") return validatedVersion;
30883
+ if (version.prerelease === "alpha") validatedVersion += `-${version.prerelease}`;
30884
+ if (version.build === undefined) return validatedVersion;
30885
+ if (Number.isInteger(version.build) && version.build >= 0) validatedVersion += `.${version.build.toString()}`;
30495
30886
  return validatedVersion;
30496
30887
  }
30497
30888
  function $430e3eda76fa4d5f$export$af210a0808087845(config) {