@atomiqlabs/chain-evm 2.1.11 → 2.1.14

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.
Files changed (151) hide show
  1. package/README.md +75 -0
  2. package/dist/chains/EVMOptions.d.ts +66 -0
  3. package/dist/chains/EVMOptions.js +2 -0
  4. package/dist/chains/alpen/AlpenInitializer.d.ts +3 -30
  5. package/dist/chains/alpen/AlpenInitializer.js +3 -3
  6. package/dist/chains/botanix/BotanixInitializer.d.ts +3 -30
  7. package/dist/chains/botanix/BotanixInitializer.js +3 -3
  8. package/dist/chains/citrea/CitreaBtcRelay.d.ts +5 -0
  9. package/dist/chains/citrea/CitreaBtcRelay.js +7 -2
  10. package/dist/chains/citrea/CitreaFees.d.ts +3 -5
  11. package/dist/chains/citrea/CitreaFees.js +3 -5
  12. package/dist/chains/citrea/CitreaInitializer.d.ts +3 -29
  13. package/dist/chains/citrea/CitreaInitializer.js +3 -3
  14. package/dist/chains/citrea/CitreaSpvVaultContract.d.ts +5 -0
  15. package/dist/chains/citrea/CitreaSpvVaultContract.js +7 -2
  16. package/dist/chains/citrea/CitreaSwapContract.d.ts +7 -2
  17. package/dist/chains/citrea/CitreaSwapContract.js +10 -5
  18. package/dist/chains/citrea/CitreaTokens.d.ts +5 -0
  19. package/dist/chains/citrea/CitreaTokens.js +5 -0
  20. package/dist/chains/goat/GoatInitializer.d.ts +3 -30
  21. package/dist/chains/goat/GoatInitializer.js +3 -3
  22. package/dist/evm/btcrelay/EVMBtcRelay.d.ts +41 -10
  23. package/dist/evm/btcrelay/EVMBtcRelay.js +50 -18
  24. package/dist/evm/btcrelay/headers/EVMBtcHeader.d.ts +53 -7
  25. package/dist/evm/btcrelay/headers/EVMBtcHeader.js +43 -5
  26. package/dist/evm/btcrelay/headers/EVMBtcStoredHeader.d.ts +53 -8
  27. package/dist/evm/btcrelay/headers/EVMBtcStoredHeader.js +41 -1
  28. package/dist/evm/chain/EVMChainInterface.d.ts +57 -2
  29. package/dist/evm/chain/EVMChainInterface.js +7 -7
  30. package/dist/evm/chain/EVMModule.d.ts +5 -0
  31. package/dist/evm/chain/EVMModule.js +6 -1
  32. package/dist/evm/chain/modules/EVMBlocks.d.ts +7 -0
  33. package/dist/evm/chain/modules/EVMBlocks.js +2 -0
  34. package/dist/evm/chain/modules/EVMEvents.js +19 -19
  35. package/dist/evm/chain/modules/EVMFees.d.ts +41 -5
  36. package/dist/evm/chain/modules/EVMFees.js +24 -5
  37. package/dist/evm/chain/modules/EVMTokens.d.ts +1 -1
  38. package/dist/evm/chain/modules/EVMTokens.js +1 -1
  39. package/dist/evm/chain/modules/EVMTransactions.d.ts +20 -2
  40. package/dist/evm/chain/modules/EVMTransactions.js +11 -8
  41. package/dist/evm/contract/EVMContractBase.d.ts +28 -10
  42. package/dist/evm/contract/EVMContractBase.js +9 -18
  43. package/dist/evm/contract/EVMContractModule.d.ts +5 -0
  44. package/dist/evm/contract/EVMContractModule.js +5 -0
  45. package/dist/evm/contract/modules/EVMContractEvents.d.ts +7 -1
  46. package/dist/evm/contract/modules/EVMContractEvents.js +23 -3
  47. package/dist/evm/events/EVMChainEvents.d.ts +8 -0
  48. package/dist/evm/events/EVMChainEvents.js +8 -0
  49. package/dist/evm/events/EVMChainEventsBrowser.d.ts +87 -19
  50. package/dist/evm/events/EVMChainEventsBrowser.js +53 -18
  51. package/dist/evm/providers/JsonRpcProviderWithRetries.d.ts +9 -0
  52. package/dist/evm/providers/JsonRpcProviderWithRetries.js +9 -0
  53. package/dist/evm/providers/ReconnectingWebSocketProvider.d.ts +5 -0
  54. package/dist/evm/providers/ReconnectingWebSocketProvider.js +5 -0
  55. package/dist/evm/providers/WebSocketProviderWithRetries.d.ts +9 -0
  56. package/dist/evm/providers/WebSocketProviderWithRetries.js +9 -0
  57. package/dist/evm/spv_swap/EVMSpvVaultContract.d.ts +46 -21
  58. package/dist/evm/spv_swap/EVMSpvVaultContract.js +62 -22
  59. package/dist/evm/spv_swap/EVMSpvVaultData.d.ts +57 -2
  60. package/dist/evm/spv_swap/EVMSpvVaultData.js +57 -2
  61. package/dist/evm/spv_swap/EVMSpvWithdrawalData.d.ts +12 -0
  62. package/dist/evm/spv_swap/EVMSpvWithdrawalData.js +12 -0
  63. package/dist/evm/swaps/EVMSwapContract.d.ts +58 -13
  64. package/dist/evm/swaps/EVMSwapContract.js +81 -54
  65. package/dist/evm/swaps/EVMSwapData.d.ts +27 -6
  66. package/dist/evm/swaps/EVMSwapData.js +26 -0
  67. package/dist/evm/swaps/EVMSwapModule.d.ts +5 -0
  68. package/dist/evm/swaps/EVMSwapModule.js +5 -0
  69. package/dist/evm/swaps/handlers/IHandler.d.ts +5 -0
  70. package/dist/evm/swaps/handlers/claim/ClaimHandlers.d.ts +15 -0
  71. package/dist/evm/swaps/handlers/claim/ClaimHandlers.js +5 -0
  72. package/dist/evm/swaps/handlers/claim/btc/BitcoinNoncedOutputClaimHandler.d.ts +5 -0
  73. package/dist/evm/swaps/handlers/claim/btc/BitcoinOutputClaimHandler.d.ts +10 -0
  74. package/dist/evm/swaps/handlers/claim/btc/BitcoinTxIdClaimHandler.d.ts +5 -0
  75. package/dist/evm/swaps/handlers/claim/btc/IBitcoinClaimHandler.d.ts +15 -0
  76. package/dist/evm/swaps/handlers/claim/btc/IBitcoinClaimHandler.js +7 -2
  77. package/dist/evm/swaps/modules/EVMLpVault.d.ts +5 -0
  78. package/dist/evm/swaps/modules/EVMLpVault.js +9 -4
  79. package/dist/evm/swaps/modules/EVMSwapClaim.d.ts +7 -2
  80. package/dist/evm/swaps/modules/EVMSwapClaim.js +11 -6
  81. package/dist/evm/swaps/modules/EVMSwapInit.d.ts +10 -0
  82. package/dist/evm/swaps/modules/EVMSwapInit.js +11 -6
  83. package/dist/evm/swaps/modules/EVMSwapRefund.d.ts +5 -0
  84. package/dist/evm/swaps/modules/EVMSwapRefund.js +9 -4
  85. package/dist/evm/wallet/EVMBrowserSigner.d.ts +22 -2
  86. package/dist/evm/wallet/EVMBrowserSigner.js +40 -2
  87. package/dist/evm/wallet/EVMPersistentSigner.d.ts +13 -2
  88. package/dist/evm/wallet/EVMPersistentSigner.js +13 -1
  89. package/dist/evm/wallet/EVMSigner.d.ts +30 -1
  90. package/dist/evm/wallet/EVMSigner.js +34 -1
  91. package/dist/index.d.ts +71 -0
  92. package/dist/index.js +70 -0
  93. package/dist/node/index.d.ts +10 -0
  94. package/dist/node/index.js +15 -0
  95. package/dist/utils/Utils.d.ts +50 -0
  96. package/dist/utils/Utils.js +45 -0
  97. package/node/index.d.ts +1 -0
  98. package/node/index.js +3 -0
  99. package/package.json +4 -3
  100. package/src/chains/EVMOptions.ts +70 -0
  101. package/src/chains/alpen/AlpenInitializer.ts +5 -27
  102. package/src/chains/botanix/BotanixChainType.ts +5 -5
  103. package/src/chains/botanix/BotanixInitializer.ts +5 -27
  104. package/src/chains/citrea/CitreaBtcRelay.ts +8 -3
  105. package/src/chains/citrea/CitreaFees.ts +3 -6
  106. package/src/chains/citrea/CitreaInitializer.ts +5 -27
  107. package/src/chains/citrea/CitreaSpvVaultContract.ts +7 -2
  108. package/src/chains/citrea/CitreaSwapContract.ts +11 -6
  109. package/src/chains/citrea/CitreaTokens.ts +6 -1
  110. package/src/chains/goat/GoatChainType.ts +5 -5
  111. package/src/chains/goat/GoatInitializer.ts +3 -25
  112. package/src/evm/btcrelay/EVMBtcRelay.ts +54 -22
  113. package/src/evm/btcrelay/headers/EVMBtcHeader.ts +60 -13
  114. package/src/evm/btcrelay/headers/EVMBtcStoredHeader.ts +55 -10
  115. package/src/evm/chain/EVMChainInterface.ts +66 -14
  116. package/src/evm/chain/EVMModule.ts +6 -1
  117. package/src/evm/chain/modules/EVMBlocks.ts +7 -0
  118. package/src/evm/chain/modules/EVMEvents.ts +19 -19
  119. package/src/evm/chain/modules/EVMFees.ts +41 -5
  120. package/src/evm/chain/modules/EVMTokens.ts +1 -1
  121. package/src/evm/chain/modules/EVMTransactions.ts +27 -8
  122. package/src/evm/contract/EVMContractBase.ts +29 -24
  123. package/src/evm/contract/EVMContractModule.ts +5 -0
  124. package/src/evm/contract/modules/EVMContractEvents.ts +27 -8
  125. package/src/evm/events/EVMChainEvents.ts +8 -0
  126. package/src/evm/events/EVMChainEventsBrowser.ts +103 -29
  127. package/src/evm/providers/JsonRpcProviderWithRetries.ts +10 -1
  128. package/src/evm/providers/ReconnectingWebSocketProvider.ts +6 -1
  129. package/src/evm/providers/WebSocketProviderWithRetries.ts +10 -1
  130. package/src/evm/spv_swap/EVMSpvVaultContract.ts +73 -31
  131. package/src/evm/spv_swap/EVMSpvVaultData.ts +57 -2
  132. package/src/evm/spv_swap/EVMSpvWithdrawalData.ts +12 -0
  133. package/src/evm/swaps/EVMSwapContract.ts +108 -63
  134. package/src/evm/swaps/EVMSwapData.ts +27 -1
  135. package/src/evm/swaps/EVMSwapModule.ts +5 -0
  136. package/src/evm/swaps/handlers/IHandler.ts +5 -0
  137. package/src/evm/swaps/handlers/claim/ClaimHandlers.ts +15 -0
  138. package/src/evm/swaps/handlers/claim/btc/BitcoinNoncedOutputClaimHandler.ts +5 -0
  139. package/src/evm/swaps/handlers/claim/btc/BitcoinOutputClaimHandler.ts +10 -0
  140. package/src/evm/swaps/handlers/claim/btc/BitcoinTxIdClaimHandler.ts +5 -0
  141. package/src/evm/swaps/handlers/claim/btc/IBitcoinClaimHandler.ts +17 -2
  142. package/src/evm/swaps/modules/EVMLpVault.ts +10 -5
  143. package/src/evm/swaps/modules/EVMSwapClaim.ts +12 -7
  144. package/src/evm/swaps/modules/EVMSwapInit.ts +17 -7
  145. package/src/evm/swaps/modules/EVMSwapRefund.ts +9 -4
  146. package/src/evm/wallet/EVMBrowserSigner.ts +44 -5
  147. package/src/evm/wallet/EVMPersistentSigner.ts +14 -2
  148. package/src/evm/wallet/EVMSigner.ts +37 -1
  149. package/src/index.ts +72 -0
  150. package/src/node/index.ts +10 -0
  151. package/src/utils/Utils.ts +50 -1
