@atomiqlabs/chain-evm 2.2.1 → 2.4.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.
@@ -120,7 +120,7 @@ function initializeAlpen(options, bitcoinRpc, network) {
120
120
  maxParallelCalls: options?.evmConfig?.maxParallelCalls ?? 5,
121
121
  useAccessLists: options?.evmConfig?.useAccessLists,
122
122
  defaultAccessListAddresses: options?.evmConfig?.defaultAccessListAddresses
123
- }, options.retryPolicy, Fees);
123
+ }, options.retryPolicy, Fees, network);
124
124
  const btcRelay = new EVMBtcRelay_1.EVMBtcRelay(chainInterface, bitcoinRpc, network, options.btcRelayContract ?? defaultContractAddresses.btcRelayContract, options.btcRelayDeploymentHeight ?? defaultContractAddresses.btcRelayDeploymentHeight);
125
125
  const swapContract = new EVMSwapContract_1.EVMSwapContract(chainInterface, btcRelay, options.swapContract ?? defaultContractAddresses.swapContract, {
126
126
  refund: {
@@ -102,7 +102,7 @@ function initializeBotanix(options, bitcoinRpc, network) {
102
102
  type: "timer",
103
103
  delayMs: 1000
104
104
  }
105
- }, options.retryPolicy, Fees);
105
+ }, options.retryPolicy, Fees, network);
106
106
  const btcRelay = new EVMBtcRelay_1.EVMBtcRelay(chainInterface, bitcoinRpc, network, options.btcRelayContract ?? defaultContractAddresses.btcRelayContract, options.btcRelayDeploymentHeight ?? defaultContractAddresses.btcRelayDeploymentHeight);
107
107
  const swapContract = new EVMSwapContract_1.EVMSwapContract(chainInterface, btcRelay, options.swapContract ?? defaultContractAddresses.swapContract, {
108
108
  refund: {
@@ -111,7 +111,7 @@ function initializeCitrea(options, bitcoinRpc, network) {
111
111
  maxParallelCalls: options?.evmConfig?.maxParallelCalls ?? 5,
112
112
  useAccessLists: options?.evmConfig?.useAccessLists,
113
113
  defaultAccessListAddresses: options?.evmConfig?.defaultAccessListAddresses
114
- }, options.retryPolicy, Fees);
114
+ }, options.retryPolicy, Fees, network);
115
115
  chainInterface.Tokens = new CitreaTokens_1.CitreaTokens(chainInterface); //Override with custom token module allowing l1 state diff based fee calculation
116
116
  const btcRelay = new CitreaBtcRelay_1.CitreaBtcRelay(chainInterface, bitcoinRpc, network, options.btcRelayContract ?? defaultContractAddresses.btcRelayContract, options.btcRelayDeploymentHeight ?? defaultContractAddresses.btcRelayDeploymentHeight);
117
117
  const swapContract = new CitreaSwapContract_1.CitreaSwapContract(chainInterface, btcRelay, options.swapContract ?? defaultContractAddresses.swapContract, {
@@ -130,7 +130,7 @@ function initializeGoat(options, bitcoinRpc, network) {
130
130
  maxParallelCalls: options?.evmConfig?.maxParallelCalls ?? 5,
131
131
  useAccessLists: options?.evmConfig?.useAccessLists,
132
132
  defaultAccessListAddresses: options?.evmConfig?.defaultAccessListAddresses
133
- }, options.retryPolicy, Fees);
133
+ }, options.retryPolicy, Fees, network);
134
134
  const btcRelay = new EVMBtcRelay_1.EVMBtcRelay(chainInterface, bitcoinRpc, network, options.btcRelayContract ?? defaultContractAddresses.btcRelayContract, options.btcRelayDeploymentHeight ?? defaultContractAddresses.btcRelayDeploymentHeight);
