@imtbl/sdk 0.3.0 → 0.3.2-alpha

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.
@@ -10352,14 +10352,14 @@ declare class ImmutableXClient {
10352
10352
  * @returns a promise that resolves with the requested Order
10353
10353
  * @throws {@link index.IMXError}
10354
10354
  */
10355
- getOrder(request: OrdersApiGetOrderRequest): Promise<Order>;
10355
+ getOrder(request: OrdersApiGetOrderRequest): Promise<OrderV3>;
10356
10356
  /**
10357
10357
  * Get a list of Orders
10358
10358
  * @param request - optional object containing the parameters to be provided in the API request
10359
10359
  * @returns a promise that resolves with the requested list of Orders
10360
10360
  * @throws {@link index.IMXError}
10361
10361
  */
10362
- listOrders(request?: OrdersApiListOrdersRequest): Promise<ListOrdersResponse>;
10362
+ listOrders(request?: OrdersApiListOrdersRequest): Promise<ListOrdersResponseV3>;
10363
10363
  /**
10364
10364
  * Get details of a Trade with the given ID
10365
10365
  * @param request - the request object containing the parameters to be provided in the API request
@@ -10509,19 +10509,27 @@ type DeviceTokenResponse = {
10509
10509
  expires_in: number;
10510
10510
  };
10511
10511
 
10512
+ /**
10513
+ * ProviderErrors should take priority over RpcErrorCodes
10514
+ */
10515
+ declare enum ProviderErrorCode {
10516
+ USER_REJECTED_REQUEST = 4001,
10517
+ UNAUTHORIZED = 4100,
10518
+ UNSUPPORTED_METHOD = 4200,
10519
+ DISCONNECTED = 4900
10520
+ }
10512
10521
  declare enum RpcErrorCode {
10513
10522
  RPC_SERVER_ERROR = -32000,
10514
10523
  INVALID_REQUEST = -32600,
10515
10524
  METHOD_NOT_FOUND = -32601,
10516
10525
  INVALID_PARAMS = -32602,
10517
10526
  INTERNAL_ERROR = -32603,
10518
- UNAUTHORIZED = -32604,
10519
10527
  PARSE_ERROR = -32700
10520
10528
  }
10521
10529
  declare class JsonRpcError extends Error {
10522
10530
  readonly message: string;
10523
- readonly code: RpcErrorCode;
10524
- constructor(code: RpcErrorCode, message: string);
10531
+ readonly code: ProviderErrorCode | RpcErrorCode;
10532
+ constructor(code: ProviderErrorCode | RpcErrorCode, message: string);
10525
10533
  }
10526
10534
 
10527
10535
  interface RequestArguments {
@@ -10545,7 +10553,13 @@ type Provider = {
10545
10553
  request: (request: RequestArguments) => Promise<any>;
10546
10554
  sendAsync: (request: JsonRpcRequestPayload | JsonRpcRequestPayload[], callback: JsonRpcRequestCallback) => void;
10547
10555
  send: (request: string | JsonRpcRequestPayload | JsonRpcRequestPayload[], callbackOrParams?: JsonRpcRequestCallback | Array<any>, callback?: JsonRpcRequestCallback) => void;
10556
+ on: (event: string, listener: (...args: any[]) => void) => void;
10557
+ removeListener: (event: string, listener: (...args: any[]) => void) => void;
10548
10558
  };
10559
+ declare enum ProviderEvent {
10560
+ ACCOUNTS_CHANGED = "accountsChanged"
10561
+ }
10562
+ type AccountsChangedEvent = Array<string>;
10549
10563
 
10550
10564
  declare class Passport {
10551
10565
  private readonly authManager;
@@ -10580,4 +10594,4 @@ declare class Passport {
10580
10594
  getAccessToken(): Promise<string | undefined>;
10581
10595
  }
10582
10596
 
10583
- export { DeviceConnectResponse, DeviceTokenResponse, JsonRpcRequestCallback, JsonRpcRequestPayload, JsonRpcResponsePayload, Networks, Passport, PassportError, PassportModuleConfiguration, PassportOverrides, Provider, RequestArguments, UserProfile };
10597
+ export { AccountsChangedEvent, DeviceConnectResponse, DeviceTokenResponse, JsonRpcError, JsonRpcRequestCallback, JsonRpcRequestPayload, JsonRpcResponsePayload, Networks, Passport, PassportError, PassportModuleConfiguration, PassportOverrides, Provider, ProviderErrorCode, ProviderEvent, RequestArguments, RpcErrorCode, UserProfile };
package/dist/passport.js CHANGED
@@ -7,6 +7,7 @@ import { OpenIdExtension } from '@magic-ext/oidc';
7
7
  import BN from 'bn.js';
8
8
  import * as encUtils from 'enc-utils';
9
9
  import { Web3Provider, JsonRpcProvider } from '@ethersproject/providers';
10
+ import { EventEmitter } from 'events';
10
11
  import { ethers, BigNumber } from 'ethers';
11
12
  import { walletContracts } from '@0xsequence/abi';
12
13
  import { encodeSignature } from '@0xsequence/config';
@@ -4606,7 +4607,7 @@ class MultiRollupApiClients {
4606
4607
  }
4607
4608
 
4608
4609
  // eslint-disable-next-line @typescript-eslint/naming-convention
4609
- const defaultHeaders = { 'x-sdk-version': 'ts-immutable-sdk-0.0.0' };
4610
+ const defaultHeaders = { 'x-sdk-version': 'ts-immutable-sdk-0.3.2-alpha' };
4610
4611
  const createConfig = ({ basePath, headers, }) => {
4611
4612
  if (!basePath.trim()) {
4612
4613
  throw Error('basePath can not be empty');
@@ -4662,7 +4663,7 @@ const createImmutableXConfiguration = ({ basePath, chainID, coreContractAddress,
4662
4663
  chainID,
4663
4664
  coreContractAddress,
4664
4665
  registrationContractAddress,
4665
- sdkVersion: 'ts-immutable-sdk-0.0.0',
4666
+ sdkVersion: 'ts-immutable-sdk-0.3.2-alpha',
4666
4667
  });
4667
4668
  /**
4668
4669
  * Sets `sdkVersion` at the time of build
@@ -8386,6 +8387,8 @@ var globalAxios = axios;
8386
8387
  * https://openapi-generator.tech
8387
8388
  * Do not edit the class manually.
8388
8389
  */
8390
+ // Some imports not used depending on template conditions
8391
+ // @ts-ignore
8389
8392
  const BASE_PATH = "https://guardian.sandbox.imtbl.com".replace(/\/+$/, "");
8390
8393
  /**
8391
8394
  *
@@ -8413,10 +8416,10 @@ class BaseAPI {
8413
8416
  */
8414
8417
  class RequiredError extends Error {
8415
8418
  field;
8419
+ name = "RequiredError";
8416
8420
  constructor(field, msg) {
8417
8421
  super(msg);
8418
8422
  this.field = field;
8419
- this.name = "RequiredError";
8420
8423
  }
8421
8424
  }
8422
8425
 
@@ -8461,8 +8464,6 @@ const setBearerAuthToObject = async function (object, configuration) {
8461
8464
  }
8462
8465
  };
8463
8466
  function setFlattenedQueryParams(urlSearchParams, parameter, key = "") {
8464
- if (parameter == null)
8465
- return;
8466
8467
  if (typeof parameter === "object") {
8467
8468
  if (Array.isArray(parameter)) {
8468
8469
  parameter.forEach(item => setFlattenedQueryParams(urlSearchParams, item, key));
@@ -8618,7 +8619,7 @@ const TransactionsApiAxiosParamCreator = function (configuration) {
8618
8619
  * @summary Info for a specific transaction
8619
8620
  * @param {string} transactionID The id of the starkex transaction to retrieve
8620
8621
  * @param {'starkex' | 'evm'} chainType roll up type
8621
- * @param {number} [chainID] ID of evm chain
8622
+ * @param {string} [chainID] ID of evm chain
8622
8623
  * @param {*} [options] Override http request option.
8623
8624
  * @throws {RequiredError}
8624
8625
  */
@@ -8693,7 +8694,7 @@ const TransactionsApiFp = function (configuration) {
8693
8694
  * @summary Info for a specific transaction
8694
8695
  * @param {string} transactionID The id of the starkex transaction to retrieve
8695
8696
  * @param {'starkex' | 'evm'} chainType roll up type
8696
- * @param {number} [chainID] ID of evm chain
8697
+ * @param {string} [chainID] ID of evm chain
8697
8698
  * @param {*} [options] Override http request option.
8698
8699
  * @throws {RequiredError}
8699
8700
  */
@@ -9371,6 +9372,7 @@ async function createOrder({ starkSigner, user, request, ordersApi, guardianClie
9371
9372
  amount_sell: amountSell,
9372
9373
  token_sell: convertToSignableToken(request.sell),
9373
9374
  fees: request.fees,
9375
+ split_fees: true,
9374
9376
  expiration_timestamp: request.expiration_timestamp,
9375
9377
  };
9376
9378
  const getSignableOrderResponse = await ordersApi.getSignableOrder({
@@ -9884,7 +9886,7 @@ class PassportConfiguration {
9884
9886
  this.imxPublicApiDomain = 'https://api.immutable.com';
9885
9887
  this.zkEvmRpcUrl = ''; // TODO: ID-785 Update once mainnet has been deployed
9886
9888
  this.zkEvmChainId = ''; // TODO: ID-785 Update once mainnet has been deployed
9887
- this.relayerUrl = 'https://relayer.immutable.com'; // TODO: ID-784 Update once we have added Relayer URL to config
9889
+ this.relayerUrl = 'https://api.immutable.com/relayer-mr';
9888
9890
  this.multiRollupConfig = multiRollupConfig.getProduction();
9889
9891
  break;
9890
9892
  }
@@ -9898,7 +9900,7 @@ class PassportConfiguration {
9898
9900
  this.imxPublicApiDomain = 'https://api.sandbox.immutable.com';
9899
9901
  this.zkEvmRpcUrl = 'https://zkevm-rpc.sandbox.x.immutable.com';
9900
9902
  this.zkEvmChainId = 'eip155:13392';
9901
- this.relayerUrl = 'https://evm-relayer.sandbox.imtbl.com'; // TODO: ID-784 Update once we have added Relayer URL to config
9903
+ this.relayerUrl = 'https://api.sandbox.immutable.com/relayer-mr';
9902
9904
  this.multiRollupConfig = multiRollupConfig.getSandbox();
9903
9905
  break;
9904
9906
  }
@@ -10060,6 +10062,169 @@ class ConfirmationScreen {
10060
10062
  }
10061
10063
  }
10062
10064
 
10065
+ var RelayerTransactionStatus;
10066
+ (function (RelayerTransactionStatus) {
10067
+ RelayerTransactionStatus["PENDING"] = "PENDING";
10068
+ RelayerTransactionStatus["SUBMITTED"] = "SUBMITTED";
10069
+ RelayerTransactionStatus["SUCCESSFUL"] = "SUCCESSFUL";
10070
+ RelayerTransactionStatus["REVERTED"] = "REVERTED";
10071
+ RelayerTransactionStatus["FAILED"] = "FAILED";
10072
+ })(RelayerTransactionStatus || (RelayerTransactionStatus = {}));
10073
+ var ProviderEvent;
10074
+ (function (ProviderEvent) {
10075
+ ProviderEvent["ACCOUNTS_CHANGED"] = "accountsChanged";
10076
+ })(ProviderEvent || (ProviderEvent = {}));
10077
+
10078
+ class TypedEventEmitter {
10079
+ emitter = new EventEmitter();
10080
+ emit(eventName, ...eventArg) {
10081
+ this.emitter.emit(eventName, ...eventArg);
10082
+ }
10083
+ on(eventName, handler) {
10084
+ this.emitter.on(eventName, handler);
10085
+ }
10086
+ removeListener(eventName, handler) {
10087
+ this.emitter.removeListener(eventName, handler);
10088
+ }
10089
+ }
10090
+
10091
+ class RelayerClient {
10092
+ config;
10093
+ constructor({ config }) {
10094
+ this.config = config;
10095
+ }
10096
+ async postToRelayer(request) {
10097
+ const body = {
10098
+ id: 1,
10099
+ jsonrpc: '2.0',
10100
+ ...request,
10101
+ };
10102
+ const response = await fetch(`${this.config.relayerUrl}/v1/transactions`, {
10103
+ method: 'POST',
10104
+ headers: {
10105
+ 'Content-Type': 'application/json',
10106
+ },
10107
+ body: JSON.stringify(body),
10108
+ });
10109
+ const jsonResponse = await response.json();
10110
+ if (jsonResponse.error) {
10111
+ throw jsonResponse.error;
10112
+ }
10113
+ return jsonResponse;
10114
+ }
10115
+ async ethSendTransaction(to, data) {
10116
+ const payload = {
10117
+ method: 'eth_sendTransaction',
10118
+ params: [{
10119
+ to,
10120
+ data,
10121
+ chainId: this.config.zkEvmChainId.toString(),
10122
+ }],
10123
+ };
10124
+ const { result } = await this.postToRelayer(payload);
10125
+ return result;
10126
+ }
10127
+ async imGetTransactionByHash(hash) {
10128
+ const payload = {
10129
+ method: 'im_getTransactionByHash',
10130
+ params: [hash],
10131
+ };
10132
+ const { result } = await this.postToRelayer(payload);
10133
+ return result;
10134
+ }
10135
+ async imGetFeeOptions(userAddress, data) {
10136
+ const payload = {
10137
+ method: 'im_getFeeOptions',
10138
+ params: [{
10139
+ userAddress,
10140
+ data,
10141
+ chainId: this.config.zkEvmChainId.toString(),
10142
+ }],
10143
+ };
10144
+ const { result } = await this.postToRelayer(payload);
10145
+ return result;
10146
+ }
10147
+ }
10148
+
10149
+ /**
10150
+ * ProviderErrors should take priority over RpcErrorCodes
10151
+ */
10152
+ var ProviderErrorCode;
10153
+ (function (ProviderErrorCode) {
10154
+ ProviderErrorCode[ProviderErrorCode["USER_REJECTED_REQUEST"] = 4001] = "USER_REJECTED_REQUEST";
10155
+ ProviderErrorCode[ProviderErrorCode["UNAUTHORIZED"] = 4100] = "UNAUTHORIZED";
10156
+ ProviderErrorCode[ProviderErrorCode["UNSUPPORTED_METHOD"] = 4200] = "UNSUPPORTED_METHOD";
10157
+ ProviderErrorCode[ProviderErrorCode["DISCONNECTED"] = 4900] = "DISCONNECTED";
10158
+ })(ProviderErrorCode || (ProviderErrorCode = {}));
10159
+ var RpcErrorCode;
10160
+ (function (RpcErrorCode) {
10161
+ RpcErrorCode[RpcErrorCode["RPC_SERVER_ERROR"] = -32000] = "RPC_SERVER_ERROR";
10162
+ RpcErrorCode[RpcErrorCode["INVALID_REQUEST"] = -32600] = "INVALID_REQUEST";
10163
+ RpcErrorCode[RpcErrorCode["METHOD_NOT_FOUND"] = -32601] = "METHOD_NOT_FOUND";
10164
+ RpcErrorCode[RpcErrorCode["INVALID_PARAMS"] = -32602] = "INVALID_PARAMS";
10165
+ RpcErrorCode[RpcErrorCode["INTERNAL_ERROR"] = -32603] = "INTERNAL_ERROR";
10166
+ RpcErrorCode[RpcErrorCode["PARSE_ERROR"] = -32700] = "PARSE_ERROR";
10167
+ })(RpcErrorCode || (RpcErrorCode = {}));
10168
+ class JsonRpcError extends Error {
10169
+ message;
10170
+ code;
10171
+ constructor(code, message) {
10172
+ super(message);
10173
+ this.message = message;
10174
+ this.code = code;
10175
+ }
10176
+ }
10177
+
10178
+ const MESSAGE_TO_SIGN = 'Only sign this message from Immutable Passport';
10179
+ async function registerZkEvmUser({ authManager, magicProvider, multiRollupApiClients, accessToken, }) {
10180
+ const web3Provider = new Web3Provider(magicProvider);
10181
+ const ethSigner = web3Provider.getSigner();
10182
+ const ethereumAddress = await ethSigner.getAddress();
10183
+ const ethereumSignature = await signRaw(MESSAGE_TO_SIGN, ethSigner);
10184
+ const headers = { Authorization: `Bearer ${accessToken}` };
10185
+ try {
10186
+ await multiRollupApiClients.passportApi.createCounterfactualAddress({
10187
+ createCounterfactualAddressRequest: {
10188
+ ethereumAddress,
10189
+ ethereumSignature,
10190
+ },
10191
+ }, { headers });
10192
+ }
10193
+ catch (error) {
10194
+ throw new JsonRpcError(RpcErrorCode.INTERNAL_ERROR, `Failed to create counterfactual address: ${error}`);
10195
+ }
10196
+ const user = await authManager.loginSilent();
10197
+ if (!user?.zkEvm) {
10198
+ throw new JsonRpcError(RpcErrorCode.INTERNAL_ERROR, 'Failed to refresh user details');
10199
+ }
10200
+ return user;
10201
+ }
10202
+
10203
+ const loginZkEvmUser = async ({ authManager, config, magicAdapter, multiRollupApiClients, }) => {
10204
+ const user = await authManager.getUser() || await authManager.login();
10205
+ if (!user.idToken) {
10206
+ throw new Error('User is missing idToken');
10207
+ }
10208
+ const magicProvider = await magicAdapter.login(user.idToken, config.network);
10209
+ if (!user.zkEvm) {
10210
+ // Generate counterfactual address and retrieve updated Auth0 user
10211
+ const userZkevm = await registerZkEvmUser({
10212
+ authManager,
10213
+ magicProvider,
10214
+ multiRollupApiClients,
10215
+ accessToken: user.accessToken,
10216
+ });
10217
+ return {
10218
+ user: userZkevm,
10219
+ magicProvider,
10220
+ };
10221
+ }
10222
+ return {
10223
+ user: user,
10224
+ magicProvider,
10225
+ };
10226
+ };
10227
+
10063
10228
  // These are ignored by the Relayer but for consistency we set them to the
10064
10229
  // appropriate values for a 1/1 wallet.
10065
10230
  //
@@ -10092,7 +10257,7 @@ function digestOfTransactionsAndNonce(nonce, normalisedTransactions) {
10092
10257
  return ethers.utils.keccak256(packMetaTransactionsNonceData);
10093
10258
  }
10094
10259
  const getNonce = async (jsonRpcProvider, smartContractWalletAddress) => {
10095
- const code = await jsonRpcProvider.send('eth_getCode', [smartContractWalletAddress]);
10260
+ const code = await jsonRpcProvider.send('eth_getCode', [smartContractWalletAddress, 'latest']);
10096
10261
  if (code && code !== '0x') {
10097
10262
  const contract = new ethers.Contract(smartContractWalletAddress, walletContracts.mainModule.abi, jsonRpcProvider);
10098
10263
  return contract.nonce();
@@ -10135,38 +10300,48 @@ const chainIdNumber = (chainId) => {
10135
10300
  return BigNumber.from(caip2Components[1]);
10136
10301
  };
10137
10302
 
10138
- var RelayerTransactionStatus;
10139
- (function (RelayerTransactionStatus) {
10140
- RelayerTransactionStatus["PENDING"] = "PENDING";
10141
- RelayerTransactionStatus["SUBMITTED"] = "SUBMITTED";
10142
- RelayerTransactionStatus["SUCCESSFUL"] = "SUCCESSFUL";
10143
- RelayerTransactionStatus["REVERTED"] = "REVERTED";
10144
- RelayerTransactionStatus["FAILED"] = "FAILED";
10145
- })(RelayerTransactionStatus || (RelayerTransactionStatus = {}));
10146
-
10147
- var RpcErrorCode;
10148
- (function (RpcErrorCode) {
10149
- RpcErrorCode[RpcErrorCode["RPC_SERVER_ERROR"] = -32000] = "RPC_SERVER_ERROR";
10150
- RpcErrorCode[RpcErrorCode["INVALID_REQUEST"] = -32600] = "INVALID_REQUEST";
10151
- RpcErrorCode[RpcErrorCode["METHOD_NOT_FOUND"] = -32601] = "METHOD_NOT_FOUND";
10152
- RpcErrorCode[RpcErrorCode["INVALID_PARAMS"] = -32602] = "INVALID_PARAMS";
10153
- RpcErrorCode[RpcErrorCode["INTERNAL_ERROR"] = -32603] = "INTERNAL_ERROR";
10154
- RpcErrorCode[RpcErrorCode["UNAUTHORIZED"] = -32604] = "UNAUTHORIZED";
10155
- RpcErrorCode[RpcErrorCode["PARSE_ERROR"] = -32700] = "PARSE_ERROR";
10156
- })(RpcErrorCode || (RpcErrorCode = {}));
10157
- class JsonRpcError extends Error {
10158
- message;
10159
- code;
10160
- constructor(code, message) {
10161
- super(message);
10162
- this.message = message;
10163
- this.code = code;
10164
- }
10165
- }
10166
-
10167
10303
  const MAX_TRANSACTION_HASH_RETRIEVAL_RETRIES = 30;
10168
10304
  const TRANSACTION_HASH_RETRIEVAL_WAIT = 1000;
10169
- const ethSendTransaction = async ({ params, magicProvider, jsonRpcProvider, relayerClient, config, user, }) => {
10305
+ const converBigNumberishToNumber = (value) => BigNumber.from(value).toNumber();
10306
+ const transformGardianTransactions = (txs) => {
10307
+ try {
10308
+ return txs.map((t) => ({
10309
+ delegateCall: t.delegateCall === true,
10310
+ revertOnError: t.revertOnError === true,
10311
+ gasLimit: t.gasLimit ? converBigNumberishToNumber(t.gasLimit).toString() : '0',
10312
+ target: t.to ?? ethers.constants.AddressZero,
10313
+ value: t.value ? converBigNumberishToNumber(t.value).toString() : '0',
10314
+ data: t.data ? t.data.toString() : '0x00',
10315
+ }));
10316
+ }
10317
+ catch (error) {
10318
+ const errorMessage = (error instanceof Error) ? error.message : String(error);
10319
+ throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, `Transaction failed to parsing: ${errorMessage}`);
10320
+ }
10321
+ };
10322
+ const guardianValidation = async ({ transactionAPI, chainId, nonce, user, metaTransactions, }) => {
10323
+ const headers = { Authorization: `Bearer ${user.accessToken}` };
10324
+ const guardianTransactions = transformGardianTransactions(metaTransactions);
10325
+ try {
10326
+ await transactionAPI.evaluateTransaction({
10327
+ id: 'evm',
10328
+ transactionEvaluationRequest: {
10329
+ chainType: 'evm',
10330
+ chainId,
10331
+ transactionData: {
10332
+ nonce,
10333
+ userAddress: user.zkEvm.ethAddress,
10334
+ metaTransactions: guardianTransactions,
10335
+ },
10336
+ },
10337
+ }, { headers });
10338
+ }
10339
+ catch (error) {
10340
+ const errorMessage = (error instanceof Error) ? error.message : String(error);
10341
+ throw new JsonRpcError(RpcErrorCode.INTERNAL_ERROR, `Transaction failed to validate with error: ${errorMessage}`);
10342
+ }
10343
+ };
10344
+ const sendTransaction = async ({ params, magicProvider, jsonRpcProvider, relayerClient, transactionAPI, config, user, }) => {
10170
10345
  const transactionRequest = params[0];
10171
10346
  if (!transactionRequest.to) {
10172
10347
  throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, 'eth_sendTransaction requires a "to" field');
@@ -10204,6 +10379,13 @@ const ethSendTransaction = async ({ params, magicProvider, jsonRpcProvider, rela
10204
10379
  value: imxFeeOption.tokenPrice,
10205
10380
  revertOnError: true,
10206
10381
  };
10382
+ await guardianValidation({
10383
+ transactionAPI,
10384
+ chainId: config.zkEvmChainId,
10385
+ nonce: converBigNumberishToNumber(nonce),
10386
+ user,
10387
+ metaTransactions: [metaTransaction, feeMetaTransaction],
10388
+ });
10207
10389
  // NOTE: We sign again because we now are adding the fee transaction, so the
10208
10390
  // whole payload is different and needs a new signature.
10209
10391
  const signedTransactions = await getSignedMetaTransactions([metaTransaction, feeMetaTransaction], nonce, chainId, user.zkEvm.ethAddress, signer);
@@ -10231,122 +10413,16 @@ const ethSendTransaction = async ({ params, magicProvider, jsonRpcProvider, rela
10231
10413
  return relayerTransaction.hash;
10232
10414
  };
10233
10415
 
10234
- class RelayerClient {
10235
- config;
10236
- constructor({ config }) {
10237
- this.config = config;
10238
- }
10239
- async postToRelayer(request) {
10240
- const body = {
10241
- id: 1,
10242
- jsonrpc: '2.0',
10243
- ...request,
10244
- };
10245
- const response = await fetch(`${this.config.relayerUrl}/v1/transactions`, {
10246
- method: 'POST',
10247
- headers: {
10248
- 'Content-Type': 'application/json',
10249
- },
10250
- body: JSON.stringify(body),
10251
- });
10252
- const jsonResponse = await response.json();
10253
- if (jsonResponse.error) {
10254
- throw jsonResponse.error;
10255
- }
10256
- return jsonResponse;
10257
- }
10258
- async ethSendTransaction(to, data) {
10259
- const payload = {
10260
- method: 'eth_sendTransaction',
10261
- params: [{
10262
- to,
10263
- data,
10264
- chainId: this.config.zkEvmChainId.toString(),
10265
- }],
10266
- };
10267
- const { result } = await this.postToRelayer(payload);
10268
- return result;
10269
- }
10270
- async imGetTransactionByHash(hash) {
10271
- const payload = {
10272
- method: 'im_getTransactionByHash',
10273
- params: [hash],
10274
- };
10275
- const { result } = await this.postToRelayer(payload);
10276
- return result;
10277
- }
10278
- async imGetFeeOptions(userAddress, data) {
10279
- const payload = {
10280
- method: 'im_getFeeOptions',
10281
- params: [{
10282
- userAddress,
10283
- data,
10284
- chainId: this.config.zkEvmChainId.toString(),
10285
- }],
10286
- };
10287
- const { result } = await this.postToRelayer(payload);
10288
- return result;
10289
- }
10290
- }
10291
-
10292
- const MESSAGE_TO_SIGN = 'Only sign this message from Immutable Passport';
10293
- async function createCounterfactualAddress({ authManager, magicProvider, multiRollupApiClients, accessToken, }) {
10294
- const web3Provider = new Web3Provider(magicProvider);
10295
- const ethSigner = web3Provider.getSigner();
10296
- const ethereumAddress = await ethSigner.getAddress();
10297
- const ethereumSignature = await signRaw(MESSAGE_TO_SIGN, ethSigner);
10298
- const headers = { Authorization: `Bearer ${accessToken}` };
10299
- try {
10300
- await multiRollupApiClients.passportApi.createCounterfactualAddress({
10301
- createCounterfactualAddressRequest: {
10302
- ethereumAddress,
10303
- ethereumSignature,
10304
- },
10305
- }, { headers });
10306
- }
10307
- catch (error) {
10308
- throw new JsonRpcError(RpcErrorCode.INTERNAL_ERROR, `Failed to create counterfactual address: ${error}`);
10309
- }
10310
- const user = await authManager.loginSilent();
10311
- if (!user?.zkEvm) {
10312
- throw new JsonRpcError(RpcErrorCode.INTERNAL_ERROR, 'Failed to refresh user details');
10313
- }
10314
- return user;
10315
- }
10316
-
10317
- const registerZkEvmUser = async ({ authManager, config, magicAdapter, multiRollupApiClients, }) => {
10318
- const user = await authManager.getUser() || await authManager.login();
10319
- if (!user.idToken) {
10320
- throw new Error('User is missing idToken');
10321
- }
10322
- const magicProvider = await magicAdapter.login(user.idToken, config.network);
10323
- if (!user.zkEvm) {
10324
- // Generate counterfactual address and retrieve updated Auth0 user
10325
- const userZkevm = await createCounterfactualAddress({
10326
- authManager,
10327
- magicProvider,
10328
- multiRollupApiClients,
10329
- accessToken: user.accessToken,
10330
- });
10331
- return {
10332
- user: userZkevm,
10333
- magicProvider,
10334
- };
10335
- }
10336
- return {
10337
- user: user,
10338
- magicProvider,
10339
- };
10340
- };
10341
-
10342
10416
  class ZkEvmProvider {
10343
10417
  authManager;
10344
10418
  config;
10345
10419
  confirmationScreen;
10346
10420
  magicAdapter;
10347
10421
  relayerClient;
10422
+ transactionAPI;
10348
10423
  multiRollupApiClients;
10349
- jsonRpcProvider; // Used for read operations
10424
+ jsonRpcProvider; // Used for read
10425
+ eventEmitter;
10350
10426
  magicProvider; // Used for signing
10351
10427
  user;
10352
10428
  constructor({ authManager, magicAdapter, config, confirmationScreen, multiRollupApiClients, }) {
@@ -10355,32 +10431,23 @@ class ZkEvmProvider {
10355
10431
  this.config = config;
10356
10432
  this.confirmationScreen = confirmationScreen;
10357
10433
  this.relayerClient = new RelayerClient({ config });
10434
+ this.transactionAPI = new TransactionsApi(new Configuration({
10435
+ basePath: this.config.imxPublicApiDomain,
10436
+ }));
10358
10437
  this.jsonRpcProvider = new JsonRpcProvider(this.config.zkEvmRpcUrl);
10359
10438
  this.multiRollupApiClients = multiRollupApiClients;
10439
+ this.eventEmitter = new TypedEventEmitter();
10360
10440
  }
10361
10441
  isLoggedIn() {
10362
10442
  return this.magicProvider !== undefined && this.user !== undefined;
10363
10443
  }
10364
10444
  async performRequest(request) {
10365
- const authWrapper = (fn) => {
10366
- if (!this.isLoggedIn()) {
10367
- throw new JsonRpcError(RpcErrorCode.UNAUTHORIZED, 'Unauthorised - call eth_requestAccounts first');
10368
- }
10369
- return fn({
10370
- params: request.params || [],
10371
- magicProvider: this.magicProvider,
10372
- jsonRpcProvider: this.jsonRpcProvider,
10373
- config: this.config,
10374
- relayerClient: this.relayerClient,
10375
- user: this.user,
10376
- });
10377
- };
10378
10445
  switch (request.method) {
10379
10446
  case 'eth_requestAccounts': {
10380
10447
  if (this.isLoggedIn()) {
10381
10448
  return [this.user.zkEvm.ethAddress];
10382
10449
  }
10383
- const { magicProvider, user } = await registerZkEvmUser({
10450
+ const { magicProvider, user } = await loginZkEvmUser({
10384
10451
  authManager: this.authManager,
10385
10452
  config: this.config,
10386
10453
  magicAdapter: this.magicAdapter,
@@ -10388,10 +10455,22 @@ class ZkEvmProvider {
10388
10455
  });
10389
10456
  this.user = user;
10390
10457
  this.magicProvider = magicProvider;
10458
+ this.eventEmitter.emit(ProviderEvent.ACCOUNTS_CHANGED, [this.user.zkEvm.ethAddress]);
10391
10459
  return [this.user.zkEvm.ethAddress];
10392
10460
  }
10393
10461
  case 'eth_sendTransaction': {
10394
- return authWrapper(ethSendTransaction);
10462
+ if (!this.isLoggedIn()) {
10463
+ throw new JsonRpcError(ProviderErrorCode.UNAUTHORIZED, 'Unauthorised - call eth_requestAccounts first');
10464
+ }
10465
+ return sendTransaction({
10466
+ params: request.params || [],
10467
+ magicProvider: this.magicProvider,
10468
+ transactionAPI: this.transactionAPI,
10469
+ jsonRpcProvider: this.jsonRpcProvider,
10470
+ config: this.config,
10471
+ relayerClient: this.relayerClient,
10472
+ user: this.user,
10473
+ });
10395
10474
  }
10396
10475
  case 'eth_accounts': {
10397
10476
  return this.isLoggedIn() ? [this.user.zkEvm.ethAddress] : [];
@@ -10412,7 +10491,7 @@ class ZkEvmProvider {
10412
10491
  return this.jsonRpcProvider.send(request.method, request.params || []);
10413
10492
  }
10414
10493
  default: {
10415
- throw new JsonRpcError(RpcErrorCode.METHOD_NOT_FOUND, 'Method not supported');
10494
+ throw new JsonRpcError(ProviderErrorCode.UNSUPPORTED_METHOD, 'Method not supported');
10416
10495
  }
10417
10496
  }
10418
10497
  }
@@ -10506,6 +10585,12 @@ class ZkEvmProvider {
10506
10585
  }
10507
10586
  throw new JsonRpcError(RpcErrorCode.INVALID_REQUEST, 'Invalid request');
10508
10587
  }
10588
+ on(event, listener) {
10589
+ this.eventEmitter.on(event, listener);
10590
+ }
10591
+ removeListener(event, listener) {
10592
+ this.eventEmitter.removeListener(event, listener);
10593
+ }
10509
10594
  }
10510
10595
 
10511
10596
  class Passport {
@@ -10599,4 +10684,4 @@ class Passport {
10599
10684
  }
10600
10685
  }
10601
10686
 
10602
- export { Networks, Passport, PassportError };
10687
+ export { JsonRpcError, Networks, Passport, PassportError, ProviderErrorCode, ProviderEvent, RpcErrorCode };