@imtbl/sdk 0.4.0-alpha.1 → 0.4.0-alpha.3

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
@@ -8,8 +8,11 @@ import { OpenIdExtension } from '@magic-ext/oidc';
8
8
  import BN$2 from 'bn.js';
9
9
  import * as encUtils from 'enc-utils';
10
10
  import { Web3Provider, JsonRpcProvider } from '@ethersproject/providers';
11
+ import { EventEmitter } from 'events';
12
+ import { ethers, BigNumber as BigNumber$1, providers, constants, utils as utils$2, Contract as Contract$1, ContractFactory } from 'ethers';
13
+ import { walletContracts } from '@0xsequence/abi';
14
+ import { encodeSignature } from '@0xsequence/config';
11
15
  import FormData$2 from 'form-data';
12
- import { providers, BigNumber as BigNumber$1, constants, utils as utils$2, Contract as Contract$1, ethers, ContractFactory } from 'ethers';
13
16
  import { Seaport as Seaport$1 } from '@opensea/seaport-js';
14
17
  import { parseUnits } from '@ethersproject/units';
15
18
  import { BigNumber as BigNumber$2 } from '@ethersproject/bignumber';
@@ -3245,6 +3248,94 @@ axios$1.default = axios$1;
3245
3248
  // this module should only have a default export
3246
3249
  var globalAxios$1 = axios$1;
3247
3250
 
3251
+ /* tslint:disable */
3252
+ /* eslint-disable */
3253
+ /**
3254
+ * Immutable X API
3255
+ * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
3256
+ *
3257
+ * The version of the OpenAPI document: 3.0
3258
+ * Contact: support@immutable.com
3259
+ *
3260
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
3261
+ * https://openapi-generator.tech
3262
+ * Do not edit the class manually.
3263
+ */
3264
+ let Configuration$1 = class Configuration {
3265
+ /**
3266
+ * parameter for apiKey security
3267
+ * @param name security name
3268
+ * @memberof Configuration
3269
+ */
3270
+ apiKey;
3271
+ /**
3272
+ * parameter for basic security
3273
+ *
3274
+ * @type {string}
3275
+ * @memberof Configuration
3276
+ */
3277
+ username;
3278
+ /**
3279
+ * parameter for basic security
3280
+ *
3281
+ * @type {string}
3282
+ * @memberof Configuration
3283
+ */
3284
+ password;
3285
+ /**
3286
+ * parameter for oauth2 security
3287
+ * @param name security name
3288
+ * @param scopes oauth2 scope
3289
+ * @memberof Configuration
3290
+ */
3291
+ accessToken;
3292
+ /**
3293
+ * override base path
3294
+ *
3295
+ * @type {string}
3296
+ * @memberof Configuration
3297
+ */
3298
+ basePath;
3299
+ /**
3300
+ * base options for axios calls
3301
+ *
3302
+ * @type {any}
3303
+ * @memberof Configuration
3304
+ */
3305
+ baseOptions;
3306
+ /**
3307
+ * The FormData constructor that will be used to create multipart form data
3308
+ * requests. You can inject this here so that execution environments that
3309
+ * do not support the FormData class can still run the generated client.
3310
+ *
3311
+ * @type {new () => FormData}
3312
+ */
3313
+ formDataCtor;
3314
+ constructor(param = {}) {
3315
+ this.apiKey = param.apiKey;
3316
+ this.username = param.username;
3317
+ this.password = param.password;
3318
+ this.accessToken = param.accessToken;
3319
+ this.basePath = param.basePath;
3320
+ this.baseOptions = param.baseOptions;
3321
+ this.formDataCtor = param.formDataCtor;
3322
+ }
3323
+ /**
3324
+ * Check if the given MIME is a JSON MIME.
3325
+ * JSON MIME examples:
3326
+ * application/json
3327
+ * application/json; charset=UTF8
3328
+ * APPLICATION/JSON
3329
+ * application/vnd.company+json
3330
+ * @param mime - MIME (Multipurpose Internet Mail Extensions)
3331
+ * @return True if the given MIME is JSON, false otherwise.
3332
+ */
3333
+ isJsonMime(mime) {
3334
+ const jsonMime = new RegExp('^(application\/json|[^;/ \t]+\/[^;/ \t]+[+]json)[ \t]*(;.*)?$', 'i');
3335
+ return mime !== null && (jsonMime.test(mime) || mime.toLowerCase() === 'application/json-patch+json');
3336
+ }
3337
+ };
3338
+
3248
3339
  /* tslint:disable */
3249
3340
  /* eslint-disable */
3250
3341
  /**
@@ -4953,7 +5044,7 @@ class TokensApi extends BaseAPI$1 {
4953
5044
  * https://openapi-generator.tech
4954
5045
  * Do not edit the class manually.
4955
5046
  */