135
135
  const swapContract = new EVMSwapContract_1.EVMSwapContract(chainInterface, btcRelay, options.swapContract ?? defaultContractAddresses.swapContract, {
136
136
  refund: {
@@ -1,4 +1,4 @@
1
- import { ChainInterface, TransactionConfirmationOptions } from "@atomiqlabs/base";
1
+ import { BitcoinNetwork, ChainInterface, TransactionConfirmationOptions } from "@atomiqlabs/base";
2
2
  import { LoggerType } from "../../utils/Utils";
3
3
  import { JsonRpcApiProvider, Signer, Transaction, TransactionRequest } from "ethers";
4
4
  import { EVMBlocks, EVMBlockTag } from "./modules/EVMBlocks";
@@ -107,7 +107,8 @@ export declare class EVMChainInterface<ChainId extends string = string> implemen
107
107
  * @internal
108
108
  */
109
109
  protected logger: LoggerType;
110
- constructor(chainId: ChainId, evmChainId: number, provider: JsonRpcApiProvider, config: EVMConfiguration, retryPolicy?: EVMRetryPolicy, evmFeeEstimator?: EVMFees);
110
+ private readonly bitcoinNetwork?;
111
+ constructor(chainId: ChainId, evmChainId: number, provider: JsonRpcApiProvider, config: EVMConfiguration, retryPolicy?: EVMRetryPolicy, evmFeeEstimator?: EVMFees, bitcoinNetwork?: BitcoinNetwork);
111
112
  /**
112
113
  * @inheritDoc
113
114
  */
@@ -207,4 +208,5 @@ export declare class EVMChainInterface<ChainId extends string = string> implemen
207
208
  * @inheritDoc
208
209
  */
209
210
  wrapSigner(signer: Signer): Promise<EVMSigner>;
211
+ verifyNetwork(bitcoinNetwork: BitcoinNetwork): Promise<void>;
210
212
  }
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.EVMChainInterface = void 0;
4
+ const base_1 = require("@atomiqlabs/base");
4
5
  const Utils_1 = require("../../utils/Utils");
5
6
  const ethers_1 = require("ethers");
6
7
  const EVMBlocks_1 = require("./modules/EVMBlocks");
@@ -17,7 +18,7 @@ const EVMBrowserSigner_1 = require("../wallet/EVMBrowserSigner");
17
18
  * @category Chain Interface
18
19
  */
19
20
  class EVMChainInterface {
20
- constructor(chainId, evmChainId, provider, config, retryPolicy, evmFeeEstimator = new EVMFees_1.EVMFees(provider)) {
21
+ constructor(chainId, evmChainId, provider, config, retryPolicy, evmFeeEstimator = new EVMFees_1.EVMFees(provider), bitcoinNetwork) {
21
22
  var _a, _b, _c, _d;
22
23
  this.chainId = chainId;
23
24
  this.evmChainId = evmChainId;
@@ -28,6 +29,7 @@ class EVMChainInterface {
28
29
  (_b = this._config).finalizedBlockTag ?? (_b.finalizedBlockTag = "finalized");
29
30
  (_c = this._config).finalityCheckStrategy ?? (_c.finalityCheckStrategy = { type: "timer" });
30
31
  (_d = this._config.finalityCheckStrategy).delayMs ?? (_d.delayMs = 1000);
32
+ this.bitcoinNetwork = bitcoinNetwork;
31
33
  this.logger = (0, Utils_1.getLogger)("EVMChainInterface(" + this.evmChainId + "): ");
32
34
  this.Fees = evmFeeEstimator;
33
35
  this.Tokens = new EVMTokens_1.EVMTokens(this);
@@ -195,5 +197,12 @@ class EVMChainInterface {
195
197
  }
196
198
  return new EVMSigner_1.EVMSigner(signer, address);
197
199
  }
200
+ async verifyNetwork(bitcoinNetwork) {
201
+ if (this.bitcoinNetwork != null && bitcoinNetwork !== this.bitcoinNetwork)
202
+ throw new Error(`Network mismatch, the chain interface was not setup for ${base_1.BitcoinNetwork[bitcoinNetwork]}, chain interface network: ${base_1.BitcoinNetwork[this.bitcoinNetwork]}`);
203
+ const network = await this.provider.getNetwork();
204
+ if (network.chainId !== BigInt(this.evmChainId))
205
+ throw new Error(`Network mismatch, the underlying RPC provider isn't using the correct chainId, expected: ${this.evmChainId}, provider returned: ${network.chainId.toString(10)}`);
206
+ }
198
207
  }
199
208
  exports.EVMChainInterface = EVMChainInterface;
@@ -178,4 +178,8 @@ export declare class EVMSwapData extends SwapData {
178
178
  * @param claimHandlerImpl Claim handler implementation used to resolve swap type
179
179
  */
180
180
  static deserializeFromStruct(struct: EscrowDataStruct, claimHandlerImpl: IClaimHandler<any, any>): EVMSwapData;
181
+ /**
182
+ * @inheritDoc
183
+ */
184
+ getEscrowStruct(): any;
181
185
  }
@@ -4,6 +4,7 @@ exports.EVMSwapData = void 0;
4
4
  const base_1 = require("@atomiqlabs/base");
5
5
  const ethers_1 = require("ethers");
6
6
  const TimelockRefundHandler_1 = require("./handlers/refund/TimelockRefundHandler");
7
+ const Utils_1 = require("../../utils/Utils");
7
8
  const FLAG_PAY_OUT = 0x01n;
8
9
  const FLAG_PAY_IN = 0x02n;
9
10
  const FLAG_REPUTATION = 0x04n;
@@ -413,6 +414,12 @@ class EVMSwapData extends base_1.SwapData {
413
414
  const { payOut, payIn, reputation, sequence } = EVMSwapData.toFlags(BigInt(struct.flags));
414
415
  return new EVMSwapData(struct.offerer, struct.claimer, struct.token, struct.refundHandler, struct.claimHandler, payOut, payIn, reputation, sequence, (0, ethers_1.hexlify)(struct.claimData), (0, ethers_1.hexlify)(struct.refundData), BigInt(struct.amount), struct.depositToken, BigInt(struct.securityDeposit), BigInt(struct.claimerBounty), claimHandlerImpl.getType(), undefined, struct.successActionCommitment);
415
416
  }
417
+ /**
418
+ * @inheritDoc
419
+ */
420
+ getEscrowStruct() {
421
+ return (0, Utils_1.replaceBigInts)(this.toEscrowStruct());
422
+ }
416
423
  }
417
424
  exports.EVMSwapData = EVMSwapData;
418
425
  base_1.SwapData.deserializers["evm"] = EVMSwapData;
@@ -1,3 +1,6 @@
1
+ export type ReplaceBigInt<T> = T extends bigint ? string : T extends (infer U)[] ? ReplaceBigInt<U>[] : T extends readonly (infer U)[] ? readonly ReplaceBigInt<U>[] : T extends object ? {
2
+ [K in keyof T]: ReplaceBigInt<T[K]>;
3
+ } : T;
1
4
  /**
2
5
  * Logger interface used across EVM modules.
3
6
  *
@@ -67,3 +70,4 @@ export declare const allowedEthersErrorNumbers: Set<number>;
67
70
  * @category Internal/Utils
68
71
  */
69
72
  export declare const allowedEthersErrorMessages: Set<string>;
73
+ export declare function replaceBigInts<T>(obj: T): ReplaceBigInt<T>;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.allowedEthersErrorMessages = exports.allowedEthersErrorNumbers = exports.allowedEthersErrorCodes = exports.bigIntMax = exports.uint32ReverseEndianness = exports.tryWithRetries = exports.getLogger = exports.onceAsync = exports.timeoutPromise = void 0;
3
+ exports.replaceBigInts = exports.allowedEthersErrorMessages = exports.allowedEthersErrorNumbers = exports.allowedEthersErrorCodes = exports.bigIntMax = exports.uint32ReverseEndianness = exports.tryWithRetries = exports.getLogger = exports.onceAsync = exports.timeoutPromise = void 0;
4
4
  /**
5
5
  * Returns a promise that resolves after `timeoutMillis` unless aborted first.
6
6
  *
@@ -142,3 +142,21 @@ exports.allowedEthersErrorNumbers = new Set([
142
142
  exports.allowedEthersErrorMessages = new Set([
143
143
  "already known"
144
144
  ]);
145
+ function replaceBigInts(obj) {
146
+ const replace = (value) => {
147
+ if (typeof (value) === "bigint")
148
+ return "0x" + value.toString(16);
149
+ if (value == null || typeof (value) !== "object")
150
+ return value;
151
+ if (Array.isArray(value)) {
152
+ return value.map(replace);
153
+ }
154
+ const mapped = {};
155
+ for (const key of Object.keys(value)) {
156
+ mapped[key] = replace(value[key]);
157
+ }
158
+ return mapped;
159
+ };
160
+ return replace(obj);
161
+ }
162
+ exports.replaceBigInts = replaceBigInts;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atomiqlabs/chain-evm",
3
- "version": "2.2.1",
3
+ "version": "2.4.0",
4
4
  "description": "EVM specific base implementation",
5
5
  "main": "./dist/index.js",
6
6
  "types:": "./dist/index.d.ts",
@@ -27,7 +27,7 @@
27
27
  "author": "adambor",
28
28
  "license": "Apache-2.0",
29
29
  "dependencies": {
30
- "@atomiqlabs/base": "^13.2.0",
30
+ "@atomiqlabs/base": "^13.4.0",
31
31
  "@noble/hashes": "^1.8.0",
32
32
  "@scure/btc-signer": "^1.6.0",
33
33
  "buffer": "6.0.3",
@@ -145,7 +145,7 @@ export function initializeAlpen(
145
145
  maxParallelCalls: options?.evmConfig?.maxParallelCalls ?? 5,
146
146
  useAccessLists: options?.evmConfig?.useAccessLists,
147
147
  defaultAccessListAddresses: options?.evmConfig?.defaultAccessListAddresses
148
- }, options.retryPolicy, Fees);
148
+ }, options.retryPolicy, Fees, network);
149
149
 
150
150
  const btcRelay = new EVMBtcRelay(
151
151
  chainInterface, bitcoinRpc, network, options.btcRelayContract ?? defaultContractAddresses.btcRelayContract,
@@ -127,7 +127,7 @@ export function initializeBotanix(
127
127
  type: "timer",
128
128
  delayMs: 1000
129
129
  }
130
- }, options.retryPolicy, Fees);
130
+ }, options.retryPolicy, Fees, network);
131
131
 
132
132
  const btcRelay = new EVMBtcRelay(
133
133
  chainInterface, bitcoinRpc, network, options.btcRelayContract ?? defaultContractAddresses.btcRelayContract,
@@ -135,7 +135,7 @@ export function initializeCitrea(
135
135
  maxParallelCalls: options?.evmConfig?.maxParallelCalls ?? 5,
136
136
  useAccessLists: options?.evmConfig?.useAccessLists,
137
137
  defaultAccessListAddresses: options?.evmConfig?.defaultAccessListAddresses
138
- }, options.retryPolicy, Fees);
138
+ }, options.retryPolicy, Fees, network);
139
139
  chainInterface.Tokens = new CitreaTokens(chainInterface); //Override with custom token module allowing l1 state diff based fee calculation
140
140
 
141
141
  const btcRelay = new CitreaBtcRelay(
@@ -155,7 +155,7 @@ export function initializeGoat(
155
155
  maxParallelCalls: options?.evmConfig?.maxParallelCalls ?? 5,
156
156
  useAccessLists: options?.evmConfig?.useAccessLists,
157
157
  defaultAccessListAddresses: options?.evmConfig?.defaultAccessListAddresses
158
- }, options.retryPolicy, Fees);
158
+ }, options.retryPolicy, Fees, network);
159
159
 
160
160
  const btcRelay = new EVMBtcRelay(
161
161
  chainInterface, bitcoinRpc, network, options.btcRelayContract ?? defaultContractAddresses.btcRelayContract,
@@ -1,4 +1,4 @@
1
- import {ChainInterface, TransactionConfirmationOptions} from "@atomiqlabs/base";
1
+ import {BitcoinNetwork, ChainInterface, TransactionConfirmationOptions} from "@atomiqlabs/base";
2
2
  import {getLogger, LoggerType} from "../../utils/Utils";
3
3
  import {
4
4
  BrowserProvider,
@@ -128,13 +128,16 @@ export class EVMChainInterface<ChainId extends string = string> implements Chain
128
128
  */
129
129
  protected logger: LoggerType;
130
130
 
131
+ private readonly bitcoinNetwork?: BitcoinNetwork;
132
+
131
133
  constructor(
132
134
  chainId: ChainId,
133
135
  evmChainId: number,
134
136
  provider: JsonRpcApiProvider,
135
137
  config: EVMConfiguration,
136
138
  retryPolicy?: EVMRetryPolicy,
137
- evmFeeEstimator: EVMFees = new EVMFees(provider)
139
+ evmFeeEstimator: EVMFees = new EVMFees(provider),
140
+ bitcoinNetwork?: BitcoinNetwork
138
141
  ) {
139
142
  this.chainId = chainId;
140
143
  this.evmChainId = evmChainId;
@@ -146,6 +149,8 @@ export class EVMChainInterface<ChainId extends string = string> implements Chain
146
149
  this._config.finalityCheckStrategy ??= {type: "timer"};
147
150
  this._config.finalityCheckStrategy.delayMs ??= 1000;
148
151
 
152
+ this.bitcoinNetwork = bitcoinNetwork;
153
+
149
154
  this.logger = getLogger("EVMChainInterface("+this.evmChainId+"): ");
150
155
 
151
156
  this.Fees = evmFeeEstimator;
@@ -358,4 +363,13 @@ export class EVMChainInterface<ChainId extends string = string> implements Chain
358
363
  return new EVMSigner(signer, address);
359
364
  }
360
365
 
366
+ async verifyNetwork(bitcoinNetwork: BitcoinNetwork): Promise<void> {
367
+ if(this.bitcoinNetwork!=null && bitcoinNetwork!==this.bitcoinNetwork)
368
+ throw new Error(`Network mismatch, the chain interface was not setup for ${BitcoinNetwork[bitcoinNetwork]}, chain interface network: ${BitcoinNetwork[this.bitcoinNetwork]}`);
369
+
370
+ const network = await this.provider.getNetwork();
371
+ if(network.chainId!==BigInt(this.evmChainId))
372
+ throw new Error(`Network mismatch, the underlying RPC provider isn't using the correct chainId, expected: ${this.evmChainId}, provider returned: ${network.chainId.toString(10)}`);
373
+ }
374
+
361
375
  }
@@ -3,6 +3,7 @@ import {AbiCoder, hexlify, keccak256, ZeroHash} from "ethers";
3
3
  import {EscrowDataStruct, EscrowDataStructOutput} from "./EscrowManagerTypechain";
4
4
  import {IClaimHandler} from "./handlers/claim/ClaimHandlers";
5
5
  import {TimelockRefundHandler} from "./handlers/refund/TimelockRefundHandler";
6
+ import {replaceBigInts} from "../../utils/Utils";
6
7
 
7
8
  const FLAG_PAY_OUT: bigint = 0x01n;
8
9
  const FLAG_PAY_IN: bigint = 0x02n;
@@ -513,6 +514,13 @@ export class EVMSwapData extends SwapData {
513
514
  );
514
515
  }
515
516
 
517
+ /**
518
+ * @inheritDoc
519
+ */
520
+ getEscrowStruct(): any {
521
+ return replaceBigInts(this.toEscrowStruct());
522
+ }
523
+
516
524
  }