@@ -5,6 +5,11 @@ import {CitreaFees} from "./CitreaFees";
5
5
 
6
6
  const logger = getLogger("CitreaBtcRelay: ");
7
7
 
8
+ /**
9
+ * Citrea BTC relay wrapper with fee estimation that includes Citrea state-diff costs.
10
+ *
11
+ * @category Networks/Citrea
12
+ */
8
13
  export class CitreaBtcRelay<B extends BtcBlock> extends EVMBtcRelay<B> {
9
14
 
10
15
  public static StateDiffSize = {
@@ -32,7 +37,7 @@ export class CitreaBtcRelay<B extends BtcBlock> extends EVMBtcRelay<B> {
32
37
 
33
38
  const synchronizationFee = (BigInt(blockheightDelta) * await this.getFeePerBlock(feeRate))
34
39
  + CitreaFees.getGasFee(
35
- EVMBtcRelay.GasCosts.GAS_BASE_MAIN * numTxs,
40
+ EVMBtcRelay._GasCosts.GAS_BASE_MAIN * numTxs,
36
41
  feeRate,
37
42
  CitreaBtcRelay.StateDiffSize.STATE_DIFF_BASE * numTxs
38
43
  );
@@ -50,10 +55,10 @@ export class CitreaBtcRelay<B extends BtcBlock> extends EVMBtcRelay<B> {
50
55
  public async getFeePerBlock(feeRate?: string): Promise<bigint> {
51
56
  feeRate ??= await this.Chain.Fees.getFeeRate();
52
57
  return CitreaFees.getGasFee(
53
- EVMBtcRelay.GasCosts.GAS_PER_BLOCKHEADER,
58
+ EVMBtcRelay._GasCosts.GAS_PER_BLOCKHEADER,
54
59
  feeRate,
55
60
  CitreaBtcRelay.StateDiffSize.STATE_DIFF_PER_BLOCKHEADER
56
61
  );
57
62
  }
58
63
 
59
- }
64
+ }
@@ -6,10 +6,9 @@ import {getLogger} from "../../utils/Utils";
6
6
  */
7
7
  export class CitreaFees extends EVMFees {
8
8
 
9
- public static readonly StateDiffSize = {
10
- APPROVE_DIFF_SIZE: 40,
11
- };
12
-
9
+ /**
10
+ * @internal
11
+ */
13
12
  protected readonly logger = getLogger("CitreaFees: ");
14
13
 
15
14
  private _blockFeeCache?: {
@@ -35,8 +34,6 @@ export class CitreaFees extends EVMFees {
35
34
 
36
35
  /**
37
36
  * Gets the gas price with caching, format: <gas price in Wei>;<transaction version: v1/v3>
38
- *
39
- * @private
40
37
  */
41
38
  public async getFeeRate(): Promise<string> {
42
39
  if(this._blockFeeCache==null || Date.now() - this._blockFeeCache.timestamp > this.MAX_FEE_AGE) {
@@ -1,6 +1,6 @@
1
1
  import {BaseTokenType, BitcoinNetwork, BitcoinRpc, ChainData, ChainInitializer, ChainSwapType} from "@atomiqlabs/base";
2
- import {JsonRpcApiProvider, JsonRpcProvider, WebSocketProvider} from "ethers";
3
- import {EVMChainInterface, EVMConfiguration, EVMRetryPolicy} from "../../evm/chain/EVMChainInterface";
2
+ import {JsonRpcProvider, WebSocketProvider} from "ethers";
3
+ import {EVMChainInterface} from "../../evm/chain/EVMChainInterface";
4
4
  import {CitreaChainType} from "./CitreaChainType";
5
5
  import {EVMChainEventsBrowser} from "../../evm/events/EVMChainEventsBrowser";
6
6
  import {EVMSwapData} from "../../evm/swaps/EVMSwapData";
@@ -11,6 +11,7 @@ import {CitreaBtcRelay} from "./CitreaBtcRelay";
11
11
  import {CitreaSwapContract} from "./CitreaSwapContract";
12
12
  import {CitreaTokens} from "./CitreaTokens";
13
13
  import {CitreaSpvVaultContract} from "./CitreaSpvVaultContract";
14
+ import {EVMOptions} from "../EVMOptions";
14
15
 
15
16
  const CitreaChainIds = {
16
17
  MAINNET: 4114,
@@ -75,7 +76,7 @@ export type CitreaAssetsType = BaseTokenType<"CBTC" | "WBTC" | "USDC">;
75
76
  * Default Citrea token assets configuration
76
77
  * @category Networks/Citrea
77
78
  */
78
- export const CitreaAssets: CitreaAssetsType = {
79
+ const CitreaAssets: CitreaAssetsType = {
79
80
  CBTC: {
80
81
  address: "0x0000000000000000000000000000000000000000",
81
82
  decimals: 18,
@@ -97,30 +98,7 @@ export const CitreaAssets: CitreaAssetsType = {
97
98
  * Configuration options for initializing Citrea chain
98
99
  * @category Networks/Citrea
99
100
  */
100
- export type CitreaOptions = {
101
- rpcUrl: string | JsonRpcApiProvider,
102
- retryPolicy?: EVMRetryPolicy,
103
- chainType?: "MAINNET" | "TESTNET4",
104
-
105
- swapContract?: string,
106
- swapContractDeploymentHeight?: number,
107
- btcRelayContract?: string,
108
- btcRelayDeploymentHeight?: number,
109
- spvVaultContract?: string,
110
- spvVaultDeploymentHeight?: number,
111
- handlerContracts?: {
112
- refund?: {
113
- timelock?: string
114
- },
115
- claim?: {
116
- [type in ChainSwapType]?: string
117
- }
118
- }
119
-
120
- fees?: CitreaFees,
121
-
122
- evmConfig?: Partial<Omit<EVMConfiguration, "safeBlockTag" | "finalizedBlockTag" | "finalityCheckStrategy">>
123
- }
101
+ export type CitreaOptions = EVMOptions<"MAINNET" | "TESTNET4", CitreaFees>;
124
102
 
125
103
  /**
126
104
  * Initialize Citrea chain integration
@@ -6,6 +6,11 @@ import {CitreaFees} from "./CitreaFees";
6
6
  import {EVMAddresses} from "../../evm/chain/modules/EVMAddresses";
7
7
 
8
8
 
9
+ /**
10
+ * Citrea SPV vault wrapper with fee estimation adjusted by expected state-diff size.
11
+ *
12
+ * @category Networks/Citrea
13
+ */
9
14
  export class CitreaSpvVaultContract extends EVMSpvVaultContract<"CITREA"> {
10
15
 
11
16
  public static readonly StateDiffSize = {
@@ -30,7 +35,7 @@ export class CitreaSpvVaultContract extends EVMSpvVaultContract<"CITREA"> {
30
35
  }
31
36
 
32
37
  async getClaimFee(signer: string, vault?: EVMSpvVaultData, data?: EVMSpvWithdrawalData, feeRate?: string): Promise<bigint> {
33
- vault ??= EVMSpvVaultData.randomVault();
38
+ vault ??= EVMSpvVaultData._randomVault();
34
39
  feeRate ??= await this.Chain.Fees.getFeeRate();
35
40
  const tokenStateChanges: Set<string> = new Set();
36
41
 
@@ -56,7 +61,7 @@ export class CitreaSpvVaultContract extends EVMSpvVaultContract<"CITREA"> {
56
61
  }
57
62
 
58
63
  async getFrontFee(signer: string, vault?: EVMSpvVaultData, data?: EVMSpvWithdrawalData, feeRate?: string): Promise<bigint> {
59
- vault ??= EVMSpvVaultData.randomVault();
64
+ vault ??= EVMSpvVaultData._randomVault();
60
65
  feeRate ??= await this.Chain.Fees.getFeeRate();
61
66
  const tokenStateChanges: Set<string> = new Set();
62
67
 
@@ -2,6 +2,11 @@ import {EVMSwapContract} from "../../evm/swaps/EVMSwapContract";
2
2
  import {EVMSwapData} from "../../evm/swaps/EVMSwapData";
3
3
  import {CitreaFees} from "./CitreaFees";
4
4
 
5
+ /**
6
+ * Citrea swap contract wrapper with fee estimation adjusted by expected state-diff size.
7
+ *
8
+ * @category Networks/Citrea
9
+ */
5
10
  export class CitreaSwapContract extends EVMSwapContract<"CITREA"> {
6
11
 
7
12
  public static readonly StateDiffSize = {
@@ -27,7 +32,7 @@ export class CitreaSwapContract extends EVMSwapContract<"CITREA"> {
27
32
  }
28
33
 
29
34
  /**
30
- * Get the estimated solana fee of the commit transaction
35
+ * Returns estimated fee of the commit transaction, including Citrea state-diff overhead.
31
36
  */
32
37
  async getCommitFee(signer: string, swapData: EVMSwapData, feeRate?: string): Promise<bigint> {
33
38
  feeRate ??= await this.Chain.Fees.getFeeRate();
@@ -45,7 +50,7 @@ export class CitreaSwapContract extends EVMSwapContract<"CITREA"> {
45
50
  }
46
51
  diffSize += this.calculateStateDiff(signer, tokenStateChanges);
47
52
 
48
- const gasFee = await this.Init.getInitFee(swapData, feeRate);
53
+ const gasFee = await this._Init.getInitFee(swapData, feeRate);
49
54
  return gasFee + CitreaFees.getGasFee(0, feeRate, diffSize);
50
55
  }
51
56
 
@@ -69,12 +74,12 @@ export class CitreaSwapContract extends EVMSwapContract<"CITREA"> {
69
74
  }
70
75
  diffSize += this.calculateStateDiff(signer, tokenStateChanges);
71
76
 
72
- const gasFee = await this.Claim.getClaimFee(swapData, feeRate);
77
+ const gasFee = await this._Claim.getClaimFee(swapData, feeRate);
73
78
  return gasFee + CitreaFees.getGasFee(0, feeRate, diffSize);
74
79
  }
75
80
 
76
81
  /**
77
- * Get the estimated solana transaction fee of the refund transaction
82
+ * Returns estimated fee of the refund transaction, including Citrea state-diff overhead.
78
83
  */
79
84
  async getRefundFee(signer: string, swapData: EVMSwapData, feeRate?: string): Promise<bigint> {
80
85
  feeRate ??= await this.Chain.Fees.getFeeRate();
@@ -96,8 +101,8 @@ export class CitreaSwapContract extends EVMSwapContract<"CITREA"> {
96
101
  }
97
102
  diffSize += this.calculateStateDiff(signer, tokenStateChanges);
98
103
 
99
- const gasFee = await this.Refund.getRefundFee(swapData, feeRate);
104
+ const gasFee = await this._Refund.getRefundFee(swapData, feeRate);
100
105
  return gasFee + CitreaFees.getGasFee(0, feeRate, diffSize);
101
106
  }
102
107
 
103
- }
108
+ }
@@ -2,6 +2,11 @@ import {EVMTokens} from "../../evm/chain/modules/EVMTokens";
2
2
  import {CitreaFees} from "./CitreaFees";
3
3
 
4
4
 
5
+ /**
6
+ * Citrea-specific token module that augments fee estimation with state-diff costs.
7
+ *
8
+ * @category Networks/Citrea
9
+ */
5
10
  export class CitreaTokens extends EVMTokens {
6
11
 
7
12
  public static readonly StateDiffSize = {
@@ -19,4 +24,4 @@ export class CitreaTokens extends EVMTokens {
19
24
  return CitreaFees.getGasFee(EVMTokens.GasCosts.APPROVE, feeRate, CitreaTokens.StateDiffSize.TRANSFER_DIFF_SIZE);
20
25
  }
21
26
 
22
- }
27
+ }
@@ -12,11 +12,11 @@ import {EVMBtcRelay} from "../../evm/btcrelay/EVMBtcRelay";
12
12
  import {EVMSpvVaultContract} from "../../evm/spv_swap/EVMSpvVaultContract";
13
13
  import {Signer} from "ethers";
14
14
 
15
- /**
16
- * Type definition for the GOAT Network chain implementation
17
- * @category Networks/GOAT
18
- */
19
- export type GoatChainType = ChainType<
15
+ /**
16
+ * Type definition for the GOAT Network chain implementation
17
+ * @category Networks/GOAT
18
+ */
19
+ export type GoatChainType = ChainType<
20
20
  "GOAT",
21
21
  never,
22
22
  EVMPreFetchVerification,
@@ -10,6 +10,7 @@ import {EVMSwapData} from "../../evm/swaps/EVMSwapData";
10
10
  import {EVMSpvVaultData} from "../../evm/spv_swap/EVMSpvVaultData";
11
11
  import {EVMSpvWithdrawalData} from "../../evm/spv_swap/EVMSpvWithdrawalData";
12
12
  import {GoatChainType} from "./GoatChainType";
13
+ import {EVMOptions} from "../EVMOptions";
13
14
 
14
15
  const GoatChainIds = {
15
16
  MAINNET: 2345,
@@ -96,7 +97,7 @@ export type GoatAssetsType = BaseTokenType<"BTC" | "PBTC" | "_PBTC_DEV">;
96
97
  * Default GOAT Network token assets configuration
97
98
  * @category Networks/GOAT
98
99
  */
99
- export const GoatAssets: GoatAssetsType = {
100
+ const GoatAssets: GoatAssetsType = {
100
101
  BTC: {
101
102
  address: "0x0000000000000000000000000000000000000000",
102
103
  decimals: 18,
@@ -118,30 +119,7 @@ export const GoatAssets: GoatAssetsType = {
118
119
  * Configuration options for initializing GOAT Network chain
119
120
  * @category Networks/GOAT
120
121
  */
121
- export type GoatOptions = {
122
- rpcUrl: string | JsonRpcApiProvider,
123
- retryPolicy?: EVMRetryPolicy,
124
- chainType?: "MAINNET" | "TESTNET" | "TESTNET4",
125
-
126
- swapContract?: string,
127
- swapContractDeploymentHeight?: number,
128
- btcRelayContract?: string,
129
- btcRelayDeploymentHeight?: number,
130
- spvVaultContract?: string,
131
- spvVaultDeploymentHeight?: number,
132
- handlerContracts?: {
133
- refund?: {
134
- timelock?: string
135
- },
136
- claim?: {
137
- [type in ChainSwapType]?: string
138
- }
139
- }
140
-
141
- fees?: EVMFees,
142
-
143
- evmConfig?: Partial<Omit<EVMConfiguration, "safeBlockTag" | "finalizedBlockTag" | "finalityCheckStrategy">>
144
- }
122
+ export type GoatOptions = EVMOptions<"MAINNET" | "TESTNET" | "TESTNET4">;
145
123
 
146
124
  /**
147
125
  * Initialize GOAT Network chain integration
@@ -27,13 +27,18 @@ function serializeBlockHeader(e: BtcBlock): EVMBtcHeader {
27
27
  const logger = getLogger("EVMBtcRelay: ");
28
28
 
29
29
  /**
30
+ * EVM BTC Relay bitcoin light client contract representation.
31
+ *
30
32
  * @category BTC Relay
31
33
  */
32
34
  export class EVMBtcRelay<B extends BtcBlock>
33
35
  extends EVMContractBase<BtcRelayTypechain>
34
36
  implements BtcRelay<EVMBtcStoredHeader, EVMTx, B, EVMSigner> {
35
37
 
36
- public static GasCosts = {
38
+ /**
39
+ * @internal
40
+ */
41
+ static _GasCosts = {
37
42
  GAS_PER_BLOCKHEADER: 30_000,
38
43
  GAS_BASE_MAIN: 15_000 + 21_000,
39
44
  GAS_PER_BLOCKHEADER_FORK: 65_000,
@@ -41,37 +46,64 @@ export class EVMBtcRelay<B extends BtcBlock>
41
46
  GAS_BASE_FORK: 25_000 + 21_000
42
47
  }
43
48
 
44
- public async SaveMainHeaders(signer: string, mainHeaders: EVMBtcHeader[], storedHeader: EVMBtcStoredHeader, feeRate: string): Promise<EVMTx> {
49
+ /**
50
+ * Returns a transaction that submits new main-chain bitcoin blockheaders to the light client.
51
+ *
52
+ * @param signer EVM signer address
53
+ * @param mainHeaders New bitcoin blockheaders to submit
54
+ * @param storedHeader Current latest committed and stored bitcoin blockheader in the light client
55
+ * @param feeRate Fee rate to apply to the transaction
56
+ */
57
+ private async SaveMainHeaders(signer: string, mainHeaders: EVMBtcHeader[], storedHeader: EVMBtcStoredHeader, feeRate: string): Promise<EVMTx> {
45
58
  const tx = await this.contract.submitMainBlockheaders.populateTransaction(Buffer.concat([
46
59
  storedHeader.serialize(),
47
60
  Buffer.concat(mainHeaders.map(header => header.serializeCompact()))
48
61
  ]));
49
62
  tx.from = signer;
50
- EVMFees.applyFeeRate(tx, EVMBtcRelay.GasCosts.GAS_BASE_MAIN + (EVMBtcRelay.GasCosts.GAS_PER_BLOCKHEADER * mainHeaders.length), feeRate);
63
+ EVMFees.applyFeeRate(tx, EVMBtcRelay._GasCosts.GAS_BASE_MAIN + (EVMBtcRelay._GasCosts.GAS_PER_BLOCKHEADER * mainHeaders.length), feeRate);
51
64
  return tx;
52
65
  }
53
66
 
54
- public async SaveShortForkHeaders(signer: string, forkHeaders: EVMBtcHeader[], storedHeader: EVMBtcStoredHeader, feeRate: string): Promise<EVMTx> {
67
+ /**
68
+ * Returns a transaction that submits a short competing branch.
69
+ * If the submitted chain has higher total chainwork than the current canonical chain, it becomes canonical.
70
+ *
71
+ * @param signer EVM signer address
72
+ * @param forkHeaders Fork bitcoin blockheaders to submit
73
+ * @param storedHeader Committed and stored bitcoin blockheader from which to fork the light client
74
+ * @param feeRate Fee rate to apply to the transaction
75
+ */
76
+ private async SaveShortForkHeaders(signer: string, forkHeaders: EVMBtcHeader[], storedHeader: EVMBtcStoredHeader, feeRate: string): Promise<EVMTx> {
55
77
  const tx = await this.contract.submitShortForkBlockheaders.populateTransaction(Buffer.concat([
56
78
  storedHeader.serialize(),
57
79
  Buffer.concat(forkHeaders.map(header => header.serializeCompact()))
58
80
  ]));
59
81
  tx.from = signer;
60
- EVMFees.applyFeeRate(tx, EVMBtcRelay.GasCosts.GAS_BASE_MAIN + (EVMBtcRelay.GasCosts.GAS_PER_BLOCKHEADER * forkHeaders.length), feeRate);
82
+ EVMFees.applyFeeRate(tx, EVMBtcRelay._GasCosts.GAS_BASE_MAIN + (EVMBtcRelay._GasCosts.GAS_PER_BLOCKHEADER * forkHeaders.length), feeRate);
61
83
  return tx;
62
84
  }
63
85
 
64
- public async SaveLongForkHeaders(signer: string, forkId: number, forkHeaders: EVMBtcHeader[], storedHeader: EVMBtcStoredHeader, feeRate: string, totalForkHeaders: number = 100): Promise<EVMTx> {
86
+ /**
87
+ * Returns a transaction that submits blockheaders to an existing long fork.
88
+ *
89
+ * @param signer EVM signer address
90
+ * @param forkId Fork ID to submit the fork blockheaders to
91
+ * @param forkHeaders Fork bitcoin blockheaders to submit
92
+ * @param storedHeader Either a committed and stored blockheader from which to fork, or the current fork tip
93
+ * @param feeRate Fee rate to apply to the transaction
94
+ * @param totalForkHeaders Total blockheaders in the fork, used for gas estimation when reorg happens
95
+ */
96
+ private async SaveLongForkHeaders(signer: string, forkId: number, forkHeaders: EVMBtcHeader[], storedHeader: EVMBtcStoredHeader, feeRate: string, totalForkHeaders: number = 100): Promise<EVMTx> {
65
97
  const tx = await this.contract.submitForkBlockheaders.populateTransaction(forkId, Buffer.concat([
66
98
  storedHeader.serialize(),
67
99
  Buffer.concat(forkHeaders.map(header => header.serializeCompact()))
68
100
  ]));
69
101
  tx.from = signer;
70
- EVMFees.applyFeeRate(tx, EVMBtcRelay.GasCosts.GAS_BASE_FORK + (EVMBtcRelay.GasCosts.GAS_PER_BLOCKHEADER_FORK * forkHeaders.length) + (EVMBtcRelay.GasCosts.GAS_PER_BLOCKHEADER_FORKED * totalForkHeaders), feeRate);
102
+ EVMFees.applyFeeRate(tx, EVMBtcRelay._GasCosts.GAS_BASE_FORK + (EVMBtcRelay._GasCosts.GAS_PER_BLOCKHEADER_FORK * forkHeaders.length) + (EVMBtcRelay._GasCosts.GAS_PER_BLOCKHEADER_FORKED * totalForkHeaders), feeRate);
71
103
  return tx;
72
104
  }
73
105
 
74
- bitcoinRpc: BitcoinRpc<B>;
106
+ readonly _bitcoinRpc: BitcoinRpc<B>;
75
107
 
76
108
  readonly maxHeadersPerTx: number = 100;
77
109
  readonly maxForkHeadersPerTx: number = 50;
@@ -85,12 +117,12 @@ export class EVMBtcRelay<B extends BtcBlock>
85
117
  contractDeploymentHeight?: number
86
118
  ) {
87
119
  super(chainInterface, contractAddress, BtcRelayAbi, contractDeploymentHeight);
88
- this.bitcoinRpc = bitcoinRpc;
120
+ this._bitcoinRpc = bitcoinRpc;
89
121
  }
90
122
 
91
123
  /**
92
- * Computes subsequent commited headers as they will appear on the blockchain when transactions
93
- * are submitted & confirmed
124
+ * Computes subsequent committed headers as they will appear on-chain once transactions
125
+ * are submitted and confirmed.
94
126
  *
95
127
  * @param initialStoredHeader
96
128
  * @param syncedHeaders
@@ -198,7 +230,7 @@ export class EVMBtcRelay<B extends BtcBlock>
198
230
  private getBlock(commitHash?: string, blockHash?: Buffer): Promise<[EVMBtcStoredHeader, string] | null> {
199
231
  const blockHashString = blockHash==null ? null : "0x"+Buffer.from([...blockHash]).reverse().toString("hex");
200
232
 
201
- const generator = () => this.Events.findInContractEvents<[EVMBtcStoredHeader, string] | null, "StoreHeader" | "StoreForkHeader">(
233
+ const generator = () => this._Events.findInContractEvents<[EVMBtcStoredHeader, string] | null, "StoreHeader" | "StoreForkHeader">(
202
234
  ["StoreHeader", "StoreForkHeader"],
203
235
  [
204
236
  commitHash ?? null,
@@ -263,7 +295,7 @@ export class EVMBtcRelay<B extends BtcBlock>
263
295
  const [storedBlockHeader, commitHash] = result;
264
296
 
265
297
  //Check if block is part of the main chain
266
- const chainCommitment = await this.contract.getCommitHash(storedBlockHeader.blockHeight);
298
+ const chainCommitment = await this.contract.getCommitHash(storedBlockHeader.getBlockheight());
267
299
  if(chainCommitment!==commitHash) return null;
268
300
 
269
301
  logger.debug("retrieveLogAndBlockheight(): block found," +
@@ -282,11 +314,11 @@ export class EVMBtcRelay<B extends BtcBlock>
282
314
  const [storedBlockHeader, commitHash] = result;
283
315
 
284
316
  //Check if block is part of the main chain
285
- const chainCommitment = await this.contract.getCommitHash(storedBlockHeader.blockHeight);
317
+ const chainCommitment = await this.contract.getCommitHash(storedBlockHeader.getBlockheight());
286
318
  if(chainCommitment!==commitHash) return null;
287
319
 
288
320
  logger.debug("retrieveLogByCommitHash(): block found," +
289
- " commit hash: "+commitmentHashStr+" blockhash: "+blockData.blockhash+" height: "+storedBlockHeader.blockHeight);
321
+ " commit hash: "+commitmentHashStr+" blockhash: "+blockData.blockhash+" height: "+storedBlockHeader.getBlockheight());
290
322
 
291
323
  return storedBlockHeader;
292
324
  }
@@ -298,17 +330,17 @@ export class EVMBtcRelay<B extends BtcBlock>
298
330
  resultStoredHeader: EVMBtcStoredHeader,
299
331
  resultBitcoinHeader: B
300
332
  } | null> {
301
- const data = await this.Events.findInContractEvents(
333
+ const data = await this._Events.findInContractEvents(
302
334
  ["StoreHeader", "StoreForkHeader"],
303
335
  null,
304
336
  async (event) => {
305
337
  const blockHashHex = Buffer.from(event.args.blockHash.substring(2), "hex").reverse().toString("hex");
306
338
  const commitHash = event.args.commitHash;
307
339
 
308
- const isInBtcMainChain = await this.bitcoinRpc.isInMainChain(blockHashHex).catch(() => false);
340
+ const isInBtcMainChain = await this._bitcoinRpc.isInMainChain(blockHashHex).catch(() => false);
309
341
  if(!isInBtcMainChain) return null;
310
342
 
311
- const blockHeader = await this.bitcoinRpc.getBlockHeader(blockHashHex);
343
+ const blockHeader = await this._bitcoinRpc.getBlockHeader(blockHashHex);
312
344
  if(blockHeader==null) return null;
313
345
 
314
346
  if(commitHash !== await this.contract.getCommitHash(blockHeader.getHeight())) return null;
@@ -408,7 +440,7 @@ export class EVMBtcRelay<B extends BtcBlock>
408
440
  if(blockheightDelta<=0) return 0n;
409
441
 
410
442
  const synchronizationFee = (BigInt(blockheightDelta) * await this.getFeePerBlock(feeRate))
411
- + EVMFees.getGasFee(EVMBtcRelay.GasCosts.GAS_BASE_MAIN * Math.ceil(blockheightDelta / this.maxHeadersPerTx), feeRate);
443
+ + EVMFees.getGasFee(EVMBtcRelay._GasCosts.GAS_BASE_MAIN * Math.ceil(blockheightDelta / this.maxHeadersPerTx), feeRate);
412
444
  logger.debug("estimateSynchronizeFee(): required blockheight: "+requiredBlockheight+
413
445
  " blockheight delta: "+blockheightDelta+" fee: "+synchronizationFee.toString(10));
414
446
 
@@ -420,7 +452,7 @@ export class EVMBtcRelay<B extends BtcBlock>
420
452
  */
421
453
  public async getFeePerBlock(feeRate?: string): Promise<bigint> {
422
454
  feeRate ??= await this.Chain.Fees.getFeeRate();
423
- return EVMFees.getGasFee(EVMBtcRelay.GasCosts.GAS_PER_BLOCKHEADER, feeRate);
455
+ return EVMFees.getGasFee(EVMBtcRelay._GasCosts.GAS_PER_BLOCKHEADER, feeRate);
424
456
  }
425
457
 
426
458
  /**
@@ -453,8 +485,8 @@ export class EVMBtcRelay<B extends BtcBlock>
453
485
  * @param signer
454
486
  * @param btcRelay
455
487
  * @param btcTxs
456
- * @param txs solana transaction array, in case we need to synchronize the btc relay ourselves the synchronization
457
- * txns are added here
488
+ * @param txs EVM transaction array. If BTC relay synchronization is needed, synchronization
489
+ * transactions are appended here.
458
490
  * @param synchronizer optional synchronizer to use to synchronize the btc relay in case it is not yet synchronized
459
491
  * to the required blockheight
460
492
  * @param feeRate Fee rate to use for synchronization transactions
@@ -2,6 +2,11 @@ import {BtcHeader} from "@atomiqlabs/base";
2
2
  import {Buffer} from "buffer";
3
3
  import {sha256} from "@noble/hashes/sha2";
4
4
 
5
+ /**
6
+ * Constructor payload for EVM bitcoin blockheader representation.
7
+ *
8
+ * @category BTC Relay
9
+ */
5
10
  export type EVMBtcHeaderType = {
6
11
  version: number;
7
12
  previousBlockhash?: Buffer;
@@ -13,21 +18,30 @@ export type EVMBtcHeaderType = {
13
18
  };
14
19
 
15
20
  /**
21
+ * Representation of a bitcoin blockheader submitted to EVM BTC relay contracts.
22
+ *
16
23
  * @category BTC Relay
17
24
  */
18
25
  export class EVMBtcHeader implements BtcHeader {
19
26
 
20
- version: number;
21
- previousBlockhash?: Buffer;
22
- merkleRoot: Buffer;
23
- timestamp: number;
24
- nbits: number;
25
- nonce: number;
26
- hash?: Buffer;
27
+ private readonly version: number;
28
+ private readonly merkleRoot: Buffer;
29
+ private readonly timestamp: number;
30
+ private readonly nbits: number;
31
+ private readonly nonce: number;
32
+ private readonly hash?: Buffer;
33
+
34
+ /**
35
+ * @internal
36
+ */
37
+ _previousBlockhash?: Buffer;
27
38
 
39
+ /**
40
+ * @internal
41
+ */
28
42
  constructor(data: EVMBtcHeaderType) {
29
43
  this.version = data.version;
30
- this.previousBlockhash = data.previousBlockhash;
44
+ this._previousBlockhash = data.previousBlockhash;
31
45
  this.merkleRoot = data.merkleRoot;
32
46
  this.timestamp = data.timestamp;
33
47
  this.nbits = data.nbits;
@@ -35,35 +49,60 @@ export class EVMBtcHeader implements BtcHeader {
35
49
  this.hash = data.hash;
36
50
  }
37
51
 
52
+ /**
53
+ * @inheritDoc
54
+ */
38
55
  getMerkleRoot(): Buffer {
39
56
  return this.merkleRoot;
40
57
  }
41
58
 
59
+ /**
60
+ * @inheritDoc
61
+ */
42
62
  getNbits(): number {
43
63
  return this.nbits;
44
64
  }
45
65
 
66
+ /**
67
+ * @inheritDoc
68
+ */
46
69
  getNonce(): number {
47
70
  return this.nonce;
48
71
  }
49
72
 
73
+ /**
74
+ * @inheritDoc
75
+ */
50
76
  getReversedPrevBlockhash(): Buffer {
51
- if(this.previousBlockhash==null) throw new Error("Previous blockhash is not known from compact blockheader!");
52
- return this.previousBlockhash;
77
+ if(this._previousBlockhash==null) throw new Error("Previous blockhash is not known from compact blockheader!");
78
+ return this._previousBlockhash;
53
79
  }
54
80
 
81
+ /**
82
+ * @inheritDoc
83
+ */
55
84
  getTimestamp(): number {
56
85
  return this.timestamp;
57
86
  }
58
87
 
88
+ /**
89
+ * @inheritDoc
90
+ */
59
91
  getVersion(): number {
60
92
  return this.version;
61
93
  }
62
94
 
95
+ /**
96
+ * @inheritDoc
97
+ */
63
98
  getHash(): Buffer {
64
99
  return Buffer.from(sha256(sha256(this.serialize())));
65
100
  }
66
101
 
102
+ /**
103
+ * Serializes the bitcoin blockheader into compact 48-byte representation
104
+ * (without previous blockhash).
105
+ */
67
106
  serializeCompact(): Buffer {
68
107
  const buffer = Buffer.alloc(48);
69
108
  buffer.writeUInt32LE(this.version, 0);
@@ -74,11 +113,14 @@ export class EVMBtcHeader implements BtcHeader {
74
113
  return buffer;
75
114
  }
76
115
 
116
+ /**
117
+ * Serializes the bitcoin blockheader into full 80-byte representation.
118
+ */
77
119
  serialize(): Buffer {
78
- if(this.previousBlockhash==null) throw new Error("Cannot serialize compact blockheader without previous blockhash!");
120
+ if(this._previousBlockhash==null) throw new Error("Cannot serialize compact blockheader without previous blockhash!");
79
121
  const buffer = Buffer.alloc(80);
80
122
  buffer.writeUInt32LE(this.version, 0);
81
- this.previousBlockhash.copy(buffer, 4);
123
+ this._previousBlockhash.copy(buffer, 4);
82
124
  this.merkleRoot.copy(buffer, 36);
83
125
  buffer.writeUInt32LE(this.timestamp, 68);
84
126
  buffer.writeUInt32LE(this.nbits, 72);
@@ -86,6 +128,11 @@ export class EVMBtcHeader implements BtcHeader {
86
128
  return buffer;
87
129
  }
88
130
 
131
+ /**
132
+ * Deserializes a bitcoin blockheader from 80-byte full or 48-byte compact representation.
133
+ *
134
+ * @param rawData Serialized blockheader bytes
135
+ */
89
136
  static deserialize(rawData: Buffer): EVMBtcHeader {
90
137
  if(rawData.length===80) {
91
138
  //Regular blockheader
@@ -112,4 +159,4 @@ export class EVMBtcHeader implements BtcHeader {
112
159
  }
113
160
  }
114
161
 
115
- }
162
+ }