4956
- let Configuration$1 = class Configuration {
5047
+ let Configuration$2 = class Configuration {
4957
5048
  /**
4958
5049
  * parameter for apiKey security
4959
5050
  * @param name security name
@@ -5386,7 +5477,7 @@ var index = /*#__PURE__*/Object.freeze({
5386
5477
  CollectionsApiAxiosParamCreator: CollectionsApiAxiosParamCreator,
5387
5478
  CollectionsApiFactory: CollectionsApiFactory,
5388
5479
  CollectionsApiFp: CollectionsApiFp,
5389
- Configuration: Configuration$1,
5480
+ Configuration: Configuration$2,
5390
5481
  CreateOrderProtocolDataOrderTypeEnum: CreateOrderProtocolDataOrderTypeEnum,
5391
5482
  ERC20ItemItemTypeEnum: ERC20ItemItemTypeEnum,
5392
5483
  ERC721ItemItemTypeEnum: ERC721ItemItemTypeEnum,
@@ -5418,6 +5509,69 @@ var index = /*#__PURE__*/Object.freeze({
5418
5509
  TokensApiFp: TokensApiFp
5419
5510
  });
5420
5511
 
5512
+ class MultiRollupApiClients {
5513
+ config;
5514
+ activitiesApi;
5515
+ chainsApi;
5516
+ collectionApi;
5517
+ nftOwnersApi;
5518
+ nftsApi;
5519
+ ordersApi;
5520
+ passportApi;
5521
+ constructor(config) {
5522
+ this.config = config;
5523
+ this.activitiesApi = new ActivitiesApi(config.indexer);
5524
+ this.chainsApi = new ChainsApi(config.indexer);
5525
+ this.collectionApi = new CollectionsApi(config.indexer);
5526
+ this.nftOwnersApi = new NftOwnersApi(config.indexer);
5527
+ this.nftsApi = new NftsApi(config.indexer);
5528
+ this.ordersApi = new OrdersApi(config.orderBook);
5529
+ this.passportApi = new PassportApi(config.passport);
5530
+ }
5531
+ }
5532
+
5533
+ // eslint-disable-next-line @typescript-eslint/naming-convention
5534
+ const defaultHeaders$1 = { 'x-sdk-version': 'ts-immutable-sdk-0.4.0-alpha.3' };
5535
+ const createConfig = ({ basePath, headers, }) => {
5536
+ if (!basePath.trim()) {
5537
+ throw Error('basePath can not be empty');
5538
+ }
5539
+ const composedHeaders = { ...defaultHeaders$1, ...(headers || {}) };
5540
+ const apiConfigOptions = {
5541
+ basePath,
5542
+ baseOptions: { headers: composedHeaders },
5543
+ };
5544
+ return new Configuration$1(apiConfigOptions);
5545
+ };
5546
+ /**
5547
+ * Creates a Configuration for the specified environment
5548
+ * @returns an MultiRollupAPIConfiguration
5549
+ */
5550
+ const multiRollupConfig = {
5551
+ getProduction: () => ({
5552
+ indexer: createConfig({
5553
+ basePath: 'https://indexer-mr.imtbl.com',
5554
+ }),
5555
+ orderBook: createConfig({
5556
+ basePath: 'https://order-book-mr.imtbl.com',
5557
+ }),
5558
+ passport: createConfig({
5559
+ basePath: 'https://api.immutable.com',
5560
+ }),
5561
+ }),
5562
+ getSandbox: () => ({
5563
+ indexer: createConfig({
5564
+ basePath: 'https://indexer-mr.sandbox.imtbl.com',
5565
+ }),
5566
+ orderBook: createConfig({
5567
+ basePath: 'https://order-book-mr.sandbox.imtbl.com',
5568
+ }),
5569
+ passport: createConfig({
5570
+ basePath: 'https://api.sandbox.immutable.com',
5571
+ }),
5572
+ }),
5573
+ };
5574
+
5421
5575
  /**
5422
5576
  * Custom Error class that is returned from the API when a request fails
5423
5577
  */
@@ -5437,7 +5591,7 @@ class APIError extends Error {
5437
5591
 
5438
5592
  /* eslint-disable implicit-arrow-linebreak */
5439
5593
  const defaultHeaders = {
5440
- sdkVersion: 'ts-immutable-sdk-multi-rollup-api-client-0.4.0-alpha.1',
5594
+ sdkVersion: 'ts-immutable-sdk-multi-rollup-api-client-0.4.0-alpha.3',
5441
5595
  };
5442
5596
  /**
5443
5597
  * createAPIConfiguration to create a custom Configuration
@@ -5703,7 +5857,7 @@ const createImmutableXConfiguration = ({ basePath, chainID, coreContractAddress,
5703
5857
  chainID,
5704
5858
  coreContractAddress,
5705
5859
  registrationContractAddress,
5706
- sdkVersion: 'ts-immutable-sdk-0.4.0-alpha.1',
5860
+ sdkVersion: 'ts-immutable-sdk-0.4.0-alpha.3',
5707
5861
  });
5708
5862
  /**
5709
5863
  * Sets `sdkVersion` at the time of build
@@ -9427,6 +9581,8 @@ var globalAxios = axios;
9427
9581
  * https://openapi-generator.tech
9428
9582
  * Do not edit the class manually.
9429
9583
  */
9584
+ // Some imports not used depending on template conditions
9585
+ // @ts-ignore
9430
9586
  const BASE_PATH = "https://guardian.sandbox.imtbl.com".replace(/\/+$/, "");
9431
9587
  /**
9432
9588
  *
@@ -9454,10 +9610,10 @@ class BaseAPI {
9454
9610
  */
9455
9611
  class RequiredError extends Error {
9456
9612
  field;
9613
+ name = "RequiredError";
9457
9614
  constructor(field, msg) {
9458
9615
  super(msg);
9459
9616
  this.field = field;
9460
- this.name = "RequiredError";
9461
9617
  }
9462
9618
  }
9463
9619
 
@@ -9502,8 +9658,6 @@ const setBearerAuthToObject = async function (object, configuration) {
9502
9658
  }
9503
9659
  };
9504
9660
  function setFlattenedQueryParams(urlSearchParams, parameter, key = "") {
9505
- if (parameter == null)
9506
- return;
9507
9661
  if (typeof parameter === "object") {
9508
9662
  if (Array.isArray(parameter)) {
9509
9663
  parameter.forEach(item => setFlattenedQueryParams(urlSearchParams, item, key));
@@ -9659,7 +9813,7 @@ const TransactionsApiAxiosParamCreator = function (configuration) {
9659
9813
  * @summary Info for a specific transaction
9660
9814
  * @param {string} transactionID The id of the starkex transaction to retrieve
9661
9815
  * @param {'starkex' | 'evm'} chainType roll up type
9662
- * @param {number} [chainID] ID of evm chain
9816
+ * @param {string} [chainID] ID of evm chain
9663
9817
  * @param {*} [options] Override http request option.
9664
9818
  * @throws {RequiredError}
9665
9819
  */
@@ -9734,7 +9888,7 @@ const TransactionsApiFp = function (configuration) {
9734
9888
  * @summary Info for a specific transaction
9735
9889
  * @param {string} transactionID The id of the starkex transaction to retrieve
9736
9890
  * @param {'starkex' | 'evm'} chainType roll up type
9737
- * @param {number} [chainID] ID of evm chain
9891
+ * @param {string} [chainID] ID of evm chain
9738
9892
  * @param {*} [options] Override http request option.
9739
9893
  * @throws {RequiredError}
9740
9894
  */
@@ -10051,10 +10205,12 @@ class AuthManager {
10051
10205
  userManager;
10052
10206
  config;
10053
10207
  deviceCredentialsManager;
10208
+ logoutMode;
10054
10209
  constructor(config) {
10055
10210
  this.config = config;
10056
10211
  this.userManager = new UserManager(getAuthConfiguration(config));
10057
10212
  this.deviceCredentialsManager = new DeviceCredentialsManager();
10213
+ this.logoutMode = config.oidcConfiguration.logoutMode || 'redirect';
10058
10214
  }
10059
10215
  static mapOidcUserToDomainModel = (oidcUser) => {
10060
10216
  const passport = oidcUser.profile?.passport;
@@ -10208,7 +10364,15 @@ class AuthManager {
10208
10364
  return response.data;
10209
10365
  }
10210
10366
  async logout() {
10211
- return withPassportError(async () => this.userManager.signoutRedirect(), PassportErrorType.LOGOUT_ERROR);
10367
+ return withPassportError(async () => {
10368
+ if (this.logoutMode === 'silent') {
10369
+ return this.userManager.signoutSilent();
10370
+ }
10371
+ return this.userManager.signoutRedirect();
10372
+ }, PassportErrorType.LOGOUT_ERROR);
10373
+ }
10374
+ async logoutSilentCallback(url) {
10375
+ return this.userManager.signoutSilentCallback(url);
10212
10376
  }
10213
10377
  async logoutDeviceFlow() {
10214
10378
  return withPassportError(async () => {
@@ -10411,6 +10575,7 @@ async function createOrder$1({ starkSigner, user, request, ordersApi, guardianCl
10411
10575
  amount_sell: amountSell,
10412
10576
  token_sell: convertToSignableToken(request.sell),
10413
10577
  fees: request.fees,
10578
+ split_fees: true,
10414
10579
  expiration_timestamp: request.expiration_timestamp,
10415
10580
  };
10416
10581
  const getSignableOrderResponse = await ordersApi.getSignableOrder({
@@ -10865,6 +11030,10 @@ class PassportConfiguration {
10865
11030
  magicProviderId;
10866
11031
  oidcConfiguration;
10867
11032
  baseConfig;
11033
+ zkEvmChainId;
11034
+ zkEvmRpcUrl;
11035
+ relayerUrl;
11036
+ multiRollupConfig;
10868
11037
  constructor({ baseConfig, overrides, ...oidcConfiguration }) {
10869
11038
  validateConfiguration(oidcConfiguration, [
10870
11039
  'clientId',
@@ -10877,10 +11046,16 @@ class PassportConfiguration {
10877
11046
  validateConfiguration(overrides, [
10878
11047
  'network',
10879
11048
  'authenticationDomain',
11049
+ 'passportDomain',
10880
11050
  'magicPublishableApiKey',
10881
11051
  'magicProviderId',
10882
- 'passportDomain',
11052
+ 'zkEvmRpcUrl',
11053
+ 'zkEvmChainId',
11054
+ 'relayerUrl',
10883
11055
  'imxPublicApiDomain',
11056
+ 'indexerMrBasePath',
11057
+ 'orderBookMrBasePath',
11058
+ 'passportMrBasePath',
10884
11059
  ], 'overrides');
10885
11060
  this.network = overrides.network;
10886
11061
  this.authenticationDomain = overrides.authenticationDomain;
@@ -10888,6 +11063,20 @@ class PassportConfiguration {
10888
11063
  this.imxPublicApiDomain = overrides.imxPublicApiDomain;
10889
11064
  this.magicPublishableApiKey = overrides.magicPublishableApiKey;
10890
11065
  this.magicProviderId = overrides.magicProviderId;
11066
+ this.zkEvmRpcUrl = overrides.zkEvmRpcUrl;
11067
+ this.zkEvmChainId = overrides.zkEvmChainId;
11068
+ this.relayerUrl = overrides.relayerUrl;
11069
+ this.multiRollupConfig = {
11070
+ indexer: createConfig({
11071
+ basePath: overrides.indexerMrBasePath,
11072
+ }),
11073
+ orderBook: createConfig({
11074
+ basePath: overrides.orderBookMrBasePath,
11075
+ }),
11076
+ passport: createConfig({
11077
+ basePath: overrides.passportMrBasePath,
11078
+ }),
11079
+ };
10891
11080
  }
10892
11081
  else {
10893
11082
  switch (baseConfig.environment) {
@@ -10898,6 +11087,10 @@ class PassportConfiguration {
10898
11087
  this.magicProviderId = 'fSMzaRQ4O7p4fttl7pCyGVtJS_G70P8SNsLXtPPGHo0=';
10899
11088
  this.passportDomain = 'https://passport.immutable.com';
10900
11089
  this.imxPublicApiDomain = 'https://api.immutable.com';
11090
+ this.zkEvmRpcUrl = ''; // TODO: ID-785 Update once mainnet has been deployed
11091
+ this.zkEvmChainId = ''; // TODO: ID-785 Update once mainnet has been deployed
11092
+ this.relayerUrl = 'https://api.immutable.com/relayer-mr';
11093
+ this.multiRollupConfig = multiRollupConfig.getProduction();
10901
11094
  break;
10902
11095
  }
10903
11096
  case Environment$1.SANDBOX:
@@ -10908,6 +11101,10 @@ class PassportConfiguration {
10908
11101
  this.magicProviderId = 'fSMzaRQ4O7p4fttl7pCyGVtJS_G70P8SNsLXtPPGHo0=';
10909
11102
  this.passportDomain = 'https://passport.sandbox.immutable.com';
10910
11103
  this.imxPublicApiDomain = 'https://api.sandbox.immutable.com';
11104
+ this.zkEvmRpcUrl = 'https://zkevm-rpc.sandbox.x.immutable.com';
11105
+ this.zkEvmChainId = 'eip155:13392';
11106
+ this.relayerUrl = 'https://api.sandbox.immutable.com/relayer-mr';
11107
+ this.multiRollupConfig = multiRollupConfig.getSandbox();
10911
11108
  break;
10912
11109
  }
10913
11110
  }
@@ -11068,6 +11265,537 @@ class ConfirmationScreen {
11068
11265
  }
11069
11266
  }
11070
11267
 
11268
+ var RelayerTransactionStatus;
11269
+ (function (RelayerTransactionStatus) {
11270
+ RelayerTransactionStatus["PENDING"] = "PENDING";
11271
+ RelayerTransactionStatus["SUBMITTED"] = "SUBMITTED";
11272
+ RelayerTransactionStatus["SUCCESSFUL"] = "SUCCESSFUL";
11273
+ RelayerTransactionStatus["REVERTED"] = "REVERTED";
11274
+ RelayerTransactionStatus["FAILED"] = "FAILED";
11275
+ })(RelayerTransactionStatus || (RelayerTransactionStatus = {}));
11276
+ var ProviderEvent;
11277
+ (function (ProviderEvent) {
11278
+ ProviderEvent["ACCOUNTS_CHANGED"] = "accountsChanged";
11279
+ })(ProviderEvent || (ProviderEvent = {}));
11280
+
11281
+ class TypedEventEmitter {
11282
+ emitter = new EventEmitter();
11283
+ emit(eventName, ...eventArg) {
11284
+ this.emitter.emit(eventName, ...eventArg);
11285
+ }
11286
+ on(eventName, handler) {
11287
+ this.emitter.on(eventName, handler);
11288
+ }
11289
+ removeListener(eventName, handler) {
11290
+ this.emitter.removeListener(eventName, handler);
11291
+ }
11292
+ }
11293
+
11294
+ class RelayerClient {
11295
+ config;
11296
+ constructor({ config }) {
11297
+ this.config = config;
11298
+ }
11299
+ async postToRelayer(request) {
11300
+ const body = {
11301
+ id: 1,
11302
+ jsonrpc: '2.0',
11303
+ ...request,
11304
+ };
11305
+ const response = await fetch(`${this.config.relayerUrl}/v1/transactions`, {
11306
+ method: 'POST',
11307
+ headers: {
11308
+ 'Content-Type': 'application/json',
11309
+ },
11310
+ body: JSON.stringify(body),
11311
+ });
11312
+ const jsonResponse = await response.json();
11313
+ if (jsonResponse.error) {
11314
+ throw jsonResponse.error;
11315
+ }
11316
+ return jsonResponse;
11317
+ }
11318
+ async ethSendTransaction(to, data) {
11319
+ const payload = {
11320
+ method: 'eth_sendTransaction',
11321
+ params: [{
11322
+ to,
11323
+ data,
11324
+ chainId: this.config.zkEvmChainId.toString(),
11325
+ }],
11326
+ };
11327
+ const { result } = await this.postToRelayer(payload);
11328
+ return result;
11329
+ }
11330
+ async imGetTransactionByHash(hash) {
11331
+ const payload = {
11332
+ method: 'im_getTransactionByHash',
11333
+ params: [hash],
11334
+ };
11335
+ const { result } = await this.postToRelayer(payload);
11336
+ return result;
11337
+ }
11338
+ async imGetFeeOptions(userAddress, data) {
11339
+ const payload = {
11340
+ method: 'im_getFeeOptions',
11341
+ params: [{
11342
+ userAddress,
11343
+ data,
11344
+ chainId: this.config.zkEvmChainId.toString(),
11345
+ }],
11346
+ };
11347
+ const { result } = await this.postToRelayer(payload);
11348
+ return result;
11349
+ }
11350
+ }
11351
+
11352
+ /**
11353
+ * ProviderErrors should take priority over RpcErrorCodes
11354
+ */
11355
+ var ProviderErrorCode;
11356
+ (function (ProviderErrorCode) {
11357
+ ProviderErrorCode[ProviderErrorCode["USER_REJECTED_REQUEST"] = 4001] = "USER_REJECTED_REQUEST";
11358
+ ProviderErrorCode[ProviderErrorCode["UNAUTHORIZED"] = 4100] = "UNAUTHORIZED";
11359
+ ProviderErrorCode[ProviderErrorCode["UNSUPPORTED_METHOD"] = 4200] = "UNSUPPORTED_METHOD";
11360
+ ProviderErrorCode[ProviderErrorCode["DISCONNECTED"] = 4900] = "DISCONNECTED";
11361
+ })(ProviderErrorCode || (ProviderErrorCode = {}));
11362
+ var RpcErrorCode;
11363
+ (function (RpcErrorCode) {
11364
+ RpcErrorCode[RpcErrorCode["RPC_SERVER_ERROR"] = -32000] = "RPC_SERVER_ERROR";
11365
+ RpcErrorCode[RpcErrorCode["INVALID_REQUEST"] = -32600] = "INVALID_REQUEST";
11366
+ RpcErrorCode[RpcErrorCode["METHOD_NOT_FOUND"] = -32601] = "METHOD_NOT_FOUND";
11367
+ RpcErrorCode[RpcErrorCode["INVALID_PARAMS"] = -32602] = "INVALID_PARAMS";
11368
+ RpcErrorCode[RpcErrorCode["INTERNAL_ERROR"] = -32603] = "INTERNAL_ERROR";
11369
+ RpcErrorCode[RpcErrorCode["PARSE_ERROR"] = -32700] = "PARSE_ERROR";
11370
+ })(RpcErrorCode || (RpcErrorCode = {}));
11371
+ class JsonRpcError extends Error {
11372
+ message;
11373
+ code;
11374
+ constructor(code, message) {
11375
+ super(message);
11376
+ this.message = message;
11377
+ this.code = code;
11378
+ }
11379
+ }
11380
+
11381
+ const MESSAGE_TO_SIGN = 'Only sign this message from Immutable Passport';
11382
+ async function registerZkEvmUser({ authManager, magicProvider, multiRollupApiClients, accessToken, }) {
11383
+ const web3Provider = new Web3Provider(magicProvider);
11384
+ const ethSigner = web3Provider.getSigner();
11385
+ const ethereumAddress = await ethSigner.getAddress();
11386
+ const ethereumSignature = await signRaw(MESSAGE_TO_SIGN, ethSigner);
11387
+ const headers = { Authorization: `Bearer ${accessToken}` };
11388
+ try {
11389
+ await multiRollupApiClients.passportApi.createCounterfactualAddress({
11390
+ createCounterfactualAddressRequest: {
11391
+ ethereumAddress,
11392
+ ethereumSignature,
11393
+ },
11394
+ }, { headers });
11395
+ }
11396
+ catch (error) {
11397
+ throw new JsonRpcError(RpcErrorCode.INTERNAL_ERROR, `Failed to create counterfactual address: ${error}`);
11398
+ }
11399
+ const user = await authManager.loginSilent();
11400
+ if (!user?.zkEvm) {
11401
+ throw new JsonRpcError(RpcErrorCode.INTERNAL_ERROR, 'Failed to refresh user details');
11402
+ }
11403
+ return user;
11404
+ }
11405
+
11406
+ const loginZkEvmUser = async ({ authManager, config, magicAdapter, multiRollupApiClients, }) => {
11407
+ const user = await authManager.getUser() || await authManager.login();
11408
+ if (!user.idToken) {
11409
+ throw new Error('User is missing idToken');
11410
+ }
11411
+ const magicProvider = await magicAdapter.login(user.idToken, config.network);
11412
+ if (!user.zkEvm) {
11413
+ // Generate counterfactual address and retrieve updated Auth0 user
11414
+ const userZkevm = await registerZkEvmUser({
11415
+ authManager,
11416
+ magicProvider,
11417
+ multiRollupApiClients,
11418
+ accessToken: user.accessToken,
11419
+ });
11420
+ return {
11421
+ user: userZkevm,
11422
+ magicProvider,
11423
+ };
11424
+ }
11425
+ return {
11426
+ user: user,
11427
+ magicProvider,
11428
+ };
11429
+ };
11430
+
11431
+ // These are ignored by the Relayer but for consistency we set them to the
11432
+ // appropriate values for a 1/1 wallet.
11433
+ //
11434
+ // Weight of a single signature in the multisig
11435
+ const SIGNATURE_WEIGHT = 1;
11436
+ // Total required weight in the multisig
11437
+ const SIGNATURE_THRESHOLD = 1;
11438
+ const ETH_SIGN_FLAG = '02';
11439
+ const ETH_SIGN_PREFIX = '\x19\x01';
11440
+ const META_TRANSACTIONS_TYPE = `tuple(
11441
+ bool delegateCall,
11442
+ bool revertOnError,
11443
+ uint256 gasLimit,
11444
+ address target,
11445
+ uint256 value,
11446
+ bytes data
11447
+ )[]`;
11448
+ function getNormalisedTransactions(txs) {
11449
+ return txs.map((t) => ({
11450
+ delegateCall: t.delegateCall === true,
11451
+ revertOnError: t.revertOnError === true,
11452
+ gasLimit: t.gasLimit ?? ethers.constants.Zero,
11453
+ target: t.to ?? ethers.constants.AddressZero,
11454
+ value: t.value ?? ethers.constants.Zero,
11455
+ data: t.data ?? [],
11456
+ }));
11457
+ }
11458
+ function digestOfTransactionsAndNonce(nonce, normalisedTransactions) {
11459
+ const packMetaTransactionsNonceData = ethers.utils.defaultAbiCoder.encode(['uint256', META_TRANSACTIONS_TYPE], [nonce, normalisedTransactions]);
11460
+ return ethers.utils.keccak256(packMetaTransactionsNonceData);
11461
+ }
11462
+ const getNonce = async (jsonRpcProvider, smartContractWalletAddress) => {
11463
+ const code = await jsonRpcProvider.send('eth_getCode', [smartContractWalletAddress, 'latest']);
11464
+ if (code && code !== '0x') {
11465
+ const contract = new ethers.Contract(smartContractWalletAddress, walletContracts.mainModule.abi, jsonRpcProvider);
11466
+ return contract.nonce();
11467
+ }
11468
+ return 0;
11469
+ };
11470
+ const getSignedMetaTransactions = async (metaTransactions, nonce, chainId, walletAddress, signer) => {
11471
+ const normalisedMetaTransactions = getNormalisedTransactions(metaTransactions);
11472
+ // Get the hash
11473
+ const digest = digestOfTransactionsAndNonce(nonce, normalisedMetaTransactions);
11474
+ const completePayload = ethers.utils.solidityPack(['string', 'uint256', 'address', 'bytes32'], [ETH_SIGN_PREFIX, chainId, walletAddress, digest]);
11475
+ const hash = ethers.utils.keccak256(completePayload);
11476
+ // Sign the digest
11477
+ const hashArray = ethers.utils.arrayify(hash);
11478
+ const ethsigNoType = await signer.signMessage(hashArray);
11479
+ const signedDigest = `${ethsigNoType}${ETH_SIGN_FLAG}`;
11480
+ // Add metadata
11481
+ const encodedSignature = encodeSignature({
11482
+ threshold: SIGNATURE_THRESHOLD,
11483
+ signers: [
11484
+ {
11485
+ weight: SIGNATURE_WEIGHT,
11486
+ signature: signedDigest,
11487
+ },
11488
+ ],
11489
+ });
11490
+ // Encode the transaction;
11491
+ const walletInterface = new ethers.utils.Interface(walletContracts.mainModule.abi);
11492
+ return walletInterface.encodeFunctionData(walletInterface.getFunction('execute'), [
11493
+ normalisedMetaTransactions,
11494
+ nonce,
11495
+ encodedSignature,
11496
+ ]);
11497
+ };
11498
+ const chainIdNumber = (chainId) => {
11499
+ const caip2Components = chainId.split(':');
11500
+ if (caip2Components.length !== 2) {
11501
+ throw new Error('Invalid configuration, chain ID is not in CAIP-2 format');
11502
+ }
11503
+ return BigNumber$1.from(caip2Components[1]);
11504
+ };
11505
+
11506
+ const MAX_TRANSACTION_HASH_RETRIEVAL_RETRIES = 30;
11507
+ const TRANSACTION_HASH_RETRIEVAL_WAIT = 1000;
11508
+ const converBigNumberishToNumber = (value) => BigNumber$1.from(value).toNumber();
11509
+ const transformGardianTransactions = (txs) => {
11510
+ try {
11511
+ return txs.map((t) => ({
11512
+ delegateCall: t.delegateCall === true,
11513
+ revertOnError: t.revertOnError === true,
11514
+ gasLimit: t.gasLimit ? converBigNumberishToNumber(t.gasLimit).toString() : '0',
11515
+ target: t.to ?? ethers.constants.AddressZero,
11516
+ value: t.value ? converBigNumberishToNumber(t.value).toString() : '0',
11517
+ data: t.data ? t.data.toString() : '0x00',
11518
+ }));
11519
+ }
11520
+ catch (error) {
11521
+ const errorMessage = (error instanceof Error) ? error.message : String(error);
11522
+ throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, `Transaction failed to parsing: ${errorMessage}`);
11523
+ }
11524
+ };
11525
+ const guardianValidation = async ({ transactionAPI, chainId, nonce, user, metaTransactions, }) => {
11526
+ const headers = { Authorization: `Bearer ${user.accessToken}` };
11527
+ const guardianTransactions = transformGardianTransactions(metaTransactions);
11528
+ try {
11529
+ await transactionAPI.evaluateTransaction({
11530
+ id: 'evm',
11531
+ transactionEvaluationRequest: {
11532
+ chainType: 'evm',
11533
+ chainId,
11534
+ transactionData: {
11535
+ nonce,
11536
+ userAddress: user.zkEvm.ethAddress,
11537
+ metaTransactions: guardianTransactions,
11538
+ },
11539
+ },
11540
+ }, { headers });
11541
+ }
11542
+ catch (error) {
11543
+ const errorMessage = (error instanceof Error) ? error.message : String(error);
11544
+ throw new JsonRpcError(RpcErrorCode.INTERNAL_ERROR, `Transaction failed to validate with error: ${errorMessage}`);
11545
+ }
11546
+ };
11547
+ const sendTransaction = async ({ params, magicProvider, jsonRpcProvider, relayerClient, transactionAPI, config, user, }) => {
11548
+ const transactionRequest = params[0];
11549
+ if (!transactionRequest.to) {
11550
+ throw new JsonRpcError(RpcErrorCode.INVALID_PARAMS, 'eth_sendTransaction requires a "to" field');
11551
+ }
11552
+ const chainId = chainIdNumber(config.zkEvmChainId);
11553
+ const magicWeb3Provider = new Web3Provider(magicProvider);
11554
+ const signer = magicWeb3Provider.getSigner();
11555
+ const nonce = await getNonce(jsonRpcProvider, user.zkEvm.ethAddress);
11556
+ const metaTransaction = {
11557
+ to: transactionRequest.to,
11558
+ data: transactionRequest.data,
11559
+ nonce,
11560
+ value: transactionRequest.value,
11561
+ revertOnError: true,
11562
+ };
11563
+ // NOTE: We sign the transaction before getting the fee options because
11564
+ // accurate estimation of a transaction gas cost is only possible if the smart
11565
+ // wallet contract can actually execute it (in a simulated environment) - and
11566
+ // it can only execute signed transactions.
11567
+ const signedTransaction = await getSignedMetaTransactions([metaTransaction], nonce, chainId, user.zkEvm.ethAddress, signer);
11568
+ // TODO: ID-698 Add support for non-native gas payments (e.g ERC20, feeTransaction initialisation must change)
11569
+ // NOTE: "Fee Options" represent the multiple ways we could pay for the gas
11570
+ // used in this transaction. Each fee option has a "recipientAddress" we
11571
+ // should transfer the payment to, an amount and a currency. We choose one
11572
+ // option and build a transaction that sends the expected currency amount for
11573
+ // that option to the specified address.
11574
+ const feeOptions = await relayerClient.imGetFeeOptions(user.zkEvm.ethAddress, signedTransaction);
11575
+ const imxFeeOption = feeOptions.find((feeOption) => feeOption.tokenSymbol === 'IMX');
11576
+ if (!imxFeeOption) {
11577
+ throw new Error('Failed to retrieve fees for IMX token');
11578
+ }
11579
+ const feeMetaTransaction = {
11580
+ nonce,
11581
+ to: imxFeeOption.recipientAddress,
11582
+ value: imxFeeOption.tokenPrice,
11583
+ revertOnError: true,
11584
+ };
11585
+ await guardianValidation({
11586
+ transactionAPI,
11587
+ chainId: config.zkEvmChainId,
11588
+ nonce: converBigNumberishToNumber(nonce),
11589
+ user,
11590
+ metaTransactions: [metaTransaction, feeMetaTransaction],
11591
+ });
11592
+ // NOTE: We sign again because we now are adding the fee transaction, so the
11593
+ // whole payload is different and needs a new signature.
11594
+ const signedTransactions = await getSignedMetaTransactions([metaTransaction, feeMetaTransaction], nonce, chainId, user.zkEvm.ethAddress, signer);
11595
+ // TODO: ID-697 Evaluate transactions through Guardian
11596
+ const relayerId = await relayerClient.ethSendTransaction(user.zkEvm.ethAddress, signedTransactions);
11597
+ const retrieveRelayerTransaction = async () => {
11598
+ const tx = await relayerClient.imGetTransactionByHash(relayerId);
11599
+ // NOTE: The transaction hash is only available from the Relayer once the
11600
+ // transaction is actually submitted onchain. Hence we need to poll the
11601
+ // Relayer get transaction endpoint until the status transitions to one that
11602
+ // has the hash available.
11603
+ if (tx.status === RelayerTransactionStatus.PENDING) {
11604
+ throw new Error();
11605
+ }
11606
+ return tx;
11607
+ };
11608
+ const relayerTransaction = await retryWithDelay(retrieveRelayerTransaction, {
11609
+ retries: MAX_TRANSACTION_HASH_RETRIEVAL_RETRIES,
11610
+ interval: TRANSACTION_HASH_RETRIEVAL_WAIT,
11611
+ finalErr: new JsonRpcError(RpcErrorCode.RPC_SERVER_ERROR, 'transaction hash not generated in time'),
11612
+ });
11613
+ if (![RelayerTransactionStatus.SUBMITTED, RelayerTransactionStatus.SUCCESSFUL].includes(relayerTransaction.status)) {
11614
+ throw new JsonRpcError(RpcErrorCode.RPC_SERVER_ERROR, `Transaction failed to submit with status ${relayerTransaction.status}`);
11615
+ }
11616
+ return relayerTransaction.hash;
11617
+ };
11618
+
11619
+ class ZkEvmProvider {
11620
+ authManager;
11621
+ config;
11622
+ confirmationScreen;
11623
+ magicAdapter;
11624
+ relayerClient;
11625
+ transactionAPI;
11626
+ multiRollupApiClients;
11627
+ jsonRpcProvider; // Used for read
11628
+ eventEmitter;
11629
+ magicProvider; // Used for signing
11630
+ user;
11631
+ constructor({ authManager, magicAdapter, config, confirmationScreen, multiRollupApiClients, }) {
11632
+ this.authManager = authManager;
11633
+ this.magicAdapter = magicAdapter;
11634
+ this.config = config;
11635
+ this.confirmationScreen = confirmationScreen;
11636
+ this.relayerClient = new RelayerClient({ config });
11637
+ this.transactionAPI = new TransactionsApi(new Configuration({
11638
+ basePath: this.config.imxPublicApiDomain,
11639
+ }));
11640
+ this.jsonRpcProvider = new JsonRpcProvider(this.config.zkEvmRpcUrl);
11641
+ this.multiRollupApiClients = multiRollupApiClients;
11642
+ this.eventEmitter = new TypedEventEmitter();
11643
+ }
11644
+ isLoggedIn() {
11645
+ return this.magicProvider !== undefined && this.user !== undefined;
11646
+ }
11647
+ async performRequest(request) {
11648
+ switch (request.method) {
11649
+ case 'eth_requestAccounts': {
11650
+ if (this.isLoggedIn()) {
11651
+ return [this.user.zkEvm.ethAddress];
11652
+ }
11653
+ const { magicProvider, user } = await loginZkEvmUser({
11654
+ authManager: this.authManager,
11655
+ config: this.config,
11656
+ magicAdapter: this.magicAdapter,
11657
+ multiRollupApiClients: this.multiRollupApiClients,
11658
+ });
11659
+ this.user = user;
11660
+ this.magicProvider = magicProvider;
11661
+ this.eventEmitter.emit(ProviderEvent.ACCOUNTS_CHANGED, [this.user.zkEvm.ethAddress]);
11662
+ return [this.user.zkEvm.ethAddress];
11663
+ }
11664
+ case 'eth_sendTransaction': {
11665
+ if (!this.isLoggedIn()) {
11666
+ throw new JsonRpcError(ProviderErrorCode.UNAUTHORIZED, 'Unauthorised - call eth_requestAccounts first');
11667
+ }
11668
+ return sendTransaction({
11669
+ params: request.params || [],
11670
+ magicProvider: this.magicProvider,
11671
+ transactionAPI: this.transactionAPI,
11672
+ jsonRpcProvider: this.jsonRpcProvider,
11673
+ config: this.config,
11674
+ relayerClient: this.relayerClient,
11675
+ user: this.user,
11676
+ });
11677
+ }
11678
+ case 'eth_accounts': {
11679
+ return this.isLoggedIn() ? [this.user.zkEvm.ethAddress] : [];
11680
+ }
11681
+ // Pass through methods
11682
+ case 'eth_gasPrice':
11683
+ case 'eth_getBalance':
11684
+ case 'eth_getStorageAt':
11685
+ case 'eth_estimateGas':
11686
+ case 'eth_call':
11687
+ case 'eth_blockNumber':
11688
+ case 'eth_chainId':
11689
+ case 'eth_getBlockByHash':
11690
+ case 'eth_getBlockByNumber':
11691
+ case 'eth_getTransactionByHash':
11692
+ case 'eth_getTransactionReceipt':
11693
+ case 'eth_getTransactionCount': {
11694
+ return this.jsonRpcProvider.send(request.method, request.params || []);
11695
+ }
11696
+ default: {
11697
+ throw new JsonRpcError(ProviderErrorCode.UNSUPPORTED_METHOD, 'Method not supported');
11698
+ }
11699
+ }
11700
+ }
11701
+ async performJsonRpcRequest(request) {
11702
+ const { id, jsonrpc } = request;
11703
+ try {
11704
+ const result = await this.performRequest(request);
11705
+ return {
11706
+ id,
11707
+ jsonrpc,
11708
+ result,
11709
+ };
11710
+ }
11711
+ catch (error) {
11712
+ let jsonRpcError;
11713
+ if (error instanceof JsonRpcError) {
11714
+ jsonRpcError = error;
11715
+ }
11716
+ else if (error instanceof Error) {
11717
+ jsonRpcError = new JsonRpcError(RpcErrorCode.INTERNAL_ERROR, error.message);
11718
+ }
11719
+ else {
11720
+ jsonRpcError = new JsonRpcError(RpcErrorCode.INTERNAL_ERROR, 'Internal error');
11721
+ }
11722
+ return {
11723
+ id,
11724
+ jsonrpc,
11725
+ error: jsonRpcError,
11726
+ };
11727
+ }
11728
+ }
11729
+ async request(request) {
11730
+ try {
11731
+ return this.performRequest(request);
11732
+ }
11733
+ catch (error) {
11734
+ if (error instanceof JsonRpcError) {
11735
+ throw error;
11736
+ }
11737
+ if (error instanceof Error) {
11738
+ throw new JsonRpcError(RpcErrorCode.INTERNAL_ERROR, error.message);
11739
+ }
11740
+ throw new JsonRpcError(RpcErrorCode.INTERNAL_ERROR, 'Internal error');
11741
+ }
11742
+ }
11743
+ sendAsync(request, callback) {
11744
+ if (!callback) {
11745
+ throw new Error('No callback provided');
11746
+ }
11747
+ if (Array.isArray(request)) {
11748
+ Promise.all(request.map(this.performJsonRpcRequest)).then((result) => {
11749
+ callback(null, result);
11750
+ }).catch((error) => {
11751
+ callback(error, []);
11752
+ });
11753
+ }
11754
+ else {
11755
+ this.performJsonRpcRequest(request).then((result) => {
11756
+ callback(null, result);
11757
+ }).catch((error) => {
11758
+ callback(error, null);
11759
+ });
11760
+ }
11761
+ }
11762
+ async send(request, callbackOrParams, callback) {
11763
+ // Web3 >= 1.0.0-beta.38 calls `send` with method and parameters.
11764
+ if (typeof request === 'string') {
11765
+ if (typeof callbackOrParams === 'function') {
11766
+ return this.sendAsync({
11767
+ method: request,
11768
+ params: [],
11769
+ }, callbackOrParams);
11770
+ }
11771
+ if (callback) {
11772
+ return this.sendAsync({
11773
+ method: request,
11774
+ params: Array.isArray(callbackOrParams) ? callbackOrParams : [],
11775
+ }, callback);
11776
+ }
11777
+ return this.request({
11778
+ method: request,
11779
+ params: Array.isArray(callbackOrParams) ? callbackOrParams : [],
11780
+ });
11781
+ }
11782
+ // Web3 <= 1.0.0-beta.37 uses `send` with a callback for async queries.
11783
+ if (typeof callbackOrParams === 'function') {
11784
+ return this.sendAsync(request, callbackOrParams);
11785
+ }
11786
+ if (!Array.isArray(request) && typeof request === 'object') {
11787
+ return this.performJsonRpcRequest(request);
11788
+ }
11789
+ throw new JsonRpcError(RpcErrorCode.INVALID_REQUEST, 'Invalid request');
11790
+ }
11791
+ on(event, listener) {
11792
+ this.eventEmitter.on(event, listener);
11793
+ }
11794
+ removeListener(event, listener) {
11795
+ this.eventEmitter.removeListener(event, listener);
11796
+ }
11797
+ }
11798
+
11071
11799
  class Passport {
11072
11800
  authManager;
11073
11801
  config;
@@ -11075,6 +11803,7 @@ class Passport {
11075
11803
  immutableXClient;
11076
11804
  magicAdapter;
11077
11805
  passportImxProviderFactory;
11806
+ multiRollupApiClients;
11078
11807
  constructor(passportModuleConfiguration) {
11079
11808
  this.config = new PassportConfiguration(passportModuleConfiguration);
11080
11809
  this.authManager = new AuthManager(this.config);
@@ -11084,6 +11813,7 @@ class Passport {
11084
11813
  || new ImmutableXClient({
11085
11814
  baseConfig: passportModuleConfiguration.baseConfig,
11086
11815
  });
11816
+ this.multiRollupApiClients = new MultiRollupApiClients(this.config.multiRollupConfig);
11087
11817
  this.passportImxProviderFactory = new PassportImxProviderFactory({
11088
11818
  authManager: this.authManager,
11089
11819
  config: this.config,
@@ -11113,12 +11843,29 @@ class Passport {
11113
11843
  async connectImxWithCredentials(tokenResponse) {
11114
11844
  return this.passportImxProviderFactory.getProviderWithCredentials(tokenResponse);
11115
11845
  }
11846
+ // TODO ID-926 Make method public once development has been finalised
11847
+ connectEvm() {
11848
+ return new ZkEvmProvider({
11849
+ authManager: this.authManager,
11850
+ magicAdapter: this.magicAdapter,
11851
+ config: this.config,
11852
+ confirmationScreen: this.confirmationScreen,
11853
+ multiRollupApiClients: this.multiRollupApiClients,
11854
+ });
11855
+ }
11116
11856
  async loginCallback() {
11117
11857
  return this.authManager.loginCallback();
11118
11858
  }
11119
11859
  async logout() {
11120
11860
  return this.authManager.logout();
11121
11861
  }
11862
+ /**
11863
+ * This method should only be called from the logout redirect uri
11864
+ * when logout mode is 'silent'.
11865
+ */
11866
+ async logoutSilentCallback(url) {
11867
+ return this.authManager.logoutSilentCallback(url);
11868
+ }
11122
11869
  async logoutDeviceFlow() {
11123
11870
  return this.authManager.logoutDeviceFlow();
11124
11871
  }
@@ -12035,31 +12782,25 @@ class ImmutableApiClientFactory {
12035
12782
  }
12036
12783
  }
12037
12784
 
12038
- const DEVNET_CHAIN_NAME = 'imtbl-zkevm-devnet';
12039
12785
  const TESTNET_CHAIN_NAME = 'imtbl-zkevm-testnet';
12040
12786
  const MAINNET_CHAIN_NAME = 'imtbl-zkevm-mainnet';
12041
- function getOrderbookConfig(chainName) {
12042
- switch (chainName) {
12043
- case DEVNET_CHAIN_NAME:
12787
+ function getOrderbookConfig(environment) {
12788
+ switch (environment) {
12789
+ case Environment$1.SANDBOX:
12044
12790
  return {
12045
- seaportContractAddress: '0x41388404Efb7a68Fd31d75CEf71dF91e2BDBa2fb',
12046
- zoneContractAddress: '0xCb5063b0c1dcF4f7fed8E7eaa79faf9859792767',
12047
- apiEndpoint: 'https://order-book-mr.dev.imtbl.com',
12048
- provider: new providers.JsonRpcProvider('https://zkevm-rpc.dev.x.immutable.com'),
12049
- };
12050
- case TESTNET_CHAIN_NAME:
12051
- return {
12052
- seaportContractAddress: '0x45E23dA18804F99Cf67408AeBE85F67c958381Ff',
12053
- zoneContractAddress: '0x25b00b7eb97eab6194798E9B8eF63Aa526D5bd7E',
12791
+ seaportContractAddress: '0x474989C4D25DD41B0B9b1ECb4643B9Fe25f83B19',
12792
+ zoneContractAddress: '0x6FeDb4949E5b452700A8a8956999a7E05B6770F3',
12054
12793
  apiEndpoint: 'https://order-book-mr.sandbox.imtbl.com',
12794
+ chainName: TESTNET_CHAIN_NAME,
12055
12795
  provider: new providers.JsonRpcProvider('https://zkevm-rpc.sandbox.x.immutable.com'),
12056
12796
  };
12057
- case MAINNET_CHAIN_NAME:
12058
- // not yet deployed
12797
+ // not yet deployed
12798
+ case Environment$1.PRODUCTION:
12059
12799
  return {
12060
12800
  seaportContractAddress: '',
12061
12801
  zoneContractAddress: '',
12062
12802
  apiEndpoint: 'https://order-book-mr.imtbl.com',
12803
+ chainName: MAINNET_CHAIN_NAME,
12063
12804
  provider: new providers.JsonRpcProvider('https://zkevm-rpc.x.immutable.com'),
12064
12805
  };
12065
12806
  default:
@@ -13018,21 +13759,19 @@ class Orderbook {
13018
13759
  apiClient;
13019
13760
  seaport;
13020
13761
  orderbookConfig;
13021
- constructor(config, localConfig) {
13022
- // either use preconfigured config or local config passed in
13023
- const maybeConfig = getOrderbookConfig(config.overrides?.chainName) || localConfig;
13024
- if (!maybeConfig) {
13025
- throw new Error('Orderbook configuration not passed, either select one of the preseet chainNames or pass in localConfig');
13026
- }
13027
- this.orderbookConfig = maybeConfig;
13028
- const { apiEndpoint } = this.orderbookConfig;
13029
- if (!apiEndpoint) {
13030
- throw new Error('API endpoint must be provided as an override');
13762
+ constructor(config) {
13763
+ const obConfig = getOrderbookConfig(config.baseConfig.environment);
13764
+ const finalConfig = {
13765
+ ...obConfig,
13766
+ ...config.overrides,
13767
+ };
13768
+ if (!finalConfig) {
13769
+ throw new Error('Orderbook configuration not passed, please specify the environment under config.baseConfig.environment');
13031
13770
  }
13032
- // TODO: Move chainId lookup to a map based on env. Just using override to get dev started
13033
- const chainName = config.overrides?.chainName;
13034
- if (!chainName) {
13035
- throw new Error('chainName must be provided as an override');
13771
+ this.orderbookConfig = finalConfig;
13772
+ const { apiEndpoint, chainName } = this.orderbookConfig;
13773
+ if (!apiEndpoint) {
13774
+ throw new Error('API endpoint must be provided');
13036
13775
  }
13037
13776
  this.apiClient = new ImmutableApiClientFactory(apiEndpoint, chainName, this.orderbookConfig.seaportContractAddress).create();
13038
13777
  const seaportLibFactory = new SeaportLibFactory(this.orderbookConfig.seaportContractAddress, this.orderbookConfig.provider);
@@ -24367,7 +25106,7 @@ const ETH_MAINNET_CHAIN_ID = 'eip155:1';
24367
25106
  /**
24368
25107
  * @constant {string} ZKEVM_DEVNET_CHAIN_ID - The chain ID for the zkEVM devnet (EIP-155 compatible format).
24369
25108
  */
24370
- const ZKEVM_DEVNET_CHAIN_ID = 'eip155:13403';
25109
+ const ZKEVM_DEVNET_CHAIN_ID = 'eip155:13423';
24371
25110
  /**
24372
25111
  /**
24373
25112
  * @constant {string} ZKEVM_TESTNET_CHAIN_ID - The chain ID for the zkEVM testnet (EIP-155 compatible format).
@@ -24425,14 +25164,14 @@ const SUPPORTED_BRIDGES_FOR_ENVIRONMENT = {
24425
25164
  */
24426
25165
  const CONTRACTS_FOR_BRIDGE = new Map()
24427
25166
  .set(ETH_SEPOLIA_TO_ZKEVM_DEVNET, {
24428
- rootChainERC20Predicate: '0x15Dd735de418B6d290727aed82cC25F8966dE4A5',
24429
- rootChainStateSender: '0xb3Bac13799dAca9D9eC9307303a65fA1218b4724',
25167
+ rootChainERC20Predicate: '0xf0b3435411A74F1aeCBD0fd6D53a90D5227fEeba',
25168
+ rootChainStateSender: '0x868097dbAcfD431F441d09D0e4D3B5eD3182E597',
24430
25169
  childChainERC20Predicate: '0x0000000000000000000000000000000000001004',
24431
25170
  childChainStateReceiver: '0x0000000000000000000000000000000000001001',
24432
25171
  })
24433
25172
  .set(ETH_SEPOLIA_TO_ZKEVM_TESTNET, {
24434
- rootChainERC20Predicate: '0x9A7E4C4337a70C6754a9672F5ba69084463794B8',
24435
- rootChainStateSender: '0xfBfF6FD165adFA113bE39eE85ef030A996153253',
25173
+ rootChainERC20Predicate: '0x0C15a8359865867CdCC44f98b2F3fd5DF098C7E0',
25174
+ rootChainStateSender: '0x4C80001188db53dbc2eaAb32d5ef825feEedECA5',
24436
25175
  childChainERC20Predicate: '0x0000000000000000000000000000000000001004',
24437
25176
  childChainStateReceiver: '0x0000000000000000000000000000000000001001',
24438
25177
  })
@@ -25024,7 +25763,7 @@ function getQuote(otherCurrency, tradeType, tradeInfo, slippage) {
25024
25763
  }
25025
25764
 
25026
25765
  const IMMUTABLE_TESTNET_RPC_URL = 'https://zkevm-rpc.sandbox.x.immutable.com';
25027
- const IMMUTABLE_TESTNET_CHAIN_ID = 13392;
25766
+ const IMMUTABLE_TESTNET_CHAIN_ID = 13372;
25028
25767
 
25029
25768
  const TIMX_IMMUTABLE_TESTNET = {
25030
25769
  chainId: IMMUTABLE_TESTNET_CHAIN_ID,
@@ -26663,16 +27402,28 @@ const SUPPORTED_CHAIN_IDS_FOR_ENVIRONMENT = {
26663
27402
  [Environment$1.PRODUCTION]: SUPPORTED_PRODUCTION_CHAINS,
26664
27403
  };
26665
27404
  function validateOverrides(overrides) {
26666
- Object.entries(overrides).forEach(([key, value]) => {
26667
- if (!value) {
27405
+ const keysToCheck = ['rpcURL', 'exchangeContracts', 'commonRoutingTokens', 'nativeToken'];
27406
+ for (const key of keysToCheck) {
27407
+ if (!overrides[key]) {
26668
27408
  throw new InvalidConfigurationError(`Missing override: ${key}`);
26669
27409
  }
26670
- });
27410
+ }
26671
27411
  Object.entries(overrides.exchangeContracts).forEach(([key, contract]) => {
26672
27412
  if (!isValidNonZeroAddress(contract)) {
26673
27413
  throw new InvalidConfigurationError(`Invalid exchange contract address for ${key}`);
26674
27414
  }
26675
27415
  });
27416
+ if (!overrides.secondaryFees) {
27417
+ return;
27418
+ }
27419
+ for (const secondaryFee of overrides.secondaryFees) {
27420
+ if (!isValidNonZeroAddress(secondaryFee.feeRecipient)) {
27421
+ throw new InvalidConfigurationError(`Invalid secondary fee recipient address: ${secondaryFee.feeRecipient}`);
27422
+ }
27423
+ if (secondaryFee.feeBasisPoints < 0 || secondaryFee.feeBasisPoints > 10000) {
27424
+ throw new InvalidConfigurationError(`Invalid secondary fee percentage: ${secondaryFee.feeBasisPoints}`);
27425
+ }
27426
+ }
26676
27427
  }
26677
27428
  /**
26678
27429
  * {@link ExchangeConfiguration} is used to configure the {@link Exchange} class.
@@ -26682,6 +27433,7 @@ function validateOverrides(overrides) {
26682
27433
  class ExchangeConfiguration {
26683
27434
  baseConfig;
26684
27435
  chain;
27436
+ secondaryFees;
26685
27437
  constructor({ chainId, baseConfig, overrides }) {
26686
27438
  this.baseConfig = baseConfig;
26687
27439
  if (overrides) {
@@ -26693,8 +27445,10 @@ class ExchangeConfiguration {
26693
27445
  commonRoutingTokens: overrides.commonRoutingTokens,
26694
27446
  nativeToken: overrides.nativeToken,
26695
27447
  };
27448
+ this.secondaryFees = overrides.secondaryFees ? overrides.secondaryFees : [];
26696
27449
  return;
26697
27450
  }
27451
+ this.secondaryFees = [];
26698
27452
  const chain = SUPPORTED_CHAIN_IDS_FOR_ENVIRONMENT[baseConfig.environment][chainId];
26699
27453
  if (!chain) {
26700
27454
  throw new ChainNotSupportedError(chainId, baseConfig.environment);
@@ -26708,11 +27462,13 @@ class Exchange {
26708
27462
  router;
26709
27463
  chainId;
26710
27464
  nativeToken;
27465
+ secondaryFees;
26711
27466
  constructor(configuration) {
26712
27467
  const config = new ExchangeConfiguration(configuration);
26713
27468
  this.chainId = config.chain.chainId;
26714
27469
  this.nativeToken = config.chain.nativeToken;
26715
27470
  this.provider = new ethers.providers.JsonRpcProvider(config.chain.rpcUrl);
27471
+ this.secondaryFees = config.secondaryFees;
26716
27472
  this.router = new Router(this.provider, config.chain.commonRoutingTokens, {
26717
27473
  multicallAddress: config.chain.contracts.multicall,
26718
27474
  factoryAddress: config.chain.contracts.coreFactory,
@@ -26795,6 +27551,9 @@ class Exchange {
26795
27551
  async getUnsignedSwapTxFromAmountOut(fromAddress, tokenInAddress, tokenOutAddress, amountOut, slippagePercent = DEFAULT_SLIPPAGE, maxHops = DEFAULT_MAX_HOPS, deadline = DEFAULT_DEADLINE) {
26796
27552
  return await this.getUnsignedSwapTx(fromAddress, tokenInAddress, tokenOutAddress, amountOut, slippagePercent, maxHops, deadline, TradeType.EXACT_OUTPUT);
26797
27553
  }
27554
+ thereAreSecondaryFees() {
27555
+ return this.secondaryFees.length > 0;
27556
+ }
26798
27557
  }
26799
27558
 
26800
27559
  /* eslint-disable class-methods-use-this */
@@ -26871,8 +27630,8 @@ const $762782b6c862d954$export$db5daa1b5156ccfe = [
26871
27630
  */ var $0472f23319457bfb$export$c06e1e7429de6283;
26872
27631
  (function(ChainId) {
26873
27632
  ChainId[ChainId["IMTBL_ZKEVM_MAINNET"] = 13371] = "IMTBL_ZKEVM_MAINNET";
26874
- ChainId[ChainId["IMTBL_ZKEVM_TESTNET"] = 13392] = "IMTBL_ZKEVM_TESTNET";
26875
- ChainId[ChainId["IMTBL_ZKEVM_DEVNET"] = 13403] = "IMTBL_ZKEVM_DEVNET";
27633
+ ChainId[ChainId["IMTBL_ZKEVM_TESTNET"] = 13372] = "IMTBL_ZKEVM_TESTNET";
27634
+ ChainId[ChainId["IMTBL_ZKEVM_DEVNET"] = 13423] = "IMTBL_ZKEVM_DEVNET";
26876
27635
  ChainId[ChainId["ETHEREUM"] = 1] = "ETHEREUM";
26877
27636
  ChainId[ChainId["SEPOLIA"] = 11155111] = "SEPOLIA";
26878
27637
  })($0472f23319457bfb$export$c06e1e7429de6283 || ($0472f23319457bfb$export$c06e1e7429de6283 = {}));
@@ -26957,6 +27716,10 @@ const $d85ad1457a3f1a83$export$161d4a74df65fc08 = {
26957
27716
  [(Environment$1).SANDBOX]: "https://checkout-api.sandbox.immutable.com",
26958
27717
  [(Environment$1).PRODUCTION]: "https://checkout-api.immutable.com"
26959
27718
  };
27719
+ const $d85ad1457a3f1a83$export$7b057be2a3f512cc = {
27720
+ [(Environment$1).SANDBOX]: "https://zkevm-rpc.sandbox.x.immutable.com",
27721
+ [(Environment$1).PRODUCTION]: "https://zkevm-rpc.x.immutable.com"
27722
+ };
26960
27723
  const $d85ad1457a3f1a83$export$6f24f3cef7d501c4 = new Map([
26961
27724
  [
26962
27725
  ($0472f23319457bfb$export$c06e1e7429de6283).ETHEREUM,
@@ -26982,7 +27745,7 @@ const $d85ad1457a3f1a83$export$6f24f3cef7d501c4 = new Map([
26982
27745
  chainIdHex: `0x${($0472f23319457bfb$export$c06e1e7429de6283).IMTBL_ZKEVM_MAINNET.toString(16)}`,
26983
27746
  chainName: ($0472f23319457bfb$export$b874c6b1dfe85e02).IMTBL_ZKEVM_MAINNET,
26984
27747
  rpcUrls: [
26985
- "https://zkevm-rpc.x.immutable.com"
27748
+ "https://rpc.immutable.com"
26986
27749
  ],
26987
27750
  nativeCurrency: {
26988
27751
  name: "IMX",
@@ -27017,7 +27780,7 @@ const $d85ad1457a3f1a83$export$3e81fc0987227f10 = new Map([
27017
27780
  chainIdHex: `0x${($0472f23319457bfb$export$c06e1e7429de6283).IMTBL_ZKEVM_TESTNET.toString(16)}`,
27018
27781
  chainName: ($0472f23319457bfb$export$b874c6b1dfe85e02).IMTBL_ZKEVM_TESTNET,
27019
27782
  rpcUrls: [
27020
- "https://zkevm-rpc.sandbox.x.immutable.com"
27783
+ "https://rpc.testnet.immutable.com"
27021
27784
  ],
27022
27785
  nativeCurrency: {
27023
27786
  name: "IMX",
@@ -27393,16 +28156,19 @@ async function $5c763be0b0b81038$var$getMetaMaskProvider() {
27393
28156
  if (!provider || !provider.request) throw new ($a8bc256d81a5e2c1$export$b722478a3cbfa3bc)("No MetaMask provider installed.", ($a8bc256d81a5e2c1$export$e3dc0620abde7f5a).METAMASK_PROVIDER_ERROR);
27394
28157
  return new (Web3Provider)(provider);
27395
28158
  }
27396
- async function $5c763be0b0b81038$export$500fbc0cd14cdbaa(defaultProvider) {
27397
- let web3Provider = null;
27398
- switch(defaultProvider){
28159
+ async function $5c763be0b0b81038$export$500fbc0cd14cdbaa(walletProviderName) {
28160
+ let provider = null;
28161
+ switch(walletProviderName){
27399
28162
  case ($e768639828688ca3$export$2d7a51a18d87e21d).METAMASK:
27400
- web3Provider = await $5c763be0b0b81038$var$getMetaMaskProvider();
28163
+ provider = await $5c763be0b0b81038$var$getMetaMaskProvider();
27401
28164
  break;
27402
28165
  default:
27403
28166
  throw new ($a8bc256d81a5e2c1$export$b722478a3cbfa3bc)("Provider not supported", ($a8bc256d81a5e2c1$export$e3dc0620abde7f5a).DEFAULT_PROVIDER_ERROR);
27404
28167
  }
27405
- return web3Provider;
28168
+ return {
28169
+ provider: provider,
28170
+ walletProviderName: walletProviderName
28171
+ };
27406
28172
  }
27407
28173
 
27408
28174
 
@@ -27411,9 +28177,8 @@ async function $5c763be0b0b81038$export$500fbc0cd14cdbaa(defaultProvider) {
27411
28177
 
27412
28178
 
27413
28179
 
27414
-
27415
28180
  function $bb88265fe45a0393$export$ebe4804963e71f98(web3Provider) {
27416
- if (web3Provider && web3Provider instanceof (Web3Provider) && web3Provider.provider?.request) return true;
28181
+ if (web3Provider && web3Provider.provider?.request && typeof web3Provider.provider.request === "function") return true;
27417
28182
  return false;
27418
28183
  }
27419
28184
  async function $bb88265fe45a0393$export$9e1fd9cc88c637a0(config, web3Provider, validateProviderOptions) {
@@ -27623,10 +28388,23 @@ class $4013c5c91bb535f6$export$6ad73ea7e1b6f37f extends Error {
27623
28388
  this.message = message;
27624
28389
  }
27625
28390
  }
27626
- const $4013c5c91bb535f6$var$networkMap = (prod, dev)=>{
27627
- if (dev) return $d85ad1457a3f1a83$export$3a9ebede6a150274;
27628
- if (prod) return $d85ad1457a3f1a83$export$6f24f3cef7d501c4;
27629
- return $d85ad1457a3f1a83$export$3e81fc0987227f10;
28391
+ const $4013c5c91bb535f6$var$networkMap = (prod, dev, local)=>{
28392
+ let networks;
28393
+ if (dev) networks = ($d85ad1457a3f1a83$export$3a9ebede6a150274);
28394
+ else if (prod) {
28395
+ networks = ($d85ad1457a3f1a83$export$6f24f3cef7d501c4);
28396
+ if (local) {
28397
+ const rpcUrls = networks.get(($0472f23319457bfb$export$c06e1e7429de6283).IMTBL_ZKEVM_MAINNET)?.rpcUrls;
28398
+ rpcUrls?.splice(0, 1, ($d85ad1457a3f1a83$export$7b057be2a3f512cc)[(Environment$1).PRODUCTION]);
28399
+ }
28400
+ } else {
28401
+ networks = ($d85ad1457a3f1a83$export$3e81fc0987227f10);
28402
+ if (local) {
28403
+ const rpcUrls = networks.get(($0472f23319457bfb$export$c06e1e7429de6283).IMTBL_ZKEVM_TESTNET)?.rpcUrls;
28404
+ rpcUrls?.splice(0, 1, ($d85ad1457a3f1a83$export$7b057be2a3f512cc)[(Environment$1).SANDBOX]);
28405
+ }
28406
+ }
28407
+ return networks;
27630
28408
  };
27631
28409
  const $4013c5c91bb535f6$export$9b794d067cdd1af6 = (config)=>{
27632
28410
  // DevMode and Sandbox will both use Sepolia.
@@ -27644,6 +28422,11 @@ class $4013c5c91bb535f6$export$4823433c4a67bbc6 {
27644
28422
  // This will be used to get around the lack of
27645
28423
  // Environment.DEVELOPMENT
27646
28424
  isDevelopment = false;
28425
+ // This is a hidden feature that is only available
28426
+ // when building the project from source code.
28427
+ // This will be used to get around the lack of
28428
+ // Environment.LOCAL_DEVELOPMENT
28429
+ isLocal = false;
27647
28430
  isProduction;
27648
28431
  remote;
27649
28432
  environment;
@@ -27653,7 +28436,7 @@ class $4013c5c91bb535f6$export$4823433c4a67bbc6 {
27653
28436
  this.environment = config.baseConfig.environment;
27654
28437
  // Developer mode will super set any environment configuration
27655
28438
  this.isProduction = !this.isDevelopment && this.environment === (Environment$1).PRODUCTION;
27656
- this.networkMap = $4013c5c91bb535f6$var$networkMap(this.isProduction, this.isDevelopment);
28439
+ this.networkMap = $4013c5c91bb535f6$var$networkMap(this.isProduction, this.isDevelopment, this.isLocal);
27657
28440
  this.remote = new ($a492ee374ae7b613$export$d902b56530cd5f87)({
27658
28441
  isDevelopment: this.isDevelopment,
27659
28442
  isProduction: this.isProduction
@@ -27799,10 +28582,7 @@ class $a8cb37a3fc8eb863$export$1f60ba4ec72508a0 {
27799
28582
  * @param {CreateProviderParams} params - The parameters for creating the provider.
27800
28583
  * @returns {Promise<CreateProviderResult>} A promise that resolves to the created provider.
27801
28584
  */ async createProvider(params) {
27802
- const web3Provider = await $5c763be0b0b81038$export$500fbc0cd14cdbaa(params.walletProvider);
27803
- return {
27804
- provider: web3Provider
27805
- };
28585
+ return await $5c763be0b0b81038$export$500fbc0cd14cdbaa(params.walletProvider);
27806
28586
  }
27807
28587
  /**
27808
28588
  * Checks if a wallet is connected to the specified provider.
@@ -27919,7 +28699,7 @@ class $a8cb37a3fc8eb863$export$1f60ba4ec72508a0 {
27919
28699
  function $parcel$export(e, n, v, s) {
27920
28700
  Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true});
27921
28701
  }
27922
- const $d663162fd5a0853f$export$38a083d9fb5551ca = "0.4.0-alpha.1";
28702
+ const $d663162fd5a0853f$export$38a083d9fb5551ca = "0.4.0-alpha.3";
27923
28703
  const $d663162fd5a0853f$export$83bf90b30cdfd29f = ()=>false;
27924
28704
  const $d663162fd5a0853f$export$1169f5475725171b = ()=>$d663162fd5a0853f$export$38a083d9fb5551ca;
27925
28705
 
@@ -29718,4 +30498,4 @@ class ERC721PermissionedMintable {
29718
30498
  }
29719
30499
  }
29720
30500
 
29721
- export { APIError, BlockchainData, $15cc9e120aa6f3bf$export$d1bfa21f7c76447a as BridgeEventType, $1f969328e5988c99$export$30f61ebf204c69f6 as BridgeReact, $d85ad1457a3f1a83$export$161d4a74df65fc08 as CHECKOUT_API_BASE_URL, $0472f23319457bfb$export$c06e1e7429de6283 as ChainId, $0472f23319457bfb$export$b874c6b1dfe85e02 as ChainName, $a8cb37a3fc8eb863$export$1f60ba4ec72508a0 as Checkout, $a8bc256d81a5e2c1$export$e3dc0620abde7f5a as CheckoutErrorType, $045213b18e9f1f94$export$75be0f6af9650f2c as CheckoutWidgetTagNames, $430e3eda76fa4d5f$export$af210a0808087845 as CheckoutWidgets, $a85ecdbd885c58ad$export$e72e7f9969a47dd3 as ConnectEventType, $f2083cd30e2f5c56$export$49d62957f420a1e2 as ConnectReact, ERC20, ERC721PermissionedMintable, Environment$1 as Environment, $de275b98d2b651c3$export$788b1fd17f3dad84 as GasEstimateType, GenericIMXProvider, $207ed853f11d19d5$export$5a0ace85cae72d45 as IMTBLWidgetEvents, ImmutableConfiguration, ImmutableXClient, MetaMaskIMXProvider, $a47e48dd2c04791b$export$1f05a55fe0680cc7 as NetworkFilterTypes, Networks, $ad06b030b1a3ba34$export$b80d2daf830437b9 as OrchestrationEventType, Orderbook, Passport, PassportError, ProviderConfiguration, $53d219e7f6bf0cd6$export$140a49745ab55563 as SwapEventType, $a4fbb8e3a6aeff58$export$971e031379577f4 as SwapReact, $08d5ddc39acd6833$export$fd9b17d87f4121d2 as TokenFilterTypes, $430e3eda76fa4d5f$export$bf1548ba7e61c17f as UpdateConfig, $77b6aac5c353d4a9$export$d9be06b70b28c742 as WalletEventType, $4f91c5f280efe242$export$a75605c67ea83a5a as WalletFilterTypes, $e768639828688ca3$export$2d7a51a18d87e21d as WalletProviderName, $89d55ace0f8f1c07$export$ceaac94f34dba154 as WalletReact, $045213b18e9f1f94$export$c88931fdc51854eb as WidgetTheme, module };
30501
+ export { APIError, BlockchainData, $15cc9e120aa6f3bf$export$d1bfa21f7c76447a as BridgeEventType, $1f969328e5988c99$export$30f61ebf204c69f6 as BridgeReact, $d85ad1457a3f1a83$export$161d4a74df65fc08 as CHECKOUT_API_BASE_URL, $0472f23319457bfb$export$c06e1e7429de6283 as ChainId, $0472f23319457bfb$export$b874c6b1dfe85e02 as ChainName, $a8cb37a3fc8eb863$export$1f60ba4ec72508a0 as Checkout, $a8bc256d81a5e2c1$export$e3dc0620abde7f5a as CheckoutErrorType, $045213b18e9f1f94$export$75be0f6af9650f2c as CheckoutWidgetTagNames, $430e3eda76fa4d5f$export$af210a0808087845 as CheckoutWidgets, $a85ecdbd885c58ad$export$e72e7f9969a47dd3 as ConnectEventType, $f2083cd30e2f5c56$export$49d62957f420a1e2 as ConnectReact, ERC20, ERC721PermissionedMintable, Environment$1 as Environment, $de275b98d2b651c3$export$788b1fd17f3dad84 as GasEstimateType, GenericIMXProvider, $207ed853f11d19d5$export$5a0ace85cae72d45 as IMTBLWidgetEvents, ImmutableConfiguration, ImmutableXClient, JsonRpcError, MetaMaskIMXProvider, $a47e48dd2c04791b$export$1f05a55fe0680cc7 as NetworkFilterTypes, Networks, $ad06b030b1a3ba34$export$b80d2daf830437b9 as OrchestrationEventType, Orderbook, Passport, PassportError, ProviderConfiguration, ProviderErrorCode, ProviderEvent, RpcErrorCode, $53d219e7f6bf0cd6$export$140a49745ab55563 as SwapEventType, $a4fbb8e3a6aeff58$export$971e031379577f4 as SwapReact, $08d5ddc39acd6833$export$fd9b17d87f4121d2 as TokenFilterTypes, $430e3eda76fa4d5f$export$bf1548ba7e61c17f as UpdateConfig, $77b6aac5c353d4a9$export$d9be06b70b28c742 as WalletEventType, $4f91c5f280efe242$export$a75605c67ea83a5a as WalletFilterTypes, $e768639828688ca3$export$2d7a51a18d87e21d as WalletProviderName, $89d55ace0f8f1c07$export$ceaac94f34dba154 as WalletReact, $045213b18e9f1f94$export$c88931fdc51854eb as WidgetTheme, module };