517
525
 
518
526
  SwapData.deserializers["evm"] = EVMSwapData;
@@ -1,4 +1,16 @@
1
1
 
2
+
3
+ export type ReplaceBigInt<T> =
4
+ T extends bigint
5
+ ? string
6
+ : T extends (infer U)[]
7
+ ? ReplaceBigInt<U>[]
8
+ : T extends readonly (infer U)[]
9
+ ? readonly ReplaceBigInt<U>[]
10
+ : T extends object
11
+ ? { [K in keyof T]: ReplaceBigInt<T[K]> }
12
+ : T;
13
+
2
14
  /**
3
15
  * Logger interface used across EVM modules.
4
16
  *
@@ -159,3 +171,23 @@ export const allowedEthersErrorNumbers: Set<number> = new Set([
159
171
  export const allowedEthersErrorMessages: Set<string> = new Set([
160
172
  "already known"
161
173
  ]);
174
+
175
+ export function replaceBigInts<T>(obj: T): ReplaceBigInt<T> {
176
+ const replace = (value: any): any => {
177
+ if(typeof(value)==="bigint") return "0x"+value.toString(16);
178
+ if(value==null || typeof(value)!=="object") return value;
179
+
180
+ if(Array.isArray(value)) {
181
+ return value.map(replace);
182
+ }
183
+
184
+ const mapped: any = {};
185
+ for(const key of Object.keys(value)) {
186
+ mapped[key] = replace(value[key]);
187
+ }
188
+ return mapped;
189
+ };
190
+
191
+ return replace(obj);
192
+ }
193
+