diff --git a/typescript/api-reference/README.md b/typescript/api-reference/README.md index 7101b6d59..724fdbf21 100644 --- a/typescript/api-reference/README.md +++ b/typescript/api-reference/README.md @@ -5,6 +5,7 @@ ### Namespaces - [BitcoinNetwork](modules/BitcoinNetwork.md) +- [Chains](modules/Chains.md) - [GetChainEvents](modules/GetChainEvents.md) - [WalletState](modules/WalletState.md) @@ -15,7 +16,10 @@ ### Classes +- [BaseL2BitcoinDepositor](classes/BaseL2BitcoinDepositor.md) +- [BaseL2TBTCToken](classes/BaseL2TBTCToken.md) - [BitcoinTxHash](classes/BitcoinTxHash.md) +- [CrossChainDepositor](classes/CrossChainDepositor.md) - [Deposit](classes/Deposit.md) - [DepositFunding](classes/DepositFunding.md) - [DepositRefund](classes/DepositRefund.md) @@ -24,7 +28,9 @@ - [ElectrumClient](classes/ElectrumClient.md) - [EthereumAddress](classes/EthereumAddress.md) - [EthereumBridge](classes/EthereumBridge.md) +- [EthereumCrossChainExtraDataEncoder](classes/EthereumCrossChainExtraDataEncoder.md) - [EthereumDepositorProxy](classes/EthereumDepositorProxy.md) +- [EthereumL1BitcoinDepositor](classes/EthereumL1BitcoinDepositor.md) - [EthereumTBTCToken](classes/EthereumTBTCToken.md) - [EthereumTBTCVault](classes/EthereumTBTCVault.md) - [EthereumWalletRegistry](classes/EthereumWalletRegistry.md) @@ -51,11 +57,16 @@ - [Bridge](interfaces/Bridge.md) - [ChainEvent](interfaces/ChainEvent.md) - [ChainIdentifier](interfaces/ChainIdentifier.md) +- [CrossChainContractsLoader](interfaces/CrossChainContractsLoader.md) +- [CrossChainExtraDataEncoder](interfaces/CrossChainExtraDataEncoder.md) - [DepositReceipt](interfaces/DepositReceipt.md) - [DepositRequest](interfaces/DepositRequest.md) - [DepositorProxy](interfaces/DepositorProxy.md) - [ElectrumCredentials](interfaces/ElectrumCredentials.md) - [EthereumContractConfig](interfaces/EthereumContractConfig.md) +- [L1BitcoinDepositor](interfaces/L1BitcoinDepositor.md) +- [L2BitcoinDepositor](interfaces/L2BitcoinDepositor.md) +- [L2TBTCToken](interfaces/L2TBTCToken.md) - [RedemptionRequest](interfaces/RedemptionRequest.md) - [TBTCToken](interfaces/TBTCToken.md) - [TBTCVault](interfaces/TBTCVault.md) @@ -66,15 +77,20 @@ - [BitcoinTxInput](README.md#bitcointxinput) - [BitcoinUtxo](README.md#bitcoinutxo) +- [ChainMapping](README.md#chainmapping) +- [CrossChainContracts](README.md#crosschaincontracts) +- [CrossChainDepositorMode](README.md#crosschaindepositormode) - [DepositRevealedEvent](README.md#depositrevealedevent) - [DkgResultApprovedEvent](README.md#dkgresultapprovedevent) - [DkgResultChallengedEvent](README.md#dkgresultchallengedevent) - [DkgResultSubmittedEvent](README.md#dkgresultsubmittedevent) - [ElectrumClientOptions](README.md#electrumclientoptions) - [ErrorMatcherFn](README.md#errormatcherfn) -- [EthereumNetwork](README.md#ethereumnetwork) - [EthereumSigner](README.md#ethereumsigner) - [ExecutionLoggerFn](README.md#executionloggerfn) +- [L1CrossChainContracts](README.md#l1crosschaincontracts) +- [L2Chain](README.md#l2chain) +- [L2CrossChainContracts](README.md#l2crosschaincontracts) - [NewWalletRegisteredEvent](README.md#newwalletregisteredevent) - [OptimisticMintingCancelledEvent](README.md#optimisticmintingcancelledevent) - [OptimisticMintingFinalizedEvent](README.md#optimisticmintingfinalizedevent) @@ -95,16 +111,19 @@ - [BitcoinPublicKeyUtils](README.md#bitcoinpublickeyutils) - [BitcoinScriptUtils](README.md#bitcoinscriptutils) - [BitcoinTargetConverter](README.md#bitcointargetconverter) +- [ChainMappings](README.md#chainmappings) ### Functions - [assembleBitcoinSpvProof](README.md#assemblebitcoinspvproof) - [backoffRetrier](README.md#backoffretrier) +- [chainIdFromSigner](README.md#chainidfromsigner) - [computeElectrumScriptHash](README.md#computeelectrumscripthash) - [ethereumAddressFromSigner](README.md#ethereumaddressfromsigner) -- [ethereumNetworkFromSigner](README.md#ethereumnetworkfromsigner) +- [ethereumCrossChainContractsLoader](README.md#ethereumcrosschaincontractsloader) - [extractBitcoinRawTxVectors](README.md#extractbitcoinrawtxvectors) -- [loadEthereumContracts](README.md#loadethereumcontracts) +- [loadBaseCrossChainContracts](README.md#loadbasecrosschaincontracts) +- [loadEthereumCoreContracts](README.md#loadethereumcorecontracts) - [packRevealDepositParameters](README.md#packrevealdepositparameters) - [retryAll](README.md#retryall) - [skipRetryWhenMatched](README.md#skipretrywhenmatched) @@ -139,6 +158,55 @@ Data about a Bitcoin unspent transaction output. ___ +### ChainMapping + +Ƭ **ChainMapping**: `Object` + +Type representing a mapping between specific L1 and L2 chains. + +#### Type declaration + +| Name | Type | Description | +| :------ | :------ | :------ | +| `base?` | [`Base`](enums/Chains.Base.md) | Identifier of the Base L2 chain. | +| `ethereum?` | [`Ethereum`](enums/Chains.Ethereum.md) | Identifier of the Ethereum L1 chain. | + +#### Defined in + +[src/lib/contracts/chain.ts:26](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/contracts/chain.ts#L26) + +___ + +### CrossChainContracts + +Ƭ **CrossChainContracts**: [`L2CrossChainContracts`](README.md#l2crosschaincontracts) & [`L1CrossChainContracts`](README.md#l1crosschaincontracts) + +Convenience type aggregating TBTC cross-chain contracts forming a connector +between TBTC L1 ledger chain and a specific supported L2/side-chain. + +#### Defined in + +[src/lib/contracts/cross-chain.ts:12](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/contracts/cross-chain.ts#L12) + +___ + +### CrossChainDepositorMode + +Ƭ **CrossChainDepositorMode**: ``"L2Transaction"`` \| ``"L1Transaction"`` + +Mode of operation for the cross-chain depositor proxy: +- [L2Transaction]: The proxy will reveal the deposit using a transaction on + the L2 chain. The tBTC system is responsible for relaying the deposit to + the tBTC L1 chain. +- [L1Transaction]: The proxy will directly reveal the deposit using a + transaction on the tBTC L1 chain. + +#### Defined in + +[src/services/deposits/cross-chain.ts:19](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/deposits/cross-chain.ts#L19) + +___ + ### DepositRevealedEvent Ƭ **DepositRevealedEvent**: [`DepositReceipt`](interfaces/DepositReceipt.md) & `Pick`\<[`DepositRequest`](interfaces/DepositRequest.md), ``"amount"`` \| ``"vault"``\> & \{ `fundingOutputIndex`: `number` ; `fundingTxHash`: [`BitcoinTxHash`](classes/BitcoinTxHash.md) } & [`ChainEvent`](interfaces/ChainEvent.md) @@ -228,18 +296,6 @@ True if the error matches, false otherwise. ___ -### EthereumNetwork - -Ƭ **EthereumNetwork**: ``"local"`` \| ``"sepolia"`` \| ``"mainnet"`` - -Supported Ethereum networks. - -#### Defined in - -[src/lib/ethereum/index.ts:75](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/index.ts#L75) - -___ - ### EthereumSigner Ƭ **EthereumSigner**: `Signer` \| `providers.Provider` @@ -250,7 +306,7 @@ or a Provider that works only in the read-only mode. #### Defined in -[src/lib/ethereum/index.ts:26](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/index.ts#L26) +[src/lib/ethereum/index.ts:34](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/index.ts#L34) ___ @@ -280,6 +336,55 @@ A function that is called with execution status messages. ___ +### L1CrossChainContracts + +Ƭ **L1CrossChainContracts**: `Object` + +Aggregates L1-specific TBTC cross-chain contracts. + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `l1BitcoinDepositor` | [`L1BitcoinDepositor`](interfaces/L1BitcoinDepositor.md) | + +#### Defined in + +[src/lib/contracts/cross-chain.ts:25](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/contracts/cross-chain.ts#L25) + +___ + +### L2Chain + +Ƭ **L2Chain**: `Exclude`\ + +Layer 2 chains supported by tBTC v2 contracts. + +#### Defined in + +[src/lib/contracts/chain.ts:21](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/contracts/chain.ts#L21) + +___ + +### L2CrossChainContracts + +Ƭ **L2CrossChainContracts**: `Object` + +Aggregates L2-specific TBTC cross-chain contracts. + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `l2BitcoinDepositor` | [`L2BitcoinDepositor`](interfaces/L2BitcoinDepositor.md) | +| `l2TbtcToken` | [`L2TBTCToken`](interfaces/L2TBTCToken.md) | + +#### Defined in + +[src/lib/contracts/cross-chain.ts:17](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/contracts/cross-chain.ts#L17) + +___ + ### NewWalletRegisteredEvent Ƭ **NewWalletRegisteredEvent**: \{ `ecdsaWalletID`: [`Hex`](classes/Hex.md) ; `walletPublicKeyHash`: [`Hex`](classes/Hex.md) } & [`ChainEvent`](interfaces/ChainEvent.md) @@ -397,7 +502,7 @@ ___ Ƭ **TBTCContracts**: `Object` -Convenience type aggregating all TBTC contracts handles. +Convenience type aggregating all TBTC core contracts. #### Type declaration @@ -410,7 +515,7 @@ Convenience type aggregating all TBTC contracts handles. #### Defined in -[src/lib/contracts/index.ts:17](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/contracts/index.ts#L17) +[src/lib/contracts/index.ts:19](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/contracts/index.ts#L19) ## Variables @@ -589,6 +694,18 @@ Utility functions allowing to perform Bitcoin target conversions. [src/lib/bitcoin/header.ts:268](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/bitcoin/header.ts#L268) +___ + +### ChainMappings + +• `Const` **ChainMappings**: [`ChainMapping`](README.md#chainmapping)[] + +List of chain mappings supported by tBTC v2 contracts. + +#### Defined in + +[src/lib/contracts/chain.ts:40](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/contracts/chain.ts#L40) + ## Functions ### assembleBitcoinSpvProof @@ -668,6 +785,30 @@ A function that can retry any function. ___ +### chainIdFromSigner + +▸ **chainIdFromSigner**(`signer`): `Promise`\<`string`\> + +Resolves the chain ID from the given signer. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `signer` | [`EthereumSigner`](README.md#ethereumsigner) | The signer whose chain ID should be resolved. | + +#### Returns + +`Promise`\<`string`\> + +Chain ID as a string. + +#### Defined in + +[src/lib/ethereum/index.ts:41](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/index.ts#L41) + +___ + ### computeElectrumScriptHash ▸ **computeElectrumScriptHash**(`script`): `string` @@ -719,31 +860,40 @@ Throws an error if the address of the signer is not a proper #### Defined in -[src/lib/ethereum/index.ts:62](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/index.ts#L62) +[src/lib/ethereum/index.ts:63](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/index.ts#L63) ___ -### ethereumNetworkFromSigner +### ethereumCrossChainContractsLoader -▸ **ethereumNetworkFromSigner**(`signer`): `Promise`\<[`EthereumNetwork`](README.md#ethereumnetwork)\> +▸ **ethereumCrossChainContractsLoader**(`signer`, `chainId`): `Promise`\<[`CrossChainContractsLoader`](interfaces/CrossChainContractsLoader.md)\> -Resolves the Ethereum network the given signer is tied to. +Creates the Ethereum implementation of tBTC cross-chain contracts loader. +The provided signer is attached to loaded L1 contracts. The given +Ethereum chain ID is used to load the L1 contracts and resolve the chain +mapping that provides corresponding L2 chains IDs. #### Parameters | Name | Type | Description | | :------ | :------ | :------ | -| `signer` | [`EthereumSigner`](README.md#ethereumsigner) | The signer whose network should be resolved. | +| `signer` | [`EthereumSigner`](README.md#ethereumsigner) | Ethereum L1 signer. | +| `chainId` | [`Ethereum`](enums/Chains.Ethereum.md) | Ethereum L1 chain ID. | #### Returns -`Promise`\<[`EthereumNetwork`](README.md#ethereumnetwork)\> +`Promise`\<[`CrossChainContractsLoader`](interfaces/CrossChainContractsLoader.md)\> -Ethereum network. +Loader for tBTC cross-chain contracts. + +**`Throws`** + +Throws an error if the signer's Ethereum chain ID is other than + the one used to construct the loader. #### Defined in -[src/lib/ethereum/index.ts:33](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/index.ts#L33) +[src/lib/ethereum/index.ts:129](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/index.ts#L129) ___ @@ -772,34 +922,65 @@ Transaction data with fields represented as un-prefixed hex strings. ___ -### loadEthereumContracts +### loadBaseCrossChainContracts + +▸ **loadBaseCrossChainContracts**(`signer`, `chainId`): `Promise`\<[`L2CrossChainContracts`](README.md#l2crosschaincontracts)\> + +Loads Base implementation of tBTC cross-chain contracts for the given Base +chain ID and attaches the given signer there. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `signer` | [`EthereumSigner`](README.md#ethereumsigner) | Signer that should be attached to the contracts. | +| `chainId` | [`Base`](enums/Chains.Base.md) | Base chain ID. | + +#### Returns + +`Promise`\<[`L2CrossChainContracts`](README.md#l2crosschaincontracts)\> + +Handle to the contracts. + +**`Throws`** + +Throws an error if the signer's Base chain ID is other than + the one used to load contracts. + +#### Defined in + +[src/lib/base/index.ts:22](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/base/index.ts#L22) + +___ + +### loadEthereumCoreContracts -▸ **loadEthereumContracts**(`signer`, `network`): `Promise`\<[`TBTCContracts`](README.md#tbtccontracts)\> +▸ **loadEthereumCoreContracts**(`signer`, `chainId`): `Promise`\<[`TBTCContracts`](README.md#tbtccontracts)\> -Loads Ethereum implementation of tBTC contracts for the given Ethereum -network and attaches the given signer there. +Loads Ethereum implementation of tBTC core contracts for the given Ethereum +chain ID and attaches the given signer there. #### Parameters | Name | Type | Description | | :------ | :------ | :------ | | `signer` | [`EthereumSigner`](README.md#ethereumsigner) | Signer that should be attached to tBTC contracts. | -| `network` | [`EthereumNetwork`](README.md#ethereumnetwork) | Ethereum network. | +| `chainId` | [`Ethereum`](enums/Chains.Ethereum.md) | Ethereum chain ID. | #### Returns `Promise`\<[`TBTCContracts`](README.md#tbtccontracts)\> -Handle to tBTC contracts. +Handle to tBTC core contracts. **`Throws`** -Throws an error if the signer's Ethereum network is other than +Throws an error if the signer's Ethereum chain ID is other than the one used to load tBTC contracts. #### Defined in -[src/lib/ethereum/index.ts:86](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/index.ts#L86) +[src/lib/ethereum/index.ts:82](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/index.ts#L82) ___ @@ -843,7 +1024,7 @@ Packed parameters. #### Defined in -[src/lib/ethereum/bridge.ts:687](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L687) +[src/lib/ethereum/bridge.ts:688](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L688) ___ diff --git a/typescript/api-reference/classes/BaseL2BitcoinDepositor.md b/typescript/api-reference/classes/BaseL2BitcoinDepositor.md new file mode 100644 index 000000000..b02ea4910 --- /dev/null +++ b/typescript/api-reference/classes/BaseL2BitcoinDepositor.md @@ -0,0 +1,307 @@ +# Class: BaseL2BitcoinDepositor + +Implementation of the Base L2BitcoinDepositor handle. + +**`See`** + +for reference. + +## Hierarchy + +- `EthersContractHandle`\<`L2BitcoinDepositorTypechain`\> + + ↳ **`BaseL2BitcoinDepositor`** + +## Implements + +- [`L2BitcoinDepositor`](../interfaces/L2BitcoinDepositor.md) + +## Table of contents + +### Constructors + +- [constructor](BaseL2BitcoinDepositor.md#constructor) + +### Properties + +- [#depositOwner](BaseL2BitcoinDepositor.md##depositowner) +- [#extraDataEncoder](BaseL2BitcoinDepositor.md##extradataencoder) +- [\_deployedAtBlockNumber](BaseL2BitcoinDepositor.md#_deployedatblocknumber) +- [\_instance](BaseL2BitcoinDepositor.md#_instance) +- [\_totalRetryAttempts](BaseL2BitcoinDepositor.md#_totalretryattempts) + +### Methods + +- [extraDataEncoder](BaseL2BitcoinDepositor.md#extradataencoder) +- [getAddress](BaseL2BitcoinDepositor.md#getaddress) +- [getChainIdentifier](BaseL2BitcoinDepositor.md#getchainidentifier) +- [getDepositOwner](BaseL2BitcoinDepositor.md#getdepositowner) +- [getEvents](BaseL2BitcoinDepositor.md#getevents) +- [initializeDeposit](BaseL2BitcoinDepositor.md#initializedeposit) +- [setDepositOwner](BaseL2BitcoinDepositor.md#setdepositowner) + +## Constructors + +### constructor + +• **new BaseL2BitcoinDepositor**(`config`, `chainId`): [`BaseL2BitcoinDepositor`](BaseL2BitcoinDepositor.md) + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `config` | [`EthereumContractConfig`](../interfaces/EthereumContractConfig.md) | +| `chainId` | [`Base`](../enums/Chains.Base.md) | + +#### Returns + +[`BaseL2BitcoinDepositor`](BaseL2BitcoinDepositor.md) + +#### Overrides + +EthersContractHandle\<L2BitcoinDepositorTypechain\>.constructor + +#### Defined in + +[src/lib/base/l2-bitcoin-depositor.ts:37](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/base/l2-bitcoin-depositor.ts#L37) + +## Properties + +### #depositOwner + +• `Private` **#depositOwner**: `undefined` \| [`ChainIdentifier`](../interfaces/ChainIdentifier.md) + +#### Defined in + +[src/lib/base/l2-bitcoin-depositor.ts:35](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/base/l2-bitcoin-depositor.ts#L35) + +___ + +### #extraDataEncoder + +• `Private` `Readonly` **#extraDataEncoder**: [`CrossChainExtraDataEncoder`](../interfaces/CrossChainExtraDataEncoder.md) + +#### Defined in + +[src/lib/base/l2-bitcoin-depositor.ts:34](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/base/l2-bitcoin-depositor.ts#L34) + +___ + +### \_deployedAtBlockNumber + +• `Protected` `Readonly` **\_deployedAtBlockNumber**: `number` + +Number of a block within which the contract was deployed. Value is read from +the contract deployment artifact. It can be overwritten by setting a +[EthersContractConfig.deployedAtBlockNumber](../interfaces/EthereumContractConfig.md#deployedatblocknumber) property. + +#### Inherited from + +EthersContractHandle.\_deployedAtBlockNumber + +#### Defined in + +[src/lib/ethereum/adapter.ts:80](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/adapter.ts#L80) + +___ + +### \_instance + +• `Protected` `Readonly` **\_instance**: `L2BitcoinDepositor` + +Ethers instance of the deployed contract. + +#### Inherited from + +EthersContractHandle.\_instance + +#### Defined in + +[src/lib/ethereum/adapter.ts:74](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/adapter.ts#L74) + +___ + +### \_totalRetryAttempts + +• `Protected` `Readonly` **\_totalRetryAttempts**: `number` + +Number of retries for ethereum requests. + +#### Inherited from + +EthersContractHandle.\_totalRetryAttempts + +#### Defined in + +[src/lib/ethereum/adapter.ts:84](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/adapter.ts#L84) + +## Methods + +### extraDataEncoder + +▸ **extraDataEncoder**(): [`CrossChainExtraDataEncoder`](../interfaces/CrossChainExtraDataEncoder.md) + +#### Returns + +[`CrossChainExtraDataEncoder`](../interfaces/CrossChainExtraDataEncoder.md) + +**`See`** + +#### Implementation of + +[L2BitcoinDepositor](../interfaces/L2BitcoinDepositor.md).[extraDataEncoder](../interfaces/L2BitcoinDepositor.md#extradataencoder) + +#### Defined in + +[src/lib/base/l2-bitcoin-depositor.ts:85](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/base/l2-bitcoin-depositor.ts#L85) + +___ + +### getAddress + +▸ **getAddress**(): [`EthereumAddress`](EthereumAddress.md) + +Get address of the contract instance. + +#### Returns + +[`EthereumAddress`](EthereumAddress.md) + +Address of this contract instance. + +#### Inherited from + +EthersContractHandle.getAddress + +#### Defined in + +[src/lib/ethereum/adapter.ts:112](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/adapter.ts#L112) + +___ + +### getChainIdentifier + +▸ **getChainIdentifier**(): [`ChainIdentifier`](../interfaces/ChainIdentifier.md) + +#### Returns + +[`ChainIdentifier`](../interfaces/ChainIdentifier.md) + +**`See`** + +#### Implementation of + +[L2BitcoinDepositor](../interfaces/L2BitcoinDepositor.md).[getChainIdentifier](../interfaces/L2BitcoinDepositor.md#getchainidentifier) + +#### Defined in + +[src/lib/base/l2-bitcoin-depositor.ts:61](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/base/l2-bitcoin-depositor.ts#L61) + +___ + +### getDepositOwner + +▸ **getDepositOwner**(): `undefined` \| [`ChainIdentifier`](../interfaces/ChainIdentifier.md) + +#### Returns + +`undefined` \| [`ChainIdentifier`](../interfaces/ChainIdentifier.md) + +**`See`** + +#### Implementation of + +[L2BitcoinDepositor](../interfaces/L2BitcoinDepositor.md).[getDepositOwner](../interfaces/L2BitcoinDepositor.md#getdepositowner) + +#### Defined in + +[src/lib/base/l2-bitcoin-depositor.ts:69](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/base/l2-bitcoin-depositor.ts#L69) + +___ + +### getEvents + +▸ **getEvents**(`eventName`, `options?`, `...filterArgs`): `Promise`\<`Event`[]\> + +Get events emitted by the Ethereum contract. +It starts searching from provided block number. If the GetEvents.Options#fromBlock +option is missing it looks for a contract's defined property +[_deployedAtBlockNumber](BaseL2BitcoinDepositor.md#_deployedatblocknumber). If the property is missing starts searching +from block `0`. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `eventName` | `string` | Name of the event. | +| `options?` | [`Options`](../interfaces/GetChainEvents.Options.md) | Options for events fetching. | +| `...filterArgs` | `unknown`[] | Arguments for events filtering. | + +#### Returns + +`Promise`\<`Event`[]\> + +Array of found events. + +#### Inherited from + +EthersContractHandle.getEvents + +#### Defined in + +[src/lib/ethereum/adapter.ts:127](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/adapter.ts#L127) + +___ + +### initializeDeposit + +▸ **initializeDeposit**(`depositTx`, `depositOutputIndex`, `deposit`, `vault?`): `Promise`\<[`Hex`](Hex.md)\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `depositTx` | [`BitcoinRawTxVectors`](../interfaces/BitcoinRawTxVectors.md) | +| `depositOutputIndex` | `number` | +| `deposit` | [`DepositReceipt`](../interfaces/DepositReceipt.md) | +| `vault?` | [`ChainIdentifier`](../interfaces/ChainIdentifier.md) | + +#### Returns + +`Promise`\<[`Hex`](Hex.md)\> + +**`See`** + +#### Implementation of + +[L2BitcoinDepositor](../interfaces/L2BitcoinDepositor.md).[initializeDeposit](../interfaces/L2BitcoinDepositor.md#initializedeposit) + +#### Defined in + +[src/lib/base/l2-bitcoin-depositor.ts:93](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/base/l2-bitcoin-depositor.ts#L93) + +___ + +### setDepositOwner + +▸ **setDepositOwner**(`depositOwner`): `void` + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `depositOwner` | `undefined` \| [`ChainIdentifier`](../interfaces/ChainIdentifier.md) | + +#### Returns + +`void` + +**`See`** + +#### Implementation of + +[L2BitcoinDepositor](../interfaces/L2BitcoinDepositor.md).[setDepositOwner](../interfaces/L2BitcoinDepositor.md#setdepositowner) + +#### Defined in + +[src/lib/base/l2-bitcoin-depositor.ts:77](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/base/l2-bitcoin-depositor.ts#L77) diff --git a/typescript/api-reference/classes/BaseL2TBTCToken.md b/typescript/api-reference/classes/BaseL2TBTCToken.md new file mode 100644 index 000000000..069905dc4 --- /dev/null +++ b/typescript/api-reference/classes/BaseL2TBTCToken.md @@ -0,0 +1,213 @@ +# Class: BaseL2TBTCToken + +Implementation of the Base L2TBTCToken handle. + +**`See`** + +for reference. + +## Hierarchy + +- `EthersContractHandle`\<`L2TBTCTypechain`\> + + ↳ **`BaseL2TBTCToken`** + +## Implements + +- [`L2TBTCToken`](../interfaces/L2TBTCToken.md) + +## Table of contents + +### Constructors + +- [constructor](BaseL2TBTCToken.md#constructor) + +### Properties + +- [\_deployedAtBlockNumber](BaseL2TBTCToken.md#_deployedatblocknumber) +- [\_instance](BaseL2TBTCToken.md#_instance) +- [\_totalRetryAttempts](BaseL2TBTCToken.md#_totalretryattempts) + +### Methods + +- [balanceOf](BaseL2TBTCToken.md#balanceof) +- [getAddress](BaseL2TBTCToken.md#getaddress) +- [getChainIdentifier](BaseL2TBTCToken.md#getchainidentifier) +- [getEvents](BaseL2TBTCToken.md#getevents) + +## Constructors + +### constructor + +• **new BaseL2TBTCToken**(`config`, `chainId`): [`BaseL2TBTCToken`](BaseL2TBTCToken.md) + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `config` | [`EthereumContractConfig`](../interfaces/EthereumContractConfig.md) | +| `chainId` | [`Base`](../enums/Chains.Base.md) | + +#### Returns + +[`BaseL2TBTCToken`](BaseL2TBTCToken.md) + +#### Overrides + +EthersContractHandle\<L2TBTCTypechain\>.constructor + +#### Defined in + +[src/lib/base/l2-tbtc-token.ts:21](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/base/l2-tbtc-token.ts#L21) + +## Properties + +### \_deployedAtBlockNumber + +• `Protected` `Readonly` **\_deployedAtBlockNumber**: `number` + +Number of a block within which the contract was deployed. Value is read from +the contract deployment artifact. It can be overwritten by setting a +[EthersContractConfig.deployedAtBlockNumber](../interfaces/EthereumContractConfig.md#deployedatblocknumber) property. + +#### Inherited from + +EthersContractHandle.\_deployedAtBlockNumber + +#### Defined in + +[src/lib/ethereum/adapter.ts:80](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/adapter.ts#L80) + +___ + +### \_instance + +• `Protected` `Readonly` **\_instance**: `L2TBTC` + +Ethers instance of the deployed contract. + +#### Inherited from + +EthersContractHandle.\_instance + +#### Defined in + +[src/lib/ethereum/adapter.ts:74](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/adapter.ts#L74) + +___ + +### \_totalRetryAttempts + +• `Protected` `Readonly` **\_totalRetryAttempts**: `number` + +Number of retries for ethereum requests. + +#### Inherited from + +EthersContractHandle.\_totalRetryAttempts + +#### Defined in + +[src/lib/ethereum/adapter.ts:84](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/adapter.ts#L84) + +## Methods + +### balanceOf + +▸ **balanceOf**(`identifier`): `Promise`\<`BigNumber`\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `identifier` | [`ChainIdentifier`](../interfaces/ChainIdentifier.md) | + +#### Returns + +`Promise`\<`BigNumber`\> + +**`See`** + +#### Implementation of + +[L2TBTCToken](../interfaces/L2TBTCToken.md).[balanceOf](../interfaces/L2TBTCToken.md#balanceof) + +#### Defined in + +[src/lib/base/l2-tbtc-token.ts:50](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/base/l2-tbtc-token.ts#L50) + +___ + +### getAddress + +▸ **getAddress**(): [`EthereumAddress`](EthereumAddress.md) + +Get address of the contract instance. + +#### Returns + +[`EthereumAddress`](EthereumAddress.md) + +Address of this contract instance. + +#### Inherited from + +EthersContractHandle.getAddress + +#### Defined in + +[src/lib/ethereum/adapter.ts:112](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/adapter.ts#L112) + +___ + +### getChainIdentifier + +▸ **getChainIdentifier**(): [`ChainIdentifier`](../interfaces/ChainIdentifier.md) + +#### Returns + +[`ChainIdentifier`](../interfaces/ChainIdentifier.md) + +**`See`** + +#### Implementation of + +[L2TBTCToken](../interfaces/L2TBTCToken.md).[getChainIdentifier](../interfaces/L2TBTCToken.md#getchainidentifier) + +#### Defined in + +[src/lib/base/l2-tbtc-token.ts:42](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/base/l2-tbtc-token.ts#L42) + +___ + +### getEvents + +▸ **getEvents**(`eventName`, `options?`, `...filterArgs`): `Promise`\<`Event`[]\> + +Get events emitted by the Ethereum contract. +It starts searching from provided block number. If the GetEvents.Options#fromBlock +option is missing it looks for a contract's defined property +[_deployedAtBlockNumber](BaseL2BitcoinDepositor.md#_deployedatblocknumber). If the property is missing starts searching +from block `0`. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `eventName` | `string` | Name of the event. | +| `options?` | [`Options`](../interfaces/GetChainEvents.Options.md) | Options for events fetching. | +| `...filterArgs` | `unknown`[] | Arguments for events filtering. | + +#### Returns + +`Promise`\<`Event`[]\> + +Array of found events. + +#### Inherited from + +EthersContractHandle.getEvents + +#### Defined in + +[src/lib/ethereum/adapter.ts:127](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/adapter.ts#L127) diff --git a/typescript/api-reference/classes/CrossChainDepositor.md b/typescript/api-reference/classes/CrossChainDepositor.md new file mode 100644 index 000000000..ddc99c141 --- /dev/null +++ b/typescript/api-reference/classes/CrossChainDepositor.md @@ -0,0 +1,172 @@ +# Class: CrossChainDepositor + +Implementation of the cross chain depositor proxy. This component is used to +reveal cross-chain deposits whose target chain is not the same as the L1 +chain the tBTC system is deployed on. + +**`See`** + +for reference. + +## Implements + +- [`DepositorProxy`](../interfaces/DepositorProxy.md) + +## Table of contents + +### Constructors + +- [constructor](CrossChainDepositor.md#constructor) + +### Properties + +- [#crossChainContracts](CrossChainDepositor.md##crosschaincontracts) +- [#revealMode](CrossChainDepositor.md##revealmode) + +### Methods + +- [#extraDataEncoder](CrossChainDepositor.md##extradataencoder) +- [extraData](CrossChainDepositor.md#extradata) +- [getChainIdentifier](CrossChainDepositor.md#getchainidentifier) +- [revealDeposit](CrossChainDepositor.md#revealdeposit) + +## Constructors + +### constructor + +• **new CrossChainDepositor**(`crossChainContracts`, `revealMode?`): [`CrossChainDepositor`](CrossChainDepositor.md) + +#### Parameters + +| Name | Type | Default value | +| :------ | :------ | :------ | +| `crossChainContracts` | [`CrossChainContracts`](../README.md#crosschaincontracts) | `undefined` | +| `revealMode` | [`CrossChainDepositorMode`](../README.md#crosschaindepositormode) | `"L2Transaction"` | + +#### Returns + +[`CrossChainDepositor`](CrossChainDepositor.md) + +#### Defined in + +[src/services/deposits/cross-chain.ts:31](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/deposits/cross-chain.ts#L31) + +## Properties + +### #crossChainContracts + +• `Private` `Readonly` **#crossChainContracts**: [`CrossChainContracts`](../README.md#crosschaincontracts) + +#### Defined in + +[src/services/deposits/cross-chain.ts:28](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/deposits/cross-chain.ts#L28) + +___ + +### #revealMode + +• `Private` `Readonly` **#revealMode**: [`CrossChainDepositorMode`](../README.md#crosschaindepositormode) + +#### Defined in + +[src/services/deposits/cross-chain.ts:29](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/deposits/cross-chain.ts#L29) + +## Methods + +### #extraDataEncoder + +▸ **#extraDataEncoder**(): [`CrossChainExtraDataEncoder`](../interfaces/CrossChainExtraDataEncoder.md) + +#### Returns + +[`CrossChainExtraDataEncoder`](../interfaces/CrossChainExtraDataEncoder.md) + +#### Defined in + +[src/services/deposits/cross-chain.ts:72](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/deposits/cross-chain.ts#L72) + +___ + +### extraData + +▸ **extraData**(): [`Hex`](Hex.md) + +#### Returns + +[`Hex`](Hex.md) + +Extra data for the cross-chain deposit script. Actually, this is + the L2 deposit owner identifier took from the L2BitcoinDepositor + contract. + +**`Throws`** + +Throws if the L2 deposit owner cannot be resolved. This + typically happens if the L2BitcoinDepositor operates with + a read-only signer whose address cannot be resolved. + +#### Defined in + +[src/services/deposits/cross-chain.ts:61](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/deposits/cross-chain.ts#L61) + +___ + +### getChainIdentifier + +▸ **getChainIdentifier**(): [`ChainIdentifier`](../interfaces/ChainIdentifier.md) + +#### Returns + +[`ChainIdentifier`](../interfaces/ChainIdentifier.md) + +The chain-specific identifier of the contract that will be + used as the actual L1 depositor embedded in the deposit script. + In this case, the depositor must be the L1BitcoinDepositor contract + corresponding to the given L2 chain the deposit is targeting. + This is because the L1BitcoinDepositor contract reveals the deposit to + the Bridge contract (on L1) and transfers minted TBTC token to the + target L2 chain once the deposit is processed. + +**`See`** + +#### Implementation of + +[DepositorProxy](../interfaces/DepositorProxy.md).[getChainIdentifier](../interfaces/DepositorProxy.md#getchainidentifier) + +#### Defined in + +[src/services/deposits/cross-chain.ts:49](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/deposits/cross-chain.ts#L49) + +___ + +### revealDeposit + +▸ **revealDeposit**(`depositTx`, `depositOutputIndex`, `deposit`, `vault?`): `Promise`\<[`Hex`](Hex.md)\> + +Reveals the given deposit depending on the reveal mode. + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `depositTx` | [`BitcoinRawTxVectors`](../interfaces/BitcoinRawTxVectors.md) | +| `depositOutputIndex` | `number` | +| `deposit` | [`DepositReceipt`](../interfaces/DepositReceipt.md) | +| `vault?` | [`ChainIdentifier`](../interfaces/ChainIdentifier.md) | + +#### Returns + +`Promise`\<[`Hex`](Hex.md)\> + +**`See`** + + - for reveal modes description. + - + +#### Implementation of + +[DepositorProxy](../interfaces/DepositorProxy.md).[revealDeposit](../interfaces/DepositorProxy.md#revealdeposit) + +#### Defined in + +[src/services/deposits/cross-chain.ts:87](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/deposits/cross-chain.ts#L87) diff --git a/typescript/api-reference/classes/DepositsService.md b/typescript/api-reference/classes/DepositsService.md index 31dad4af5..5b3a91e08 100644 --- a/typescript/api-reference/classes/DepositsService.md +++ b/typescript/api-reference/classes/DepositsService.md @@ -10,14 +10,16 @@ Service exposing features related to tBTC v2 deposits. ### Properties +- [#crossChainContracts](DepositsService.md##crosschaincontracts) +- [#defaultDepositor](DepositsService.md##defaultdepositor) - [bitcoinClient](DepositsService.md#bitcoinclient) -- [defaultDepositor](DepositsService.md#defaultdepositor) - [depositRefundLocktimeDuration](DepositsService.md#depositrefundlocktimeduration) - [tbtcContracts](DepositsService.md#tbtccontracts) ### Methods - [generateDepositReceipt](DepositsService.md#generatedepositreceipt) +- [initiateCrossChainDeposit](DepositsService.md#initiatecrosschaindeposit) - [initiateDeposit](DepositsService.md#initiatedeposit) - [initiateDepositWithProxy](DepositsService.md#initiatedepositwithproxy) - [setDefaultDepositor](DepositsService.md#setdefaultdepositor) @@ -26,7 +28,7 @@ Service exposing features related to tBTC v2 deposits. ### constructor -• **new DepositsService**(`tbtcContracts`, `bitcoinClient`): [`DepositsService`](DepositsService.md) +• **new DepositsService**(`tbtcContracts`, `bitcoinClient`, `crossChainContracts`): [`DepositsService`](DepositsService.md) #### Parameters @@ -34,6 +36,7 @@ Service exposing features related to tBTC v2 deposits. | :------ | :------ | | `tbtcContracts` | [`TBTCContracts`](../README.md#tbtccontracts) | | `bitcoinClient` | [`BitcoinClient`](../interfaces/BitcoinClient.md) | +| `crossChainContracts` | (`_`: ``"Base"``) => `undefined` \| [`CrossChainContracts`](../README.md#crosschaincontracts) | #### Returns @@ -41,32 +44,61 @@ Service exposing features related to tBTC v2 deposits. #### Defined in -[src/services/deposits/deposits-service.ts:41](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/deposits/deposits-service.ts#L41) +[src/services/deposits/deposits-service.ts:51](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/deposits/deposits-service.ts#L51) ## Properties -### bitcoinClient +### #crossChainContracts -• `Private` `Readonly` **bitcoinClient**: [`BitcoinClient`](../interfaces/BitcoinClient.md) +• `Private` `Readonly` **#crossChainContracts**: (`_`: ``"Base"``) => `undefined` \| [`CrossChainContracts`](../README.md#crosschaincontracts) -Bitcoin client handle. +#### Type declaration + +▸ (`_`): `undefined` \| [`CrossChainContracts`](../README.md#crosschaincontracts) + +Gets cross-chain contracts for the given supported L2 chain. + +##### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `_` | ``"Base"`` | Name of the L2 chain for which to get cross-chain contracts. | + +##### Returns + +`undefined` \| [`CrossChainContracts`](../README.md#crosschaincontracts) + +Cross-chain contracts for the given L2 chain or + undefined if not initialized. #### Defined in -[src/services/deposits/deposits-service.ts:34](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/deposits/deposits-service.ts#L34) +[src/services/deposits/deposits-service.ts:49](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/deposits/deposits-service.ts#L49) ___ -### defaultDepositor +### #defaultDepositor -• `Private` **defaultDepositor**: `undefined` \| [`ChainIdentifier`](../interfaces/ChainIdentifier.md) +• `Private` **#defaultDepositor**: `undefined` \| [`ChainIdentifier`](../interfaces/ChainIdentifier.md) Chain-specific identifier of the default depositor used for deposits initiated by this service. #### Defined in -[src/services/deposits/deposits-service.ts:39](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/deposits/deposits-service.ts#L39) +[src/services/deposits/deposits-service.ts:42](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/deposits/deposits-service.ts#L42) + +___ + +### bitcoinClient + +• `Private` `Readonly` **bitcoinClient**: [`BitcoinClient`](../interfaces/BitcoinClient.md) + +Bitcoin client handle. + +#### Defined in + +[src/services/deposits/deposits-service.ts:37](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/deposits/deposits-service.ts#L37) ___ @@ -79,7 +111,7 @@ This is 9 month in seconds assuming 1 month = 30 days #### Defined in -[src/services/deposits/deposits-service.ts:26](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/deposits/deposits-service.ts#L26) +[src/services/deposits/deposits-service.ts:29](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/deposits/deposits-service.ts#L29) ___ @@ -91,7 +123,7 @@ Handle to tBTC contracts. #### Defined in -[src/services/deposits/deposits-service.ts:30](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/deposits/deposits-service.ts#L30) +[src/services/deposits/deposits-service.ts:33](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/deposits/deposits-service.ts#L33) ## Methods @@ -113,7 +145,56 @@ Handle to tBTC contracts. #### Defined in -[src/services/deposits/deposits-service.ts:119](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/deposits/deposits-service.ts#L119) +[src/services/deposits/deposits-service.ts:177](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/deposits/deposits-service.ts#L177) + +___ + +### initiateCrossChainDeposit + +▸ **initiateCrossChainDeposit**(`bitcoinRecoveryAddress`, `l2ChainName`): `Promise`\<[`Deposit`](Deposit.md)\> + +Initiates the tBTC v2 cross-chain deposit process. A cross-chain deposit +is a deposit that targets an L2 chain other than the L1 chain the tBTC +system is deployed on. Such a deposit is initiated using a transaction +on the L2 chain. To make it happen, the given L2 cross-chain contracts +must be initialized along with a L2 signer first. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `bitcoinRecoveryAddress` | `string` | P2PKH or P2WPKH Bitcoin address that can be used for emergency recovery of the deposited funds. | +| `l2ChainName` | ``"Base"`` | Name of the L2 chain the deposit is targeting. | + +#### Returns + +`Promise`\<[`Deposit`](Deposit.md)\> + +Handle to the initiated deposit process. + +**`Throws`** + +Throws an error if one of the following occurs: + - There are no active wallet in the Bridge contract + - The Bitcoin recovery address is not a valid P2(W)PKH + - The cross-chain contracts for the given L2 chain are not + initialized + - The L2 deposit owner cannot be resolved. This typically + happens if the L2 cross-chain contracts operate with a + read-only signer whose address cannot be resolved. + +**`See`** + +for cross-chain contracts initialization. + +**`Dev`** + +This is actually a call to initiateDepositWithProxy with a built-in + depositor proxy. + +#### Defined in + +[src/services/deposits/deposits-service.ts:157](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/deposits/deposits-service.ts#L157) ___ @@ -147,7 +228,7 @@ Throws an error if one of the following occurs: #### Defined in -[src/services/deposits/deposits-service.ts:61](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/deposits/deposits-service.ts#L61) +[src/services/deposits/deposits-service.ts:76](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/deposits/deposits-service.ts#L76) ___ @@ -189,7 +270,7 @@ Throws an error if one of the following occurs: #### Defined in -[src/services/deposits/deposits-service.ts:100](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/deposits/deposits-service.ts#L100) +[src/services/deposits/deposits-service.ts:115](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/deposits/deposits-service.ts#L115) ___ @@ -218,4 +299,4 @@ Typically, there is no need to use this method when DepositsService #### Defined in -[src/services/deposits/deposits-service.ts:197](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/deposits/deposits-service.ts#L197) +[src/services/deposits/deposits-service.ts:255](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/deposits/deposits-service.ts#L255) diff --git a/typescript/api-reference/classes/EthereumBridge.md b/typescript/api-reference/classes/EthereumBridge.md index f4510f780..683eb5750 100644 --- a/typescript/api-reference/classes/EthereumBridge.md +++ b/typescript/api-reference/classes/EthereumBridge.md @@ -59,14 +59,14 @@ for reference. ### constructor -• **new EthereumBridge**(`config`, `deploymentType?`): [`EthereumBridge`](EthereumBridge.md) +• **new EthereumBridge**(`config`, `chainId?`): [`EthereumBridge`](EthereumBridge.md) #### Parameters | Name | Type | Default value | | :------ | :------ | :------ | | `config` | [`EthereumContractConfig`](../interfaces/EthereumContractConfig.md) | `undefined` | -| `deploymentType` | ``"local"`` \| ``"sepolia"`` \| ``"mainnet"`` | `"local"` | +| `chainId` | [`Ethereum`](../enums/Chains.Ethereum.md) | `Chains.Ethereum.Local` | #### Returns @@ -78,7 +78,7 @@ EthersContractHandle\<BridgeTypechain\>.constructor #### Defined in -[src/lib/ethereum/bridge.ts:59](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L59) +[src/lib/ethereum/bridge.ts:60](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L60) ## Properties @@ -148,7 +148,7 @@ EthersContractHandle.\_totalRetryAttempts #### Defined in -[src/lib/ethereum/bridge.ts:493](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L493) +[src/lib/ethereum/bridge.ts:494](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L494) ___ @@ -177,7 +177,7 @@ Builds the UTXO hash based on the UTXO components. UTXO hash is computed as #### Defined in -[src/lib/ethereum/bridge.ts:617](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L617) +[src/lib/ethereum/bridge.ts:618](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L618) ___ @@ -204,7 +204,7 @@ ___ #### Defined in -[src/lib/ethereum/bridge.ts:428](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L428) +[src/lib/ethereum/bridge.ts:429](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L429) ___ @@ -246,7 +246,7 @@ ___ #### Defined in -[src/lib/ethereum/bridge.ts:86](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L86) +[src/lib/ethereum/bridge.ts:87](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L87) ___ @@ -273,7 +273,7 @@ Bridge.getDepositRevealedEvents #### Defined in -[src/lib/ethereum/bridge.ts:94](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L94) +[src/lib/ethereum/bridge.ts:95](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L95) ___ @@ -284,7 +284,7 @@ ___ Get events emitted by the Ethereum contract. It starts searching from provided block number. If the GetEvents.Options#fromBlock option is missing it looks for a contract's defined property -[_deployedAtBlockNumber](EthereumBridge.md#_deployedatblocknumber). If the property is missing starts searching +[_deployedAtBlockNumber](BaseL2BitcoinDepositor.md#_deployedatblocknumber). If the property is missing starts searching from block `0`. #### Parameters @@ -334,7 +334,7 @@ Bridge.getNewWalletRegisteredEvents #### Defined in -[src/lib/ethereum/bridge.ts:529](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L529) +[src/lib/ethereum/bridge.ts:530](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L530) ___ @@ -361,7 +361,7 @@ Bridge.getRedemptionRequestedEvents #### Defined in -[src/lib/ethereum/bridge.ts:634](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L634) +[src/lib/ethereum/bridge.ts:635](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L635) ___ @@ -381,7 +381,7 @@ ___ #### Defined in -[src/lib/ethereum/bridge.ts:514](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L514) +[src/lib/ethereum/bridge.ts:515](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L515) ___ @@ -405,7 +405,7 @@ Parsed deposit request. #### Defined in -[src/lib/ethereum/bridge.ts:473](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L473) +[src/lib/ethereum/bridge.ts:474](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L474) ___ @@ -430,7 +430,7 @@ Parsed redemption request. #### Defined in -[src/lib/ethereum/bridge.ts:212](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L212) +[src/lib/ethereum/bridge.ts:213](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L213) ___ @@ -454,7 +454,7 @@ Parsed wallet data. #### Defined in -[src/lib/ethereum/bridge.ts:588](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L588) +[src/lib/ethereum/bridge.ts:589](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L589) ___ @@ -481,7 +481,7 @@ ___ #### Defined in -[src/lib/ethereum/bridge.ts:131](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L131) +[src/lib/ethereum/bridge.ts:132](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L132) ___ @@ -510,7 +510,7 @@ ___ #### Defined in -[src/lib/ethereum/bridge.ts:333](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L333) +[src/lib/ethereum/bridge.ts:334](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L334) ___ @@ -539,7 +539,7 @@ ___ #### Defined in -[src/lib/ethereum/bridge.ts:230](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L230) +[src/lib/ethereum/bridge.ts:231](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L231) ___ @@ -568,7 +568,7 @@ ___ #### Defined in -[src/lib/ethereum/bridge.ts:267](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L267) +[src/lib/ethereum/bridge.ts:268](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L268) ___ @@ -597,7 +597,7 @@ ___ #### Defined in -[src/lib/ethereum/bridge.ts:377](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L377) +[src/lib/ethereum/bridge.ts:378](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L378) ___ @@ -624,7 +624,7 @@ ___ #### Defined in -[src/lib/ethereum/bridge.ts:154](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L154) +[src/lib/ethereum/bridge.ts:155](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L155) ___ @@ -644,7 +644,7 @@ ___ #### Defined in -[src/lib/ethereum/bridge.ts:319](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L319) +[src/lib/ethereum/bridge.ts:320](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L320) ___ @@ -664,7 +664,7 @@ ___ #### Defined in -[src/lib/ethereum/bridge.ts:554](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L554) +[src/lib/ethereum/bridge.ts:555](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L555) ___ @@ -690,7 +690,7 @@ ___ #### Defined in -[src/lib/ethereum/bridge.ts:571](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L571) +[src/lib/ethereum/bridge.ts:572](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L572) ___ @@ -715,7 +715,7 @@ Deposit key. #### Defined in -[src/lib/ethereum/bridge.ts:454](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L454) +[src/lib/ethereum/bridge.ts:455](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L455) ___ @@ -740,4 +740,4 @@ The redemption key. #### Defined in -[src/lib/ethereum/bridge.ts:182](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L182) +[src/lib/ethereum/bridge.ts:183](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/bridge.ts#L183) diff --git a/typescript/api-reference/classes/EthereumCrossChainExtraDataEncoder.md b/typescript/api-reference/classes/EthereumCrossChainExtraDataEncoder.md new file mode 100644 index 000000000..370e78311 --- /dev/null +++ b/typescript/api-reference/classes/EthereumCrossChainExtraDataEncoder.md @@ -0,0 +1,84 @@ +# Class: EthereumCrossChainExtraDataEncoder + +Implementation of the Ethereum CrossChainExtraDataEncoder. + +**`See`** + +for reference. + +## Implements + +- [`CrossChainExtraDataEncoder`](../interfaces/CrossChainExtraDataEncoder.md) + +## Table of contents + +### Constructors + +- [constructor](EthereumCrossChainExtraDataEncoder.md#constructor) + +### Methods + +- [decodeDepositOwner](EthereumCrossChainExtraDataEncoder.md#decodedepositowner) +- [encodeDepositOwner](EthereumCrossChainExtraDataEncoder.md#encodedepositowner) + +## Constructors + +### constructor + +• **new EthereumCrossChainExtraDataEncoder**(): [`EthereumCrossChainExtraDataEncoder`](EthereumCrossChainExtraDataEncoder.md) + +#### Returns + +[`EthereumCrossChainExtraDataEncoder`](EthereumCrossChainExtraDataEncoder.md) + +## Methods + +### decodeDepositOwner + +▸ **decodeDepositOwner**(`extraData`): [`ChainIdentifier`](../interfaces/ChainIdentifier.md) + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `extraData` | [`Hex`](Hex.md) | + +#### Returns + +[`ChainIdentifier`](../interfaces/ChainIdentifier.md) + +**`See`** + +#### Implementation of + +[CrossChainExtraDataEncoder](../interfaces/CrossChainExtraDataEncoder.md).[decodeDepositOwner](../interfaces/CrossChainExtraDataEncoder.md#decodedepositowner) + +#### Defined in + +[src/lib/ethereum/l1-bitcoin-depositor.ts:154](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/l1-bitcoin-depositor.ts#L154) + +___ + +### encodeDepositOwner + +▸ **encodeDepositOwner**(`depositOwner`): [`Hex`](Hex.md) + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `depositOwner` | [`ChainIdentifier`](../interfaces/ChainIdentifier.md) | + +#### Returns + +[`Hex`](Hex.md) + +**`See`** + +#### Implementation of + +[CrossChainExtraDataEncoder](../interfaces/CrossChainExtraDataEncoder.md).[encodeDepositOwner](../interfaces/CrossChainExtraDataEncoder.md#encodedepositowner) + +#### Defined in + +[src/lib/ethereum/l1-bitcoin-depositor.ts:140](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/l1-bitcoin-depositor.ts#L140) diff --git a/typescript/api-reference/classes/EthereumL1BitcoinDepositor.md b/typescript/api-reference/classes/EthereumL1BitcoinDepositor.md new file mode 100644 index 000000000..b6527dc56 --- /dev/null +++ b/typescript/api-reference/classes/EthereumL1BitcoinDepositor.md @@ -0,0 +1,250 @@ +# Class: EthereumL1BitcoinDepositor + +Implementation of the Ethereum L1BitcoinDepositor handle. It can be +constructed for each supported L2 chain. + +**`See`** + +for reference. + +## Hierarchy + +- `EthersContractHandle`\<`L1BitcoinDepositorTypechain`\> + + ↳ **`EthereumL1BitcoinDepositor`** + +## Implements + +- [`L1BitcoinDepositor`](../interfaces/L1BitcoinDepositor.md) + +## Table of contents + +### Constructors + +- [constructor](EthereumL1BitcoinDepositor.md#constructor) + +### Properties + +- [#extraDataEncoder](EthereumL1BitcoinDepositor.md##extradataencoder) +- [\_deployedAtBlockNumber](EthereumL1BitcoinDepositor.md#_deployedatblocknumber) +- [\_instance](EthereumL1BitcoinDepositor.md#_instance) +- [\_totalRetryAttempts](EthereumL1BitcoinDepositor.md#_totalretryattempts) + +### Methods + +- [extraDataEncoder](EthereumL1BitcoinDepositor.md#extradataencoder) +- [getAddress](EthereumL1BitcoinDepositor.md#getaddress) +- [getChainIdentifier](EthereumL1BitcoinDepositor.md#getchainidentifier) +- [getEvents](EthereumL1BitcoinDepositor.md#getevents) +- [initializeDeposit](EthereumL1BitcoinDepositor.md#initializedeposit) + +## Constructors + +### constructor + +• **new EthereumL1BitcoinDepositor**(`config`, `chainId`, `l2ChainName`): [`EthereumL1BitcoinDepositor`](EthereumL1BitcoinDepositor.md) + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `config` | [`EthereumContractConfig`](../interfaces/EthereumContractConfig.md) | +| `chainId` | [`Ethereum`](../enums/Chains.Ethereum.md) | +| `l2ChainName` | ``"Base"`` | + +#### Returns + +[`EthereumL1BitcoinDepositor`](EthereumL1BitcoinDepositor.md) + +#### Overrides + +EthersContractHandle\<L1BitcoinDepositorTypechain\>.constructor + +#### Defined in + +[src/lib/ethereum/l1-bitcoin-depositor.ts:55](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/l1-bitcoin-depositor.ts#L55) + +## Properties + +### #extraDataEncoder + +• `Private` `Readonly` **#extraDataEncoder**: [`CrossChainExtraDataEncoder`](../interfaces/CrossChainExtraDataEncoder.md) + +#### Defined in + +[src/lib/ethereum/l1-bitcoin-depositor.ts:53](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/l1-bitcoin-depositor.ts#L53) + +___ + +### \_deployedAtBlockNumber + +• `Protected` `Readonly` **\_deployedAtBlockNumber**: `number` + +Number of a block within which the contract was deployed. Value is read from +the contract deployment artifact. It can be overwritten by setting a +[EthersContractConfig.deployedAtBlockNumber](../interfaces/EthereumContractConfig.md#deployedatblocknumber) property. + +#### Inherited from + +EthersContractHandle.\_deployedAtBlockNumber + +#### Defined in + +[src/lib/ethereum/adapter.ts:80](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/adapter.ts#L80) + +___ + +### \_instance + +• `Protected` `Readonly` **\_instance**: `L1BitcoinDepositor` + +Ethers instance of the deployed contract. + +#### Inherited from + +EthersContractHandle.\_instance + +#### Defined in + +[src/lib/ethereum/adapter.ts:74](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/adapter.ts#L74) + +___ + +### \_totalRetryAttempts + +• `Protected` `Readonly` **\_totalRetryAttempts**: `number` + +Number of retries for ethereum requests. + +#### Inherited from + +EthersContractHandle.\_totalRetryAttempts + +#### Defined in + +[src/lib/ethereum/adapter.ts:84](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/adapter.ts#L84) + +## Methods + +### extraDataEncoder + +▸ **extraDataEncoder**(): [`CrossChainExtraDataEncoder`](../interfaces/CrossChainExtraDataEncoder.md) + +#### Returns + +[`CrossChainExtraDataEncoder`](../interfaces/CrossChainExtraDataEncoder.md) + +**`See`** + +#### Implementation of + +[L1BitcoinDepositor](../interfaces/L1BitcoinDepositor.md).[extraDataEncoder](../interfaces/L1BitcoinDepositor.md#extradataencoder) + +#### Defined in + +[src/lib/ethereum/l1-bitcoin-depositor.ts:90](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/l1-bitcoin-depositor.ts#L90) + +___ + +### getAddress + +▸ **getAddress**(): [`EthereumAddress`](EthereumAddress.md) + +Get address of the contract instance. + +#### Returns + +[`EthereumAddress`](EthereumAddress.md) + +Address of this contract instance. + +#### Inherited from + +EthersContractHandle.getAddress + +#### Defined in + +[src/lib/ethereum/adapter.ts:112](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/adapter.ts#L112) + +___ + +### getChainIdentifier + +▸ **getChainIdentifier**(): [`ChainIdentifier`](../interfaces/ChainIdentifier.md) + +#### Returns + +[`ChainIdentifier`](../interfaces/ChainIdentifier.md) + +**`See`** + +#### Implementation of + +[L1BitcoinDepositor](../interfaces/L1BitcoinDepositor.md).[getChainIdentifier](../interfaces/L1BitcoinDepositor.md#getchainidentifier) + +#### Defined in + +[src/lib/ethereum/l1-bitcoin-depositor.ts:82](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/l1-bitcoin-depositor.ts#L82) + +___ + +### getEvents + +▸ **getEvents**(`eventName`, `options?`, `...filterArgs`): `Promise`\<`Event`[]\> + +Get events emitted by the Ethereum contract. +It starts searching from provided block number. If the GetEvents.Options#fromBlock +option is missing it looks for a contract's defined property +[_deployedAtBlockNumber](BaseL2BitcoinDepositor.md#_deployedatblocknumber). If the property is missing starts searching +from block `0`. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `eventName` | `string` | Name of the event. | +| `options?` | [`Options`](../interfaces/GetChainEvents.Options.md) | Options for events fetching. | +| `...filterArgs` | `unknown`[] | Arguments for events filtering. | + +#### Returns + +`Promise`\<`Event`[]\> + +Array of found events. + +#### Inherited from + +EthersContractHandle.getEvents + +#### Defined in + +[src/lib/ethereum/adapter.ts:127](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/adapter.ts#L127) + +___ + +### initializeDeposit + +▸ **initializeDeposit**(`depositTx`, `depositOutputIndex`, `deposit`, `vault?`): `Promise`\<[`Hex`](Hex.md)\> + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `depositTx` | [`BitcoinRawTxVectors`](../interfaces/BitcoinRawTxVectors.md) | +| `depositOutputIndex` | `number` | +| `deposit` | [`DepositReceipt`](../interfaces/DepositReceipt.md) | +| `vault?` | [`ChainIdentifier`](../interfaces/ChainIdentifier.md) | + +#### Returns + +`Promise`\<[`Hex`](Hex.md)\> + +**`See`** + +#### Implementation of + +[L1BitcoinDepositor](../interfaces/L1BitcoinDepositor.md).[initializeDeposit](../interfaces/L1BitcoinDepositor.md#initializedeposit) + +#### Defined in + +[src/lib/ethereum/l1-bitcoin-depositor.ts:98](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/l1-bitcoin-depositor.ts#L98) diff --git a/typescript/api-reference/classes/EthereumTBTCToken.md b/typescript/api-reference/classes/EthereumTBTCToken.md index 107b12bfc..95a043433 100644 --- a/typescript/api-reference/classes/EthereumTBTCToken.md +++ b/typescript/api-reference/classes/EthereumTBTCToken.md @@ -42,14 +42,14 @@ for reference. ### constructor -• **new EthereumTBTCToken**(`config`, `deploymentType?`): [`EthereumTBTCToken`](EthereumTBTCToken.md) +• **new EthereumTBTCToken**(`config`, `chainId?`): [`EthereumTBTCToken`](EthereumTBTCToken.md) #### Parameters | Name | Type | Default value | | :------ | :------ | :------ | | `config` | [`EthereumContractConfig`](../interfaces/EthereumContractConfig.md) | `undefined` | -| `deploymentType` | ``"local"`` \| ``"sepolia"`` \| ``"mainnet"`` | `"local"` | +| `chainId` | [`Ethereum`](../enums/Chains.Ethereum.md) | `Chains.Ethereum.Local` | #### Returns @@ -218,7 +218,7 @@ ___ Get events emitted by the Ethereum contract. It starts searching from provided block number. If the GetEvents.Options#fromBlock option is missing it looks for a contract's defined property -[_deployedAtBlockNumber](EthereumBridge.md#_deployedatblocknumber). If the property is missing starts searching +[_deployedAtBlockNumber](BaseL2BitcoinDepositor.md#_deployedatblocknumber). If the property is missing starts searching from block `0`. #### Parameters diff --git a/typescript/api-reference/classes/EthereumTBTCVault.md b/typescript/api-reference/classes/EthereumTBTCVault.md index 43c6971ca..cf5df7fde 100644 --- a/typescript/api-reference/classes/EthereumTBTCVault.md +++ b/typescript/api-reference/classes/EthereumTBTCVault.md @@ -50,14 +50,14 @@ for reference. ### constructor -• **new EthereumTBTCVault**(`config`, `deploymentType?`): [`EthereumTBTCVault`](EthereumTBTCVault.md) +• **new EthereumTBTCVault**(`config`, `chainId?`): [`EthereumTBTCVault`](EthereumTBTCVault.md) #### Parameters | Name | Type | Default value | | :------ | :------ | :------ | | `config` | [`EthereumContractConfig`](../interfaces/EthereumContractConfig.md) | `undefined` | -| `deploymentType` | ``"local"`` \| ``"sepolia"`` \| ``"mainnet"`` | `"local"` | +| `chainId` | [`Ethereum`](../enums/Chains.Ethereum.md) | `Chains.Ethereum.Local` | #### Returns @@ -69,7 +69,7 @@ EthersContractHandle\<TBTCVaultTypechain\>.constructor #### Defined in -[src/lib/ethereum/tbtc-vault.ts:40](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/tbtc-vault.ts#L40) +[src/lib/ethereum/tbtc-vault.ts:41](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/tbtc-vault.ts#L41) ## Properties @@ -146,7 +146,7 @@ EthersContractHandle.\_totalRetryAttempts #### Defined in -[src/lib/ethereum/tbtc-vault.ts:149](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/tbtc-vault.ts#L149) +[src/lib/ethereum/tbtc-vault.ts:150](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/tbtc-vault.ts#L150) ___ @@ -173,7 +173,7 @@ ___ #### Defined in -[src/lib/ethereum/tbtc-vault.ts:172](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/tbtc-vault.ts#L172) +[src/lib/ethereum/tbtc-vault.ts:173](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/tbtc-vault.ts#L173) ___ @@ -215,7 +215,7 @@ ___ #### Defined in -[src/lib/ethereum/tbtc-vault.ts:67](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/tbtc-vault.ts#L67) +[src/lib/ethereum/tbtc-vault.ts:68](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/tbtc-vault.ts#L68) ___ @@ -226,7 +226,7 @@ ___ Get events emitted by the Ethereum contract. It starts searching from provided block number. If the GetEvents.Options#fromBlock option is missing it looks for a contract's defined property -[_deployedAtBlockNumber](EthereumBridge.md#_deployedatblocknumber). If the property is missing starts searching +[_deployedAtBlockNumber](BaseL2BitcoinDepositor.md#_deployedatblocknumber). If the property is missing starts searching from block `0`. #### Parameters @@ -269,7 +269,7 @@ ___ #### Defined in -[src/lib/ethereum/tbtc-vault.ts:89](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/tbtc-vault.ts#L89) +[src/lib/ethereum/tbtc-vault.ts:90](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/tbtc-vault.ts#L90) ___ @@ -296,7 +296,7 @@ TBTCVault.getOptimisticMintingCancelledEvents #### Defined in -[src/lib/ethereum/tbtc-vault.ts:267](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/tbtc-vault.ts#L267) +[src/lib/ethereum/tbtc-vault.ts:268](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/tbtc-vault.ts#L268) ___ @@ -323,7 +323,7 @@ TBTCVault.getOptimisticMintingFinalizedEvents #### Defined in -[src/lib/ethereum/tbtc-vault.ts:294](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/tbtc-vault.ts#L294) +[src/lib/ethereum/tbtc-vault.ts:295](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/tbtc-vault.ts#L295) ___ @@ -350,7 +350,7 @@ TBTCVault.getOptimisticMintingRequestedEvents #### Defined in -[src/lib/ethereum/tbtc-vault.ts:234](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/tbtc-vault.ts#L234) +[src/lib/ethereum/tbtc-vault.ts:235](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/tbtc-vault.ts#L235) ___ @@ -376,7 +376,7 @@ ___ #### Defined in -[src/lib/ethereum/tbtc-vault.ts:113](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/tbtc-vault.ts#L113) +[src/lib/ethereum/tbtc-vault.ts:114](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/tbtc-vault.ts#L114) ___ @@ -402,7 +402,7 @@ ___ #### Defined in -[src/lib/ethereum/tbtc-vault.ts:103](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/tbtc-vault.ts#L103) +[src/lib/ethereum/tbtc-vault.ts:104](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/tbtc-vault.ts#L104) ___ @@ -422,7 +422,7 @@ ___ #### Defined in -[src/lib/ethereum/tbtc-vault.ts:75](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/tbtc-vault.ts#L75) +[src/lib/ethereum/tbtc-vault.ts:76](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/tbtc-vault.ts#L76) ___ @@ -449,7 +449,7 @@ ___ #### Defined in -[src/lib/ethereum/tbtc-vault.ts:198](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/tbtc-vault.ts#L198) +[src/lib/ethereum/tbtc-vault.ts:199](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/tbtc-vault.ts#L199) ___ @@ -473,7 +473,7 @@ Parsed optimistic minting request. #### Defined in -[src/lib/ethereum/tbtc-vault.ts:221](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/tbtc-vault.ts#L221) +[src/lib/ethereum/tbtc-vault.ts:222](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/tbtc-vault.ts#L222) ___ @@ -500,4 +500,4 @@ ___ #### Defined in -[src/lib/ethereum/tbtc-vault.ts:123](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/tbtc-vault.ts#L123) +[src/lib/ethereum/tbtc-vault.ts:124](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/tbtc-vault.ts#L124) diff --git a/typescript/api-reference/classes/EthereumWalletRegistry.md b/typescript/api-reference/classes/EthereumWalletRegistry.md index 8483e8f90..78e6b65d6 100644 --- a/typescript/api-reference/classes/EthereumWalletRegistry.md +++ b/typescript/api-reference/classes/EthereumWalletRegistry.md @@ -42,14 +42,14 @@ for reference. ### constructor -• **new EthereumWalletRegistry**(`config`, `deploymentType?`): [`EthereumWalletRegistry`](EthereumWalletRegistry.md) +• **new EthereumWalletRegistry**(`config`, `chainId?`): [`EthereumWalletRegistry`](EthereumWalletRegistry.md) #### Parameters | Name | Type | Default value | | :------ | :------ | :------ | | `config` | [`EthereumContractConfig`](../interfaces/EthereumContractConfig.md) | `undefined` | -| `deploymentType` | ``"local"`` \| ``"sepolia"`` \| ``"mainnet"`` | `"local"` | +| `chainId` | [`Ethereum`](../enums/Chains.Ethereum.md) | `Chains.Ethereum.Local` | #### Returns @@ -61,7 +61,7 @@ EthersContractHandle\<WalletRegistryTypechain\>.constructor #### Defined in -[src/lib/ethereum/wallet-registry.ts:32](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/wallet-registry.ts#L32) +[src/lib/ethereum/wallet-registry.ts:33](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/wallet-registry.ts#L33) ## Properties @@ -153,7 +153,7 @@ ___ #### Defined in -[src/lib/ethereum/wallet-registry.ts:59](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/wallet-registry.ts#L59) +[src/lib/ethereum/wallet-registry.ts:60](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/wallet-registry.ts#L60) ___ @@ -180,7 +180,7 @@ WalletRegistry.getDkgResultApprovedEvents #### Defined in -[src/lib/ethereum/wallet-registry.ts:125](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/wallet-registry.ts#L125) +[src/lib/ethereum/wallet-registry.ts:126](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/wallet-registry.ts#L126) ___ @@ -207,7 +207,7 @@ WalletRegistry.getDkgResultChallengedEvents #### Defined in -[src/lib/ethereum/wallet-registry.ts:150](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/wallet-registry.ts#L150) +[src/lib/ethereum/wallet-registry.ts:151](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/wallet-registry.ts#L151) ___ @@ -234,7 +234,7 @@ WalletRegistry.getDkgResultSubmittedEvents #### Defined in -[src/lib/ethereum/wallet-registry.ts:82](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/wallet-registry.ts#L82) +[src/lib/ethereum/wallet-registry.ts:83](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/wallet-registry.ts#L83) ___ @@ -245,7 +245,7 @@ ___ Get events emitted by the Ethereum contract. It starts searching from provided block number. If the GetEvents.Options#fromBlock option is missing it looks for a contract's defined property -[_deployedAtBlockNumber](EthereumBridge.md#_deployedatblocknumber). If the property is missing starts searching +[_deployedAtBlockNumber](BaseL2BitcoinDepositor.md#_deployedatblocknumber). If the property is missing starts searching from block `0`. #### Parameters @@ -294,4 +294,4 @@ ___ #### Defined in -[src/lib/ethereum/wallet-registry.ts:67](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/wallet-registry.ts#L67) +[src/lib/ethereum/wallet-registry.ts:68](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/ethereum/wallet-registry.ts#L68) diff --git a/typescript/api-reference/classes/TBTC.md b/typescript/api-reference/classes/TBTC.md index eaaa27565..68f119868 100644 --- a/typescript/api-reference/classes/TBTC.md +++ b/typescript/api-reference/classes/TBTC.md @@ -10,6 +10,8 @@ Entrypoint component of the tBTC v2 SDK. ### Properties +- [#crossChainContracts](TBTC.md##crosschaincontracts) +- [#crossChainContractsLoader](TBTC.md##crosschaincontractsloader) - [bitcoinClient](TBTC.md#bitcoinclient) - [deposits](TBTC.md#deposits) - [maintenance](TBTC.md#maintenance) @@ -18,6 +20,8 @@ Entrypoint component of the tBTC v2 SDK. ### Methods +- [crossChainContracts](TBTC.md#crosschaincontracts) +- [initializeCrossChain](TBTC.md#initializecrosschain) - [initializeCustom](TBTC.md#initializecustom) - [initializeEthereum](TBTC.md#initializeethereum) - [initializeMainnet](TBTC.md#initializemainnet) @@ -27,7 +31,7 @@ Entrypoint component of the tBTC v2 SDK. ### constructor -• **new TBTC**(`tbtcContracts`, `bitcoinClient`): [`TBTC`](TBTC.md) +• **new TBTC**(`tbtcContracts`, `bitcoinClient`, `crossChainContractsLoader?`): [`TBTC`](TBTC.md) #### Parameters @@ -35,6 +39,7 @@ Entrypoint component of the tBTC v2 SDK. | :------ | :------ | | `tbtcContracts` | [`TBTCContracts`](../README.md#tbtccontracts) | | `bitcoinClient` | [`BitcoinClient`](../interfaces/BitcoinClient.md) | +| `crossChainContractsLoader?` | [`CrossChainContractsLoader`](../interfaces/CrossChainContractsLoader.md) | #### Returns @@ -42,10 +47,36 @@ Entrypoint component of the tBTC v2 SDK. #### Defined in -[src/services/tbtc.ts:40](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/tbtc.ts#L40) +[src/services/tbtc.ts:59](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/tbtc.ts#L59) ## Properties +### #crossChainContracts + +• `Private` `Readonly` **#crossChainContracts**: `Map`\<``"Base"``, [`CrossChainContracts`](../README.md#crosschaincontracts)\> + +Mapping of cross-chain contracts for different supported L2 chains. +Each set of cross-chain contracts must be first initialized using +the `initializeCrossChain` method. + +#### Defined in + +[src/services/tbtc.ts:57](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/tbtc.ts#L57) + +___ + +### #crossChainContractsLoader + +• `Private` `Optional` `Readonly` **#crossChainContractsLoader**: [`CrossChainContractsLoader`](../interfaces/CrossChainContractsLoader.md) + +Reference to the cross-chain contracts loader. + +#### Defined in + +[src/services/tbtc.ts:51](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/tbtc.ts#L51) + +___ + ### bitcoinClient • `Readonly` **bitcoinClient**: [`BitcoinClient`](../interfaces/BitcoinClient.md) @@ -54,7 +85,7 @@ Bitcoin client handle for low-level access. #### Defined in -[src/services/tbtc.ts:38](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/tbtc.ts#L38) +[src/services/tbtc.ts:47](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/tbtc.ts#L47) ___ @@ -66,7 +97,7 @@ Service supporting the tBTC v2 deposit flow. #### Defined in -[src/services/tbtc.ts:21](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/tbtc.ts#L21) +[src/services/tbtc.ts:30](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/tbtc.ts#L30) ___ @@ -79,7 +110,7 @@ and operators. #### Defined in -[src/services/tbtc.ts:26](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/tbtc.ts#L26) +[src/services/tbtc.ts:35](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/tbtc.ts#L35) ___ @@ -91,7 +122,7 @@ Service supporting the tBTC v2 redemption flow. #### Defined in -[src/services/tbtc.ts:30](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/tbtc.ts#L30) +[src/services/tbtc.ts:39](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/tbtc.ts#L39) ___ @@ -103,10 +134,76 @@ Handle to tBTC contracts for low-level access. #### Defined in -[src/services/tbtc.ts:34](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/tbtc.ts#L34) +[src/services/tbtc.ts:43](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/tbtc.ts#L43) ## Methods +### crossChainContracts + +▸ **crossChainContracts**(`l2ChainName`): `undefined` \| [`CrossChainContracts`](../README.md#crosschaincontracts) + +Gets cross-chain contracts for the given supported L2 chain. +The given L2 chain contracts must be first initialized using the +`initializeCrossChain` method. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `l2ChainName` | ``"Base"`` | Name of the L2 chain for which to get cross-chain contracts. | + +#### Returns + +`undefined` \| [`CrossChainContracts`](../README.md#crosschaincontracts) + +Cross-chain contracts for the given L2 chain or + undefined if not initialized. + +#### Defined in + +[src/services/tbtc.ts:233](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/tbtc.ts#L233) + +___ + +### initializeCrossChain + +▸ **initializeCrossChain**(`l2ChainName`, `l2Signer`): `Promise`\<`void`\> + +Initializes cross-chain contracts for the given L2 chain, using the +given signer. Updates the signer on subsequent calls. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `l2ChainName` | ``"Base"`` | Name of the L2 chain for which to initialize cross-chain contracts. | +| `l2Signer` | [`EthereumSigner`](../README.md#ethereumsigner) | Signer to use with the L2 chain contracts. | + +#### Returns + +`Promise`\<`void`\> + +Void promise. + +**`Throws`** + +Throws an error if: + - Cross-chain contracts loader is not available for this TBTC SDK instance, + - Chain mapping between the L1 and the given L2 chain is not defined. + +**`Dev`** + +In case this function needs to support non-EVM L2 chains that can't + use EthereumSigner as a signer type, the l2Signer parameter should + probably be turned into a union of multiple supported types or + generalized in some other way. + +#### Defined in + +[src/services/tbtc.ts:185](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/tbtc.ts#L185) + +___ + ### initializeCustom ▸ **initializeCustom**(`tbtcContracts`, `bitcoinClient`): `Promise`\<[`TBTC`](TBTC.md)\> @@ -135,13 +232,13 @@ This function is especially useful for local development as it gives #### Defined in -[src/services/tbtc.ts:117](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/tbtc.ts#L117) +[src/services/tbtc.ts:163](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/tbtc.ts#L163) ___ ### initializeEthereum -▸ **initializeEthereum**(`signer`, `ethereumNetwork`, `bitcoinNetwork`): `Promise`\<[`TBTC`](TBTC.md)\> +▸ **initializeEthereum**(`signer`, `ethereumChainId`, `bitcoinNetwork`): `Promise`\<[`TBTC`](TBTC.md)\> Initializes the tBTC v2 SDK entrypoint for the given Ethereum network and Bitcoin network. The initialized instance uses default Electrum servers to interact @@ -152,7 +249,7 @@ with Bitcoin network. | Name | Type | Description | | :------ | :------ | :------ | | `signer` | [`EthereumSigner`](../README.md#ethereumsigner) | Ethereum signer. | -| `ethereumNetwork` | [`EthereumNetwork`](../README.md#ethereumnetwork) | Ethereum network. | +| `ethereumChainId` | [`Ethereum`](../enums/Chains.Ethereum.md) | Ethereum chain ID. | | `bitcoinNetwork` | [`BitcoinNetwork`](../enums/BitcoinNetwork-1.md) | Bitcoin network. | #### Returns @@ -168,7 +265,7 @@ Throws an error if the underlying signer's Ethereum network is #### Defined in -[src/services/tbtc.ts:88](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/tbtc.ts#L88) +[src/services/tbtc.ts:122](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/tbtc.ts#L122) ___ @@ -199,7 +296,7 @@ Throws an error if the signer's Ethereum network is other than #### Defined in -[src/services/tbtc.ts:60](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/tbtc.ts#L60) +[src/services/tbtc.ts:86](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/tbtc.ts#L86) ___ @@ -230,4 +327,4 @@ Throws an error if the signer's Ethereum network is other than #### Defined in -[src/services/tbtc.ts:73](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/tbtc.ts#L73) +[src/services/tbtc.ts:103](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/services/tbtc.ts#L103) diff --git a/typescript/api-reference/enums/Chains.Base.md b/typescript/api-reference/enums/Chains.Base.md new file mode 100644 index 000000000..535d23c8f --- /dev/null +++ b/typescript/api-reference/enums/Chains.Base.md @@ -0,0 +1,30 @@ +# Enumeration: Base + +[Chains](../modules/Chains.md).Base + +## Table of contents + +### Enumeration Members + +- [Base](Chains.Base.md#base) +- [BaseSepolia](Chains.Base.md#basesepolia) + +## Enumeration Members + +### Base + +• **Base** = ``"8453"`` + +#### Defined in + +[src/lib/contracts/chain.ts:13](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/contracts/chain.ts#L13) + +___ + +### BaseSepolia + +• **BaseSepolia** = ``"84532"`` + +#### Defined in + +[src/lib/contracts/chain.ts:14](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/contracts/chain.ts#L14) diff --git a/typescript/api-reference/enums/Chains.Ethereum.md b/typescript/api-reference/enums/Chains.Ethereum.md new file mode 100644 index 000000000..88dc17e11 --- /dev/null +++ b/typescript/api-reference/enums/Chains.Ethereum.md @@ -0,0 +1,41 @@ +# Enumeration: Ethereum + +[Chains](../modules/Chains.md).Ethereum + +## Table of contents + +### Enumeration Members + +- [Local](Chains.Ethereum.md#local) +- [Mainnet](Chains.Ethereum.md#mainnet) +- [Sepolia](Chains.Ethereum.md#sepolia) + +## Enumeration Members + +### Local + +• **Local** = ``"1101"`` + +#### Defined in + +[src/lib/contracts/chain.ts:9](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/contracts/chain.ts#L9) + +___ + +### Mainnet + +• **Mainnet** = ``"1"`` + +#### Defined in + +[src/lib/contracts/chain.ts:7](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/contracts/chain.ts#L7) + +___ + +### Sepolia + +• **Sepolia** = ``"11155111"`` + +#### Defined in + +[src/lib/contracts/chain.ts:8](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/contracts/chain.ts#L8) diff --git a/typescript/api-reference/interfaces/CrossChainContractsLoader.md b/typescript/api-reference/interfaces/CrossChainContractsLoader.md new file mode 100644 index 000000000..4fea39457 --- /dev/null +++ b/typescript/api-reference/interfaces/CrossChainContractsLoader.md @@ -0,0 +1,58 @@ +# Interface: CrossChainContractsLoader + +Interface for loading TBTC cross-chain contracts for a specific L2 chain. +It should be implemented for each supported L1 chain tBTC ledger is deployed +on. + +## Table of contents + +### Properties + +- [loadChainMapping](CrossChainContractsLoader.md#loadchainmapping) +- [loadL1Contracts](CrossChainContractsLoader.md#loadl1contracts) + +## Properties + +### loadChainMapping + +• **loadChainMapping**: () => `undefined` \| [`ChainMapping`](../README.md#chainmapping) + +#### Type declaration + +▸ (): `undefined` \| [`ChainMapping`](../README.md#chainmapping) + +Loads the chain mapping based on underlying L1 chain. + +##### Returns + +`undefined` \| [`ChainMapping`](../README.md#chainmapping) + +#### Defined in + +[src/lib/contracts/cross-chain.ts:38](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/contracts/cross-chain.ts#L38) + +___ + +### loadL1Contracts + +• **loadL1Contracts**: (`l2ChainName`: ``"Base"``) => `Promise`\<[`L1CrossChainContracts`](../README.md#l1crosschaincontracts)\> + +#### Type declaration + +▸ (`l2ChainName`): `Promise`\<[`L1CrossChainContracts`](../README.md#l1crosschaincontracts)\> + +Loads L1-specific TBTC cross-chain contracts for the given L2 chain. + +##### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `l2ChainName` | ``"Base"`` | Name of the L2 chain for which to load L1 contracts. | + +##### Returns + +`Promise`\<[`L1CrossChainContracts`](../README.md#l1crosschaincontracts)\> + +#### Defined in + +[src/lib/contracts/cross-chain.ts:43](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/contracts/cross-chain.ts#L43) diff --git a/typescript/api-reference/interfaces/CrossChainExtraDataEncoder.md b/typescript/api-reference/interfaces/CrossChainExtraDataEncoder.md new file mode 100644 index 000000000..469a518e7 --- /dev/null +++ b/typescript/api-reference/interfaces/CrossChainExtraDataEncoder.md @@ -0,0 +1,63 @@ +# Interface: CrossChainExtraDataEncoder + +Interface for encoding and decoding the extra data included in the +cross-chain deposit script. + +## Implemented by + +- [`EthereumCrossChainExtraDataEncoder`](../classes/EthereumCrossChainExtraDataEncoder.md) + +## Table of contents + +### Methods + +- [decodeDepositOwner](CrossChainExtraDataEncoder.md#decodedepositowner) +- [encodeDepositOwner](CrossChainExtraDataEncoder.md#encodedepositowner) + +## Methods + +### decodeDepositOwner + +▸ **decodeDepositOwner**(`extraData`): [`ChainIdentifier`](ChainIdentifier.md) + +Decodes the extra data into the deposit owner identifier. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `extraData` | [`Hex`](../classes/Hex.md) | Extra data to decode. | + +#### Returns + +[`ChainIdentifier`](ChainIdentifier.md) + +Identifier of the deposit owner. + +#### Defined in + +[src/lib/contracts/cross-chain.ts:165](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/contracts/cross-chain.ts#L165) + +___ + +### encodeDepositOwner + +▸ **encodeDepositOwner**(`depositOwner`): [`Hex`](../classes/Hex.md) + +Encodes the given deposit owner identifier into the extra data. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `depositOwner` | [`ChainIdentifier`](ChainIdentifier.md) | Identifier of the deposit owner to encode. For cross-chain deposits, the deposit owner is typically an identifier on the L2 chain. | + +#### Returns + +[`Hex`](../classes/Hex.md) + +Encoded extra data. + +#### Defined in + +[src/lib/contracts/cross-chain.ts:158](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/contracts/cross-chain.ts#L158) diff --git a/typescript/api-reference/interfaces/DepositorProxy.md b/typescript/api-reference/interfaces/DepositorProxy.md index 9eba5ed1c..aa694798b 100644 --- a/typescript/api-reference/interfaces/DepositorProxy.md +++ b/typescript/api-reference/interfaces/DepositorProxy.md @@ -10,6 +10,7 @@ optional 32-byte extra data field of the deposit script). ## Implemented by +- [`CrossChainDepositor`](../classes/CrossChainDepositor.md) - [`EthereumDepositorProxy`](../classes/EthereumDepositorProxy.md) ## Table of contents diff --git a/typescript/api-reference/interfaces/L1BitcoinDepositor.md b/typescript/api-reference/interfaces/L1BitcoinDepositor.md new file mode 100644 index 000000000..3f0f01b86 --- /dev/null +++ b/typescript/api-reference/interfaces/L1BitcoinDepositor.md @@ -0,0 +1,76 @@ +# Interface: L1BitcoinDepositor + +Interface for communication with the L1BitcoinDepositor on-chain contract +specific to the given L2 chain, deployed on the L1 chain. + +## Implemented by + +- [`EthereumL1BitcoinDepositor`](../classes/EthereumL1BitcoinDepositor.md) + +## Table of contents + +### Methods + +- [extraDataEncoder](L1BitcoinDepositor.md#extradataencoder) +- [getChainIdentifier](L1BitcoinDepositor.md#getchainidentifier) +- [initializeDeposit](L1BitcoinDepositor.md#initializedeposit) + +## Methods + +### extraDataEncoder + +▸ **extraDataEncoder**(): [`CrossChainExtraDataEncoder`](CrossChainExtraDataEncoder.md) + +#### Returns + +[`CrossChainExtraDataEncoder`](CrossChainExtraDataEncoder.md) + +Extra data encoder for this contract. The encoder is used to +encode and decode the extra data included in the cross-chain deposit script. + +#### Defined in + +[src/lib/contracts/cross-chain.ts:126](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/contracts/cross-chain.ts#L126) + +___ + +### getChainIdentifier + +▸ **getChainIdentifier**(): [`ChainIdentifier`](ChainIdentifier.md) + +Gets the chain-specific identifier of this contract. + +#### Returns + +[`ChainIdentifier`](ChainIdentifier.md) + +#### Defined in + +[src/lib/contracts/cross-chain.ts:120](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/contracts/cross-chain.ts#L120) + +___ + +### initializeDeposit + +▸ **initializeDeposit**(`depositTx`, `depositOutputIndex`, `deposit`, `vault?`): `Promise`\<[`Hex`](../classes/Hex.md)\> + +Initializes the cross-chain deposit directly on the given L1 chain. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `depositTx` | [`BitcoinRawTxVectors`](BitcoinRawTxVectors.md) | Deposit transaction data | +| `depositOutputIndex` | `number` | Index of the deposit transaction output that funds the revealed deposit | +| `deposit` | [`DepositReceipt`](DepositReceipt.md) | Data of the revealed deposit | +| `vault?` | [`ChainIdentifier`](ChainIdentifier.md) | Optional parameter denoting the vault the given deposit should be routed to | + +#### Returns + +`Promise`\<[`Hex`](../classes/Hex.md)\> + +Transaction hash of the reveal deposit transaction. + +#### Defined in + +[src/lib/contracts/cross-chain.ts:138](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/contracts/cross-chain.ts#L138) diff --git a/typescript/api-reference/interfaces/L2BitcoinDepositor.md b/typescript/api-reference/interfaces/L2BitcoinDepositor.md new file mode 100644 index 000000000..412f090d3 --- /dev/null +++ b/typescript/api-reference/interfaces/L2BitcoinDepositor.md @@ -0,0 +1,120 @@ +# Interface: L2BitcoinDepositor + +Interface for communication with the L2BitcoinDepositor on-chain contract +deployed on the given L2 chain. + +## Implemented by + +- [`BaseL2BitcoinDepositor`](../classes/BaseL2BitcoinDepositor.md) + +## Table of contents + +### Methods + +- [extraDataEncoder](L2BitcoinDepositor.md#extradataencoder) +- [getChainIdentifier](L2BitcoinDepositor.md#getchainidentifier) +- [getDepositOwner](L2BitcoinDepositor.md#getdepositowner) +- [initializeDeposit](L2BitcoinDepositor.md#initializedeposit) +- [setDepositOwner](L2BitcoinDepositor.md#setdepositowner) + +## Methods + +### extraDataEncoder + +▸ **extraDataEncoder**(): [`CrossChainExtraDataEncoder`](CrossChainExtraDataEncoder.md) + +#### Returns + +[`CrossChainExtraDataEncoder`](CrossChainExtraDataEncoder.md) + +Extra data encoder for this contract. The encoder is used to +encode and decode the extra data included in the cross-chain deposit script. + +#### Defined in + +[src/lib/contracts/cross-chain.ts:92](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/contracts/cross-chain.ts#L92) + +___ + +### getChainIdentifier + +▸ **getChainIdentifier**(): [`ChainIdentifier`](ChainIdentifier.md) + +Gets the chain-specific identifier of this contract. + +#### Returns + +[`ChainIdentifier`](ChainIdentifier.md) + +#### Defined in + +[src/lib/contracts/cross-chain.ts:72](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/contracts/cross-chain.ts#L72) + +___ + +### getDepositOwner + +▸ **getDepositOwner**(): `undefined` \| [`ChainIdentifier`](ChainIdentifier.md) + +Gets the identifier that should be used as the owner of the deposits +issued by this contract. + +#### Returns + +`undefined` \| [`ChainIdentifier`](ChainIdentifier.md) + +The identifier of the deposit owner or undefined if not set. + +#### Defined in + +[src/lib/contracts/cross-chain.ts:79](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/contracts/cross-chain.ts#L79) + +___ + +### initializeDeposit + +▸ **initializeDeposit**(`depositTx`, `depositOutputIndex`, `deposit`, `vault?`): `Promise`\<[`Hex`](../classes/Hex.md)\> + +Initializes the cross-chain deposit indirectly through the given L2 chain. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `depositTx` | [`BitcoinRawTxVectors`](BitcoinRawTxVectors.md) | Deposit transaction data | +| `depositOutputIndex` | `number` | Index of the deposit transaction output that funds the revealed deposit | +| `deposit` | [`DepositReceipt`](DepositReceipt.md) | Data of the revealed deposit | +| `vault?` | [`ChainIdentifier`](ChainIdentifier.md) | Optional parameter denoting the vault the given deposit should be routed to | + +#### Returns + +`Promise`\<[`Hex`](../classes/Hex.md)\> + +Transaction hash of the reveal deposit transaction. + +#### Defined in + +[src/lib/contracts/cross-chain.ts:104](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/contracts/cross-chain.ts#L104) + +___ + +### setDepositOwner + +▸ **setDepositOwner**(`depositOwner`): `void` + +Sets the identifier that should be used as the owner of the deposits +issued by this contract. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `depositOwner` | [`ChainIdentifier`](ChainIdentifier.md) | Identifier of the deposit owner or undefined to clear. | + +#### Returns + +`void` + +#### Defined in + +[src/lib/contracts/cross-chain.ts:86](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/contracts/cross-chain.ts#L86) diff --git a/typescript/api-reference/interfaces/L2TBTCToken.md b/typescript/api-reference/interfaces/L2TBTCToken.md new file mode 100644 index 000000000..29db500d8 --- /dev/null +++ b/typescript/api-reference/interfaces/L2TBTCToken.md @@ -0,0 +1,55 @@ +# Interface: L2TBTCToken + +Interface for communication with the on-chain contract of the given +canonical L2 tBTC token. + +## Implemented by + +- [`BaseL2TBTCToken`](../classes/BaseL2TBTCToken.md) + +## Table of contents + +### Methods + +- [balanceOf](L2TBTCToken.md#balanceof) +- [getChainIdentifier](L2TBTCToken.md#getchainidentifier) + +## Methods + +### balanceOf + +▸ **balanceOf**(`identifier`): `Promise`\<`BigNumber`\> + +Returns the balance of the given identifier. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `identifier` | [`ChainIdentifier`](ChainIdentifier.md) | Identifier of the account to get the balance for. | + +#### Returns + +`Promise`\<`BigNumber`\> + +The balance of the given identifier in 1e18 precision. + +#### Defined in + +[src/lib/contracts/cross-chain.ts:61](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/contracts/cross-chain.ts#L61) + +___ + +### getChainIdentifier + +▸ **getChainIdentifier**(): [`ChainIdentifier`](ChainIdentifier.md) + +Gets the chain-specific identifier of this contract. + +#### Returns + +[`ChainIdentifier`](ChainIdentifier.md) + +#### Defined in + +[src/lib/contracts/cross-chain.ts:54](https://github.com/keep-network/tbtc-v2/blob/main/typescript/src/lib/contracts/cross-chain.ts#L54) diff --git a/typescript/api-reference/modules/Chains.md b/typescript/api-reference/modules/Chains.md new file mode 100644 index 000000000..c9e37e04b --- /dev/null +++ b/typescript/api-reference/modules/Chains.md @@ -0,0 +1,10 @@ +# Namespace: Chains + +Chains supported by tBTC v2 contracts. + +## Table of contents + +### Enumerations + +- [Base](../enums/Chains.Base.md) +- [Ethereum](../enums/Chains.Ethereum.md) diff --git a/typescript/package.json b/typescript/package.json index fb08b8f5a..17c2cb3af 100644 --- a/typescript/package.json +++ b/typescript/package.json @@ -22,7 +22,7 @@ "typechain/" ], "config": { - "contracts": "./node_modules/@keep-network/ecdsa/artifacts/WalletRegistry.json ./node_modules/@keep-network/tbtc-v2/artifacts/{Bridge,TBTCVault,TBTC}.json" + "contracts": "./node_modules/@keep-network/ecdsa/artifacts/WalletRegistry.json ./node_modules/@keep-network/tbtc-v2/artifacts/{Bridge,TBTCVault,TBTC}.json ./node_modules/@keep-network/tbtc-v2/build/contracts/l2/L1BitcoinDepositor.sol/L1BitcoinDepositor.json ./node_modules/@keep-network/tbtc-v2/build/contracts/l2/L2BitcoinDepositor.sol/L2BitcoinDepositor.json ./node_modules/@keep-network/tbtc-v2/build/contracts/l2/L2TBTC.sol/L2TBTC.json" }, "dependencies": { "@bitcoinerlab/secp256k1": "^1.0.5", diff --git a/typescript/src/index.ts b/typescript/src/index.ts index 2ee4bcafd..e922cbdb8 100644 --- a/typescript/src/index.ts +++ b/typescript/src/index.ts @@ -1,4 +1,5 @@ // Export shared library modules. +export * from "./lib/base" export * from "./lib/bitcoin" export * from "./lib/contracts" export * from "./lib/electrum" diff --git a/typescript/src/lib/base/artifacts/base/BaseTBTC.json b/typescript/src/lib/base/artifacts/base/BaseTBTC.json new file mode 100644 index 000000000..8e834c472 --- /dev/null +++ b/typescript/src/lib/base/artifacts/base/BaseTBTC.json @@ -0,0 +1,863 @@ +{ + "address": "0x236aa50979D5f3De3Bd1Eeb40E81137F22ab794b", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "guardian", + "type": "address" + } + ], + "name": "GuardianAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "guardian", + "type": "address" + } + ], + "name": "GuardianRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "minter", + "type": "address" + } + ], + "name": "MinterAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "minter", + "type": "address" + } + ], + "name": "MinterRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "guardian", + "type": "address" + } + ], + "name": "addGuardian", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "minter", + "type": "address" + } + ], + "name": "addMinter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burnFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getGuardians", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMinters", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "guardians", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_name", + "type": "string" + }, + { + "internalType": "string", + "name": "_symbol", + "type": "string" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isGuardian", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isMinter", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "minters", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "recoverERC20", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC721Upgradeable", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "recoverERC721", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "guardian", + "type": "address" + } + ], + "name": "removeGuardian", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "minter", + "type": "address" + } + ], + "name": "removeMinter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x85f05786bb1d38013714332804139352f16aa2751d05b4517ed2f7e67d683a6a", + "receipt": { + "to": null, + "from": "0x123694886DBf5Ac94DDA07135349534536D14cAf", + "contractAddress": "0x236aa50979D5f3De3Bd1Eeb40E81137F22ab794b", + "transactionIndex": 1, + "gasUsed": "754031", + "logsBloom": "0x00000000000000000000400000000000400000000002000000800000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000002800001000000000000000080000000000000000000020000000000000000000800000000800000000000000000400000400000000000000000000000000000000000000000000080000000000000800000000000000000000000000000000400000000000000000000000000000000000000000020000000040000000000440000000000000400000000000000000020000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x676b27fe07778a4d23b12ebcda86efb3396f4727c4f22fecfc534f22ad0382f2", + "transactionHash": "0x85f05786bb1d38013714332804139352f16aa2751d05b4517ed2f7e67d683a6a", + "logs": [ + { + "transactionIndex": 1, + "blockNumber": 2126367, + "transactionHash": "0x85f05786bb1d38013714332804139352f16aa2751d05b4517ed2f7e67d683a6a", + "address": "0x236aa50979D5f3De3Bd1Eeb40E81137F22ab794b", + "topics": [ + "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", + "0x00000000000000000000000041c9b5639e3f2f6c61e9b78b2c6ff3746e79d91a" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0x676b27fe07778a4d23b12ebcda86efb3396f4727c4f22fecfc534f22ad0382f2" + }, + { + "transactionIndex": 1, + "blockNumber": 2126367, + "transactionHash": "0x85f05786bb1d38013714332804139352f16aa2751d05b4517ed2f7e67d683a6a", + "address": "0x236aa50979D5f3De3Bd1Eeb40E81137F22ab794b", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000123694886dbf5ac94dda07135349534536d14caf" + ], + "data": "0x", + "logIndex": 1, + "blockHash": "0x676b27fe07778a4d23b12ebcda86efb3396f4727c4f22fecfc534f22ad0382f2" + }, + { + "transactionIndex": 1, + "blockNumber": 2126367, + "transactionHash": "0x85f05786bb1d38013714332804139352f16aa2751d05b4517ed2f7e67d683a6a", + "address": "0x236aa50979D5f3De3Bd1Eeb40E81137F22ab794b", + "topics": [ + "0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 2, + "blockHash": "0x676b27fe07778a4d23b12ebcda86efb3396f4727c4f22fecfc534f22ad0382f2" + }, + { + "transactionIndex": 1, + "blockNumber": 2126367, + "transactionHash": "0x85f05786bb1d38013714332804139352f16aa2751d05b4517ed2f7e67d683a6a", + "address": "0x236aa50979D5f3De3Bd1Eeb40E81137F22ab794b", + "topics": [ + "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" + ], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001293a54e160d1cd7075487898d65266081a15458", + "logIndex": 3, + "blockHash": "0x676b27fe07778a4d23b12ebcda86efb3396f4727c4f22fecfc534f22ad0382f2" + } + ], + "blockNumber": 2126367, + "cumulativeGasUsed": "818044", + "status": 1, + "byzantium": true + }, + "numDeployments": 1, + "implementation": "0x41C9b5639E3F2F6C61e9B78b2c6FF3746E79d91A", + "devdoc": "Contract deployed as upgradable proxy" +} diff --git a/typescript/src/lib/base/artifacts/baseSepolia/BaseL2BitcoinDepositor.json b/typescript/src/lib/base/artifacts/baseSepolia/BaseL2BitcoinDepositor.json new file mode 100644 index 000000000..6ed5a21d0 --- /dev/null +++ b/typescript/src/lib/base/artifacts/baseSepolia/BaseL2BitcoinDepositor.json @@ -0,0 +1,429 @@ +{ + "address": "0x04BE8F183572ec802aD26756F3E9398098700E76", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "components": [ + { + "internalType": "bytes4", + "name": "version", + "type": "bytes4" + }, + { + "internalType": "bytes", + "name": "inputVector", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "outputVector", + "type": "bytes" + }, + { + "internalType": "bytes4", + "name": "locktime", + "type": "bytes4" + } + ], + "indexed": false, + "internalType": "struct IBridgeTypes.BitcoinTxInfo", + "name": "fundingTx", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "fundingOutputIndex", + "type": "uint32" + }, + { + "internalType": "bytes8", + "name": "blindingFactor", + "type": "bytes8" + }, + { + "internalType": "bytes20", + "name": "walletPubKeyHash", + "type": "bytes20" + }, + { + "internalType": "bytes20", + "name": "refundPubKeyHash", + "type": "bytes20" + }, + { + "internalType": "bytes4", + "name": "refundLocktime", + "type": "bytes4" + }, + { + "internalType": "address", + "name": "vault", + "type": "address" + } + ], + "indexed": false, + "internalType": "struct IBridgeTypes.DepositRevealInfo", + "name": "reveal", + "type": "tuple" + }, + { + "indexed": true, + "internalType": "address", + "name": "l2DepositOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "l2Sender", + "type": "address" + } + ], + "name": "DepositInitialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l1BitcoinDepositor", + "type": "address" + } + ], + "name": "attachL1BitcoinDepositor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_wormholeRelayer", + "type": "address" + }, + { + "internalType": "address", + "name": "_l2WormholeGateway", + "type": "address" + }, + { + "internalType": "uint16", + "name": "_l1ChainId", + "type": "uint16" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes4", + "name": "version", + "type": "bytes4" + }, + { + "internalType": "bytes", + "name": "inputVector", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "outputVector", + "type": "bytes" + }, + { + "internalType": "bytes4", + "name": "locktime", + "type": "bytes4" + } + ], + "internalType": "struct IBridgeTypes.BitcoinTxInfo", + "name": "fundingTx", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "fundingOutputIndex", + "type": "uint32" + }, + { + "internalType": "bytes8", + "name": "blindingFactor", + "type": "bytes8" + }, + { + "internalType": "bytes20", + "name": "walletPubKeyHash", + "type": "bytes20" + }, + { + "internalType": "bytes20", + "name": "refundPubKeyHash", + "type": "bytes20" + }, + { + "internalType": "bytes4", + "name": "refundLocktime", + "type": "bytes4" + }, + { + "internalType": "address", + "name": "vault", + "type": "address" + } + ], + "internalType": "struct IBridgeTypes.DepositRevealInfo", + "name": "reveal", + "type": "tuple" + }, + { + "internalType": "address", + "name": "l2DepositOwner", + "type": "address" + } + ], + "name": "initializeDeposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "l1BitcoinDepositor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l1ChainId", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l2WormholeGateway", + "outputs": [ + { + "internalType": "contract IL2WormholeGateway", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + }, + { + "internalType": "bytes[]", + "name": "additionalVaas", + "type": "bytes[]" + }, + { + "internalType": "bytes32", + "name": "sourceAddress", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "sourceChain", + "type": "uint16" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "receiveWormholeMessages", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "wormholeRelayer", + "outputs": [ + { + "internalType": "contract IWormholeRelayer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0xaeb9ee6679e0f96108788abffa9ed78c943c09565686dfdb826378e9bd1487df", + "receipt": { + "to": null, + "from": "0x68ad60CC5e8f3B7cC53beaB321cf0e6036962dBc", + "contractAddress": "0x04BE8F183572ec802aD26756F3E9398098700E76", + "transactionIndex": 2, + "gasUsed": "704802", + "logsBloom": "0x00000000000000000000000000000000400000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000202000001000000000000000000000000000000000000020000000000000000000800000000800000000000000000000000400002000200000000000000000000000000000000000080000000000000800080000000000000000000000000000400000000000100000000000000000000000000000020000000000000000020040000000008000400000000000000000020000000000000000000080000000000000000000000000000000000000000400000", + "blockHash": "0xcb1f5aa73f2f63d359224b51e7abf66a431e3420daa6940b72a3a58dd5a00c85", + "transactionHash": "0xaeb9ee6679e0f96108788abffa9ed78c943c09565686dfdb826378e9bd1487df", + "logs": [ + { + "transactionIndex": 2, + "blockNumber": 7063584, + "transactionHash": "0xaeb9ee6679e0f96108788abffa9ed78c943c09565686dfdb826378e9bd1487df", + "address": "0x04BE8F183572ec802aD26756F3E9398098700E76", + "topics": [ + "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", + "0x0000000000000000000000001ecd87c8d510a7390a561ae0ac54fbe7e5125bcf" + ], + "data": "0x", + "logIndex": 1, + "blockHash": "0xcb1f5aa73f2f63d359224b51e7abf66a431e3420daa6940b72a3a58dd5a00c85" + }, + { + "transactionIndex": 2, + "blockNumber": 7063584, + "transactionHash": "0xaeb9ee6679e0f96108788abffa9ed78c943c09565686dfdb826378e9bd1487df", + "address": "0x04BE8F183572ec802aD26756F3E9398098700E76", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000068ad60cc5e8f3b7cc53beab321cf0e6036962dbc" + ], + "data": "0x", + "logIndex": 2, + "blockHash": "0xcb1f5aa73f2f63d359224b51e7abf66a431e3420daa6940b72a3a58dd5a00c85" + }, + { + "transactionIndex": 2, + "blockNumber": 7063584, + "transactionHash": "0xaeb9ee6679e0f96108788abffa9ed78c943c09565686dfdb826378e9bd1487df", + "address": "0x04BE8F183572ec802aD26756F3E9398098700E76", + "topics": [ + "0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 3, + "blockHash": "0xcb1f5aa73f2f63d359224b51e7abf66a431e3420daa6940b72a3a58dd5a00c85" + }, + { + "transactionIndex": 2, + "blockNumber": 7063584, + "transactionHash": "0xaeb9ee6679e0f96108788abffa9ed78c943c09565686dfdb826378e9bd1487df", + "address": "0x04BE8F183572ec802aD26756F3E9398098700E76", + "topics": [ + "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b2f6c5b73239c39360ee0ea95047565dab13e3c7", + "logIndex": 4, + "blockHash": "0xcb1f5aa73f2f63d359224b51e7abf66a431e3420daa6940b72a3a58dd5a00c85" + } + ], + "blockNumber": 7063584, + "cumulativeGasUsed": "804788", + "status": 1, + "byzantium": true + }, + "numDeployments": 1, + "implementation": "0x1Ecd87C8D510A7390a561AE0Ac54FBe7e5125BcF", + "devdoc": "Contract deployed as upgradable proxy" +} diff --git a/typescript/src/lib/base/artifacts/baseSepolia/BaseTBTC.json b/typescript/src/lib/base/artifacts/baseSepolia/BaseTBTC.json new file mode 100644 index 000000000..0d0d151ae --- /dev/null +++ b/typescript/src/lib/base/artifacts/baseSepolia/BaseTBTC.json @@ -0,0 +1,863 @@ +{ + "address": "0xb8f31A249bcb45267d06b9E51252c4793B917Cd0", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "guardian", + "type": "address" + } + ], + "name": "GuardianAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "guardian", + "type": "address" + } + ], + "name": "GuardianRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "minter", + "type": "address" + } + ], + "name": "MinterAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "minter", + "type": "address" + } + ], + "name": "MinterRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "guardian", + "type": "address" + } + ], + "name": "addGuardian", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "minter", + "type": "address" + } + ], + "name": "addMinter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burnFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getGuardians", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMinters", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "guardians", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_name", + "type": "string" + }, + { + "internalType": "string", + "name": "_symbol", + "type": "string" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isGuardian", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isMinter", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "minters", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "recoverERC20", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC721Upgradeable", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "recoverERC721", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "guardian", + "type": "address" + } + ], + "name": "removeGuardian", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "minter", + "type": "address" + } + ], + "name": "removeMinter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0xab8316fb27299ddc835c0755166c57dcb404e7e2745291646d100006d84602fe", + "receipt": { + "to": null, + "from": "0x68ad60CC5e8f3B7cC53beaB321cf0e6036962dBc", + "contractAddress": "0xb8f31A249bcb45267d06b9E51252c4793B917Cd0", + "transactionIndex": 4, + "gasUsed": "754291", + "logsBloom": "0x00000000000000008000000000000000400000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000202000001000000000000000000000000000000000400020000000000000000000800000000800000000000000001000000400000000200000000000000000002000000000000000080000000000000800000000000000000000000000000000400000000000000000000000000000000000000000020000000000000200020040000000000000400000000000000000020000000000000000000000000000000000000000000000000000000000040000000", + "blockHash": "0x3c3159a5412f976db6df1bd29994d90b54a135ce117fa722f9ae5be5a3ef7cc4", + "transactionHash": "0xab8316fb27299ddc835c0755166c57dcb404e7e2745291646d100006d84602fe", + "logs": [ + { + "transactionIndex": 4, + "blockNumber": 5774426, + "transactionHash": "0xab8316fb27299ddc835c0755166c57dcb404e7e2745291646d100006d84602fe", + "address": "0xb8f31A249bcb45267d06b9E51252c4793B917Cd0", + "topics": [ + "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", + "0x0000000000000000000000001e9e56acdb2987dce23eb6e751c22d4f89296a06" + ], + "data": "0x", + "logIndex": 2, + "blockHash": "0x3c3159a5412f976db6df1bd29994d90b54a135ce117fa722f9ae5be5a3ef7cc4" + }, + { + "transactionIndex": 4, + "blockNumber": 5774426, + "transactionHash": "0xab8316fb27299ddc835c0755166c57dcb404e7e2745291646d100006d84602fe", + "address": "0xb8f31A249bcb45267d06b9E51252c4793B917Cd0", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000068ad60cc5e8f3b7cc53beab321cf0e6036962dbc" + ], + "data": "0x", + "logIndex": 3, + "blockHash": "0x3c3159a5412f976db6df1bd29994d90b54a135ce117fa722f9ae5be5a3ef7cc4" + }, + { + "transactionIndex": 4, + "blockNumber": 5774426, + "transactionHash": "0xab8316fb27299ddc835c0755166c57dcb404e7e2745291646d100006d84602fe", + "address": "0xb8f31A249bcb45267d06b9E51252c4793B917Cd0", + "topics": [ + "0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 4, + "blockHash": "0x3c3159a5412f976db6df1bd29994d90b54a135ce117fa722f9ae5be5a3ef7cc4" + }, + { + "transactionIndex": 4, + "blockNumber": 5774426, + "transactionHash": "0xab8316fb27299ddc835c0755166c57dcb404e7e2745291646d100006d84602fe", + "address": "0xb8f31A249bcb45267d06b9E51252c4793B917Cd0", + "topics": [ + "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b2f6c5b73239c39360ee0ea95047565dab13e3c7", + "logIndex": 5, + "blockHash": "0x3c3159a5412f976db6df1bd29994d90b54a135ce117fa722f9ae5be5a3ef7cc4" + } + ], + "blockNumber": 5774426, + "cumulativeGasUsed": "1688352", + "status": 1, + "byzantium": true + }, + "numDeployments": 1, + "implementation": "0x1e9E56Acdb2987DCe23Eb6E751C22d4f89296a06", + "devdoc": "Contract deployed as upgradable proxy" +} diff --git a/typescript/src/lib/base/index.ts b/typescript/src/lib/base/index.ts new file mode 100644 index 000000000..c34cab9fd --- /dev/null +++ b/typescript/src/lib/base/index.ts @@ -0,0 +1,45 @@ +import { + chainIdFromSigner, + ethereumAddressFromSigner, + EthereumSigner, +} from "../ethereum" +import { BaseL2BitcoinDepositor } from "./l2-bitcoin-depositor" +import { BaseL2TBTCToken } from "./l2-tbtc-token" +import { Chains, L2CrossChainContracts } from "../contracts" + +export * from "./l2-bitcoin-depositor" +export * from "./l2-tbtc-token" + +/** + * Loads Base implementation of tBTC cross-chain contracts for the given Base + * chain ID and attaches the given signer there. + * @param signer Signer that should be attached to the contracts. + * @param chainId Base chain ID. + * @returns Handle to the contracts. + * @throws Throws an error if the signer's Base chain ID is other than + * the one used to load contracts. + */ +export async function loadBaseCrossChainContracts( + signer: EthereumSigner, + chainId: Chains.Base +): Promise { + const signerChainId = await chainIdFromSigner(signer) + if (signerChainId !== chainId) { + throw new Error( + "Signer uses different chain than Base cross-chain contracts" + ) + } + + const l2BitcoinDepositor = new BaseL2BitcoinDepositor( + { signerOrProvider: signer }, + chainId + ) + l2BitcoinDepositor.setDepositOwner(await ethereumAddressFromSigner(signer)) + + const l2TbtcToken = new BaseL2TBTCToken({ signerOrProvider: signer }, chainId) + + return { + l2BitcoinDepositor, + l2TbtcToken, + } +} diff --git a/typescript/src/lib/base/l2-bitcoin-depositor.ts b/typescript/src/lib/base/l2-bitcoin-depositor.ts new file mode 100644 index 000000000..2419ce0bc --- /dev/null +++ b/typescript/src/lib/base/l2-bitcoin-depositor.ts @@ -0,0 +1,122 @@ +import { + EthersContractConfig, + EthersContractDeployment, + EthersContractHandle, +} from "../ethereum/adapter" +import { L2BitcoinDepositor as L2BitcoinDepositorTypechain } from "../../../typechain/L2BitcoinDepositor" +import { + ChainIdentifier, + Chains, + CrossChainExtraDataEncoder, + DepositReceipt, + L2BitcoinDepositor, +} from "../contracts" +import { + EthereumAddress, + EthereumCrossChainExtraDataEncoder, + packRevealDepositParameters, +} from "../ethereum" + +// TODO: Uncomment once BaseL2BitcoinDepositor is available on Base mainnet. +// import BaseL2BitcoinDepositorDeployment from "./artifacts/base/BaseL2BitcoinDepositor.json" +import BaseSepoliaL2BitcoinDepositorDeployment from "./artifacts/baseSepolia/BaseL2BitcoinDepositor.json" +import { BitcoinRawTxVectors } from "../bitcoin" +import { Hex } from "../utils" + +/** + * Implementation of the Base L2BitcoinDepositor handle. + * @see {L2BitcoinDepositor} for reference. + */ +export class BaseL2BitcoinDepositor + extends EthersContractHandle + implements L2BitcoinDepositor +{ + readonly #extraDataEncoder: CrossChainExtraDataEncoder + #depositOwner: ChainIdentifier | undefined + + constructor(config: EthersContractConfig, chainId: Chains.Base) { + let deployment: EthersContractDeployment + + switch (chainId) { + case Chains.Base.BaseSepolia: + deployment = BaseSepoliaL2BitcoinDepositorDeployment + break + case Chains.Base.Base: + // TODO: Uncomment once BaseL2BitcoinDepositor is available on Base mainnet. + // deployment = BaseL2BitcoinDepositorDeployment + // break + default: + throw new Error("Unsupported deployment type") + } + + super(config, deployment) + + this.#extraDataEncoder = new EthereumCrossChainExtraDataEncoder() + } + + // eslint-disable-next-line valid-jsdoc + /** + * @see {L2BitcoinDepositor#getChainIdentifier} + */ + getChainIdentifier(): ChainIdentifier { + return EthereumAddress.from(this._instance.address) + } + + // eslint-disable-next-line valid-jsdoc + /** + * @see {L2BitcoinDepositor#getDepositOwner} + */ + getDepositOwner(): ChainIdentifier | undefined { + return this.#depositOwner + } + + // eslint-disable-next-line valid-jsdoc + /** + * @see {L2BitcoinDepositor#setDepositOwner} + */ + setDepositOwner(depositOwner: ChainIdentifier | undefined) { + this.#depositOwner = depositOwner + } + + // eslint-disable-next-line valid-jsdoc + /** + * @see {L2BitcoinDepositor#extraDataEncoder} + */ + extraDataEncoder(): CrossChainExtraDataEncoder { + return this.#extraDataEncoder + } + + // eslint-disable-next-line valid-jsdoc + /** + * @see {L2BitcoinDepositor#initializeDeposit} + */ + async initializeDeposit( + depositTx: BitcoinRawTxVectors, + depositOutputIndex: number, + deposit: DepositReceipt, + vault?: ChainIdentifier + ): Promise { + const { fundingTx, reveal } = packRevealDepositParameters( + depositTx, + depositOutputIndex, + deposit, + vault + ) + + if (!deposit.extraData) { + throw new Error("Extra data is required") + } + + const l2DepositOwner = this.extraDataEncoder().decodeDepositOwner( + deposit.extraData + ) + + const tx = await this._instance.initializeDeposit( + fundingTx, + reveal, + `0x${l2DepositOwner.identifierHex}` + ) + + return Hex.from(tx.hash) + } +} diff --git a/typescript/src/lib/base/l2-tbtc-token.ts b/typescript/src/lib/base/l2-tbtc-token.ts new file mode 100644 index 000000000..018f4a42e --- /dev/null +++ b/typescript/src/lib/base/l2-tbtc-token.ts @@ -0,0 +1,53 @@ +import { + EthersContractConfig, + EthersContractDeployment, + EthersContractHandle, +} from "../ethereum/adapter" +import { L2TBTC as L2TBTCTypechain } from "../../../typechain/L2TBTC" +import { ChainIdentifier, Chains, L2TBTCToken } from "../contracts" +import { BigNumber } from "ethers" +import BaseL2TBTCTokenDeployment from "./artifacts/base/BaseTBTC.json" +import BaseSepoliaL2TBTCTokenDeployment from "./artifacts/baseSepolia/BaseTBTC.json" +import { EthereumAddress } from "../ethereum" + +/** + * Implementation of the Base L2TBTCToken handle. + * @see {L2TBTCToken} for reference. + */ +export class BaseL2TBTCToken + extends EthersContractHandle + implements L2TBTCToken +{ + constructor(config: EthersContractConfig, chainId: Chains.Base) { + let deployment: EthersContractDeployment + + switch (chainId) { + case Chains.Base.BaseSepolia: + deployment = BaseSepoliaL2TBTCTokenDeployment + break + case Chains.Base.Base: + deployment = BaseL2TBTCTokenDeployment + break + default: + throw new Error("Unsupported deployment type") + } + + super(config, deployment) + } + + // eslint-disable-next-line valid-jsdoc + /** + * @see {L2TBTCToken#getChainIdentifier} + */ + getChainIdentifier(): ChainIdentifier { + return EthereumAddress.from(this._instance.address) + } + + // eslint-disable-next-line valid-jsdoc + /** + * @see {L2TBTCToken#balanceOf} + */ + balanceOf(identifier: ChainIdentifier): Promise { + return this._instance.balanceOf(`0x${identifier.identifierHex}`) + } +} diff --git a/typescript/src/lib/contracts/chain.ts b/typescript/src/lib/contracts/chain.ts new file mode 100644 index 000000000..1393e3acd --- /dev/null +++ b/typescript/src/lib/contracts/chain.ts @@ -0,0 +1,49 @@ +/* eslint-disable no-unused-vars */ +/** + * Chains supported by tBTC v2 contracts. + */ +export namespace Chains { + export enum Ethereum { + Mainnet = "1", + Sepolia = "11155111", + Local = "1101", + } + + export enum Base { + Base = "8453", + BaseSepolia = "84532", + } +} + +/** + * Layer 2 chains supported by tBTC v2 contracts. + */ +export type L2Chain = Exclude + +/** + * Type representing a mapping between specific L1 and L2 chains. + */ +export type ChainMapping = { + /** + * Identifier of the Ethereum L1 chain. + */ + ethereum?: Chains.Ethereum + /** + * Identifier of the Base L2 chain. + */ + base?: Chains.Base +} + +/** + * List of chain mappings supported by tBTC v2 contracts. + */ +export const ChainMappings: ChainMapping[] = [ + { + ethereum: Chains.Ethereum.Mainnet, + base: Chains.Base.Base, + }, + { + ethereum: Chains.Ethereum.Sepolia, + base: Chains.Base.BaseSepolia, + }, +] diff --git a/typescript/src/lib/contracts/cross-chain.ts b/typescript/src/lib/contracts/cross-chain.ts new file mode 100644 index 000000000..869e9201b --- /dev/null +++ b/typescript/src/lib/contracts/cross-chain.ts @@ -0,0 +1,166 @@ +import { ChainIdentifier } from "./chain-identifier" +import { BigNumber } from "ethers" +import { ChainMapping, L2Chain } from "./chain" +import { BitcoinRawTxVectors } from "../bitcoin" +import { DepositReceipt } from "./bridge" +import { Hex } from "../utils" + +/** + * Convenience type aggregating TBTC cross-chain contracts forming a connector + * between TBTC L1 ledger chain and a specific supported L2/side-chain. + */ +export type CrossChainContracts = L2CrossChainContracts & L1CrossChainContracts + +/** + * Aggregates L2-specific TBTC cross-chain contracts. + */ +export type L2CrossChainContracts = { + l2TbtcToken: L2TBTCToken + l2BitcoinDepositor: L2BitcoinDepositor +} + +/** + * Aggregates L1-specific TBTC cross-chain contracts. + */ +export type L1CrossChainContracts = { + l1BitcoinDepositor: L1BitcoinDepositor +} + +/** + * Interface for loading TBTC cross-chain contracts for a specific L2 chain. + * It should be implemented for each supported L1 chain tBTC ledger is deployed + * on. + */ +export interface CrossChainContractsLoader { + /** + * Loads the chain mapping based on underlying L1 chain. + */ + loadChainMapping: () => ChainMapping | undefined + /** + * Loads L1-specific TBTC cross-chain contracts for the given L2 chain. + * @param l2ChainName Name of the L2 chain for which to load L1 contracts. + */ + loadL1Contracts: (l2ChainName: L2Chain) => Promise +} + +/** + * Interface for communication with the on-chain contract of the given + * canonical L2 tBTC token. + */ +export interface L2TBTCToken { + /** + * Gets the chain-specific identifier of this contract. + */ + getChainIdentifier(): ChainIdentifier + + /** + * Returns the balance of the given identifier. + * @param identifier Identifier of the account to get the balance for. + * @returns The balance of the given identifier in 1e18 precision. + */ + balanceOf(identifier: ChainIdentifier): Promise +} + +/** + * Interface for communication with the L2BitcoinDepositor on-chain contract + * deployed on the given L2 chain. + */ +export interface L2BitcoinDepositor { + /** + * Gets the chain-specific identifier of this contract. + */ + getChainIdentifier(): ChainIdentifier + + /** + * Gets the identifier that should be used as the owner of the deposits + * issued by this contract. + * @returns The identifier of the deposit owner or undefined if not set. + */ + getDepositOwner(): ChainIdentifier | undefined + + /** + * Sets the identifier that should be used as the owner of the deposits + * issued by this contract. + * @param depositOwner Identifier of the deposit owner or undefined to clear. + */ + setDepositOwner(depositOwner: ChainIdentifier): void + + /** + * @returns Extra data encoder for this contract. The encoder is used to + * encode and decode the extra data included in the cross-chain deposit script. + */ + extraDataEncoder(): CrossChainExtraDataEncoder + + /** + * Initializes the cross-chain deposit indirectly through the given L2 chain. + * @param depositTx Deposit transaction data + * @param depositOutputIndex Index of the deposit transaction output that + * funds the revealed deposit + * @param deposit Data of the revealed deposit + * @param vault Optional parameter denoting the vault the given deposit + * should be routed to + * @returns Transaction hash of the reveal deposit transaction. + */ + initializeDeposit( + depositTx: BitcoinRawTxVectors, + depositOutputIndex: number, + deposit: DepositReceipt, + vault?: ChainIdentifier + ): Promise +} + +/** + * Interface for communication with the L1BitcoinDepositor on-chain contract + * specific to the given L2 chain, deployed on the L1 chain. + */ +export interface L1BitcoinDepositor { + /** + * Gets the chain-specific identifier of this contract. + */ + getChainIdentifier(): ChainIdentifier + + /** + * @returns Extra data encoder for this contract. The encoder is used to + * encode and decode the extra data included in the cross-chain deposit script. + */ + extraDataEncoder(): CrossChainExtraDataEncoder + + /** + * Initializes the cross-chain deposit directly on the given L1 chain. + * @param depositTx Deposit transaction data + * @param depositOutputIndex Index of the deposit transaction output that + * funds the revealed deposit + * @param deposit Data of the revealed deposit + * @param vault Optional parameter denoting the vault the given deposit + * should be routed to + * @returns Transaction hash of the reveal deposit transaction. + */ + initializeDeposit( + depositTx: BitcoinRawTxVectors, + depositOutputIndex: number, + deposit: DepositReceipt, + vault?: ChainIdentifier + ): Promise +} + +/** + * Interface for encoding and decoding the extra data included in the + * cross-chain deposit script. + */ +export interface CrossChainExtraDataEncoder { + /** + * Encodes the given deposit owner identifier into the extra data. + * @param depositOwner Identifier of the deposit owner to encode. + * For cross-chain deposits, the deposit owner is typically an + * identifier on the L2 chain. + * @returns Encoded extra data. + */ + encodeDepositOwner(depositOwner: ChainIdentifier): Hex + + /** + * Decodes the extra data into the deposit owner identifier. + * @param extraData Extra data to decode. + * @returns Identifier of the deposit owner. + */ + decodeDepositOwner(extraData: Hex): ChainIdentifier +} diff --git a/typescript/src/lib/contracts/index.ts b/typescript/src/lib/contracts/index.ts index 818c4046b..af1e3ffd6 100644 --- a/typescript/src/lib/contracts/index.ts +++ b/typescript/src/lib/contracts/index.ts @@ -1,6 +1,8 @@ export * from "./bridge" +export * from "./chain" export * from "./chain-event" export * from "./chain-identifier" +export * from "./cross-chain" export * from "./depositor-proxy" export * from "./tbtc-token" export * from "./tbtc-vault" @@ -12,7 +14,7 @@ import { TBTCVault } from "./tbtc-vault" import { WalletRegistry } from "./wallet-registry" /** - * Convenience type aggregating all TBTC contracts handles. + * Convenience type aggregating all TBTC core contracts. */ export type TBTCContracts = { bridge: Bridge diff --git a/typescript/src/lib/ethereum/artifacts/sepolia/BaseL1BitcoinDepositor.json b/typescript/src/lib/ethereum/artifacts/sepolia/BaseL1BitcoinDepositor.json new file mode 100644 index 000000000..fbd7dddff --- /dev/null +++ b/typescript/src/lib/ethereum/artifacts/sepolia/BaseL1BitcoinDepositor.json @@ -0,0 +1,681 @@ +{ + "address": "0x0c5e36731008f4AFC1AF5Da2C4D5E07eE4a3EB69", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "depositKey", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "l2DepositOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "l1Sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "initialAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tbtcAmount", + "type": "uint256" + } + ], + "name": "DepositFinalized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "depositKey", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "l2DepositOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "l1Sender", + "type": "address" + } + ], + "name": "DepositInitialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "initializeDepositGasOffset", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "finalizeDepositGasOffset", + "type": "uint256" + } + ], + "name": "GasOffsetParametersUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "l2FinalizeDepositGasLimit", + "type": "uint256" + } + ], + "name": "L2FinalizeDepositGasLimitUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newReimbursementPool", + "type": "address" + } + ], + "name": "ReimbursementPoolUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "SATOSHI_MULTIPLIER", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l2BitcoinDepositor", + "type": "address" + } + ], + "name": "attachL2BitcoinDepositor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bridge", + "outputs": [ + { + "internalType": "contract IBridge", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "deposits", + "outputs": [ + { + "internalType": "enum L1BitcoinDepositor.DepositState", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "depositKey", + "type": "uint256" + } + ], + "name": "finalizeDeposit", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "finalizeDepositGasOffset", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "gasReimbursements", + "outputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint96", + "name": "gasSpent", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_tbtcBridge", + "type": "address" + }, + { + "internalType": "address", + "name": "_tbtcVault", + "type": "address" + }, + { + "internalType": "address", + "name": "_wormhole", + "type": "address" + }, + { + "internalType": "address", + "name": "_wormholeRelayer", + "type": "address" + }, + { + "internalType": "address", + "name": "_wormholeTokenBridge", + "type": "address" + }, + { + "internalType": "address", + "name": "_l2WormholeGateway", + "type": "address" + }, + { + "internalType": "uint16", + "name": "_l2ChainId", + "type": "uint16" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes4", + "name": "version", + "type": "bytes4" + }, + { + "internalType": "bytes", + "name": "inputVector", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "outputVector", + "type": "bytes" + }, + { + "internalType": "bytes4", + "name": "locktime", + "type": "bytes4" + } + ], + "internalType": "struct IBridgeTypes.BitcoinTxInfo", + "name": "fundingTx", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "fundingOutputIndex", + "type": "uint32" + }, + { + "internalType": "bytes8", + "name": "blindingFactor", + "type": "bytes8" + }, + { + "internalType": "bytes20", + "name": "walletPubKeyHash", + "type": "bytes20" + }, + { + "internalType": "bytes20", + "name": "refundPubKeyHash", + "type": "bytes20" + }, + { + "internalType": "bytes4", + "name": "refundLocktime", + "type": "bytes4" + }, + { + "internalType": "address", + "name": "vault", + "type": "address" + } + ], + "internalType": "struct IBridgeTypes.DepositRevealInfo", + "name": "reveal", + "type": "tuple" + }, + { + "internalType": "address", + "name": "l2DepositOwner", + "type": "address" + } + ], + "name": "initializeDeposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "initializeDepositGasOffset", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l2BitcoinDepositor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l2ChainId", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l2FinalizeDepositGasLimit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l2WormholeGateway", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "quoteFinalizeDeposit", + "outputs": [ + { + "internalType": "uint256", + "name": "cost", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "reimbursementPool", + "outputs": [ + { + "internalType": "contract ReimbursementPool", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "tbtcToken", + "outputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "tbtcVault", + "outputs": [ + { + "internalType": "contract ITBTCVault", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_initializeDepositGasOffset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_finalizeDepositGasOffset", + "type": "uint256" + } + ], + "name": "updateGasOffsetParameters", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_l2FinalizeDepositGasLimit", + "type": "uint256" + } + ], + "name": "updateL2FinalizeDepositGasLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ReimbursementPool", + "name": "_reimbursementPool", + "type": "address" + } + ], + "name": "updateReimbursementPool", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "wormhole", + "outputs": [ + { + "internalType": "contract IWormhole", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "wormholeRelayer", + "outputs": [ + { + "internalType": "contract IWormholeRelayer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "wormholeTokenBridge", + "outputs": [ + { + "internalType": "contract IWormholeTokenBridge", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x5a405183332f623649fcf19f8506cf2582882d5dc2b05582e0066388ef122229", + "receipt": { + "to": null, + "from": "0x68ad60CC5e8f3B7cC53beaB321cf0e6036962dBc", + "contractAddress": "0x0c5e36731008f4AFC1AF5Da2C4D5E07eE4a3EB69", + "transactionIndex": 94, + "gasUsed": "887851", + "logsBloom": "0x00000000000000000000000000000000400000000000000400800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000202000001000000000000000000000000000000000000020000000000000000000800000000800000000000000008000000400000000200000000000000000000000000000040000080000000000000800000000000000000000000000000000400000000000000000000000000000010000000000020000000000000200020040000000000000400000000000000000020000000000000000000000000000000100000000000000000000000000000000000", + "blockHash": "0x9d4a08d2b6fd26df76447aa1b5e0054686b1d462dc12be4d271dca1299060a2c", + "transactionHash": "0x5a405183332f623649fcf19f8506cf2582882d5dc2b05582e0066388ef122229", + "logs": [ + { + "transactionIndex": 94, + "blockNumber": 5441536, + "transactionHash": "0x5a405183332f623649fcf19f8506cf2582882d5dc2b05582e0066388ef122229", + "address": "0x0c5e36731008f4AFC1AF5Da2C4D5E07eE4a3EB69", + "topics": [ + "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", + "0x000000000000000000000000720cb49a8b3c03e199075544f7f1f4d772dd6d06" + ], + "data": "0x", + "logIndex": 75, + "blockHash": "0x9d4a08d2b6fd26df76447aa1b5e0054686b1d462dc12be4d271dca1299060a2c" + }, + { + "transactionIndex": 94, + "blockNumber": 5441536, + "transactionHash": "0x5a405183332f623649fcf19f8506cf2582882d5dc2b05582e0066388ef122229", + "address": "0x0c5e36731008f4AFC1AF5Da2C4D5E07eE4a3EB69", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000068ad60cc5e8f3b7cc53beab321cf0e6036962dbc" + ], + "data": "0x", + "logIndex": 76, + "blockHash": "0x9d4a08d2b6fd26df76447aa1b5e0054686b1d462dc12be4d271dca1299060a2c" + }, + { + "transactionIndex": 94, + "blockNumber": 5441536, + "transactionHash": "0x5a405183332f623649fcf19f8506cf2582882d5dc2b05582e0066388ef122229", + "address": "0x0c5e36731008f4AFC1AF5Da2C4D5E07eE4a3EB69", + "topics": [ + "0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 77, + "blockHash": "0x9d4a08d2b6fd26df76447aa1b5e0054686b1d462dc12be4d271dca1299060a2c" + }, + { + "transactionIndex": 94, + "blockNumber": 5441536, + "transactionHash": "0x5a405183332f623649fcf19f8506cf2582882d5dc2b05582e0066388ef122229", + "address": "0x0c5e36731008f4AFC1AF5Da2C4D5E07eE4a3EB69", + "topics": [ + "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dd0007713cb99564b7835fd628a1718e8f9f9785", + "logIndex": 78, + "blockHash": "0x9d4a08d2b6fd26df76447aa1b5e0054686b1d462dc12be4d271dca1299060a2c" + } + ], + "blockNumber": 5441536, + "cumulativeGasUsed": "8903785", + "status": 1, + "byzantium": true + }, + "numDeployments": 1, + "implementation": "0x720Cb49A8b3c03E199075544F7f1F4d772Dd6d06", + "devdoc": "Contract deployed as upgradable proxy" +} diff --git a/typescript/src/lib/ethereum/bridge.ts b/typescript/src/lib/ethereum/bridge.ts index 1c3d63dac..b27494c5e 100644 --- a/typescript/src/lib/ethereum/bridge.ts +++ b/typescript/src/lib/ethereum/bridge.ts @@ -17,6 +17,7 @@ import { DepositRevealedEvent, DepositReceipt, DepositRequest, + Chains, } from "../contracts" import { Event as EthersEvent } from "@ethersproject/contracts" import { BigNumber, constants, ContractTransaction, utils } from "ethers" @@ -58,18 +59,18 @@ export class EthereumBridge { constructor( config: EthersContractConfig, - deploymentType: "local" | "sepolia" | "mainnet" = "local" + chainId: Chains.Ethereum = Chains.Ethereum.Local ) { let deployment: EthersContractDeployment - switch (deploymentType) { - case "local": + switch (chainId) { + case Chains.Ethereum.Local: deployment = LocalBridgeDeployment break - case "sepolia": + case Chains.Ethereum.Sepolia: deployment = SepoliaBridgeDeployment break - case "mainnet": + case Chains.Ethereum.Mainnet: deployment = MainnetBridgeDeployment break default: diff --git a/typescript/src/lib/ethereum/index.ts b/typescript/src/lib/ethereum/index.ts index 687b85841..c8573a305 100644 --- a/typescript/src/lib/ethereum/index.ts +++ b/typescript/src/lib/ethereum/index.ts @@ -1,14 +1,22 @@ -import { TBTCContracts } from "../contracts" +import { + ChainMappings, + Chains, + CrossChainContractsLoader, + L2Chain, + TBTCContracts, +} from "../contracts" import { providers, Signer } from "ethers" import { EthereumBridge } from "./bridge" import { EthereumWalletRegistry } from "./wallet-registry" import { EthereumTBTCToken } from "./tbtc-token" import { EthereumTBTCVault } from "./tbtc-vault" import { EthereumAddress } from "./address" +import { EthereumL1BitcoinDepositor } from "./l1-bitcoin-depositor" export * from "./address" export * from "./bridge" export * from "./depositor-proxy" +export * from "./l1-bitcoin-depositor" export * from "./tbtc-token" export * from "./tbtc-vault" export * from "./wallet-registry" @@ -26,13 +34,13 @@ export { EthersContractConfig as EthereumContractConfig } from "./adapter" export type EthereumSigner = Signer | providers.Provider /** - * Resolves the Ethereum network the given signer is tied to. - * @param signer The signer whose network should be resolved. - * @returns Ethereum network. + * Resolves the chain ID from the given signer. + * @param signer The signer whose chain ID should be resolved. + * @returns Chain ID as a string. */ -export async function ethereumNetworkFromSigner( +export async function chainIdFromSigner( signer: EthereumSigner -): Promise { +): Promise { let chainId: number if (Signer.isSigner(signer)) { chainId = await signer.getChainId() @@ -41,14 +49,7 @@ export async function ethereumNetworkFromSigner( chainId = network.chainId } - switch (chainId) { - case 1: - return "mainnet" - case 11155111: - return "sepolia" - default: - return "local" - } + return chainId.toString() } /** @@ -70,34 +71,29 @@ export async function ethereumAddressFromSigner( } /** - * Supported Ethereum networks. - */ -export type EthereumNetwork = "local" | "sepolia" | "mainnet" - -/** - * Loads Ethereum implementation of tBTC contracts for the given Ethereum - * network and attaches the given signer there. + * Loads Ethereum implementation of tBTC core contracts for the given Ethereum + * chain ID and attaches the given signer there. * @param signer Signer that should be attached to tBTC contracts. - * @param network Ethereum network. - * @returns Handle to tBTC contracts. - * @throws Throws an error if the signer's Ethereum network is other than + * @param chainId Ethereum chain ID. + * @returns Handle to tBTC core contracts. + * @throws Throws an error if the signer's Ethereum chain ID is other than * the one used to load tBTC contracts. */ -export async function loadEthereumContracts( +export async function loadEthereumCoreContracts( signer: EthereumSigner, - network: EthereumNetwork + chainId: Chains.Ethereum ): Promise { - const signerNetwork = await ethereumNetworkFromSigner(signer) - if (signerNetwork !== network) { - throw new Error("Signer uses different network than tBTC contracts") + const signerChainId = await chainIdFromSigner(signer) + if (signerChainId !== chainId) { + throw new Error("Signer uses different chain than Ethereum core contracts") } - const bridge = new EthereumBridge({ signerOrProvider: signer }, network) - const tbtcToken = new EthereumTBTCToken({ signerOrProvider: signer }, network) - const tbtcVault = new EthereumTBTCVault({ signerOrProvider: signer }, network) + const bridge = new EthereumBridge({ signerOrProvider: signer }, chainId) + const tbtcToken = new EthereumTBTCToken({ signerOrProvider: signer }, chainId) + const tbtcVault = new EthereumTBTCVault({ signerOrProvider: signer }, chainId) const walletRegistry = new EthereumWalletRegistry( { signerOrProvider: signer }, - network + chainId ) const bridgeWalletRegistry = await bridge.walletRegistry() @@ -118,3 +114,42 @@ export async function loadEthereumContracts( walletRegistry, } } + +/** + * Creates the Ethereum implementation of tBTC cross-chain contracts loader. + * The provided signer is attached to loaded L1 contracts. The given + * Ethereum chain ID is used to load the L1 contracts and resolve the chain + * mapping that provides corresponding L2 chains IDs. + * @param signer Ethereum L1 signer. + * @param chainId Ethereum L1 chain ID. + * @returns Loader for tBTC cross-chain contracts. + * @throws Throws an error if the signer's Ethereum chain ID is other than + * the one used to construct the loader. + */ +export async function ethereumCrossChainContractsLoader( + signer: EthereumSigner, + chainId: Chains.Ethereum +): Promise { + const signerChainId = await chainIdFromSigner(signer) + if (signerChainId !== chainId) { + throw new Error( + "Signer uses different chain than Ethereum cross-chain contracts" + ) + } + + const loadChainMapping = () => + ChainMappings.find((ecm) => ecm.ethereum === chainId) + + const loadL1Contracts = async (l2ChainName: L2Chain) => ({ + l1BitcoinDepositor: new EthereumL1BitcoinDepositor( + { signerOrProvider: signer }, + chainId, + l2ChainName + ), + }) + + return { + loadChainMapping, + loadL1Contracts, + } +} diff --git a/typescript/src/lib/ethereum/l1-bitcoin-depositor.ts b/typescript/src/lib/ethereum/l1-bitcoin-depositor.ts new file mode 100644 index 000000000..9e49c481f --- /dev/null +++ b/typescript/src/lib/ethereum/l1-bitcoin-depositor.ts @@ -0,0 +1,161 @@ +import { + EthersContractConfig, + EthersContractDeployment, + EthersContractHandle, +} from "./adapter" +import { L1BitcoinDepositor as L1BitcoinDepositorTypechain } from "../../../typechain/L1BitcoinDepositor" +import { + ChainIdentifier, + Chains, + CrossChainExtraDataEncoder, + DepositReceipt, + L1BitcoinDepositor, + L2Chain, +} from "../contracts" +import { EthereumAddress, packRevealDepositParameters } from "./index" +import { BitcoinRawTxVectors } from "../bitcoin" +import { Hex } from "../utils" + +// TODO: Uncomment once BaseL1BitcoinDepositor is available on Ethereum mainnet. +// import MainnetBaseL1BitcoinDepositorDeployment from "./artifacts/mainnet/BaseL1BitcoinDepositor.json" +import SepoliaBaseL1BitcoinDepositorDeployment from "./artifacts/sepolia/BaseL1BitcoinDepositor.json" + +const artifactLoader = { + getMainnet: (l2ChainName: L2Chain) => { + switch (l2ChainName) { + // TODO: Uncomment once BaseL1BitcoinDepositor is available on Ethereum mainnet. + // case "Base": + // return MainnetBaseL1BitcoinDepositorDeployment + default: + throw new Error("Unsupported L2 chain") + } + }, + + getSepolia: (l2ChainName: L2Chain) => { + switch (l2ChainName) { + case "Base": + return SepoliaBaseL1BitcoinDepositorDeployment + default: + throw new Error("Unsupported L2 chain") + } + }, +} + +/** + * Implementation of the Ethereum L1BitcoinDepositor handle. It can be + * constructed for each supported L2 chain. + * @see {L1BitcoinDepositor} for reference. + */ +export class EthereumL1BitcoinDepositor + extends EthersContractHandle + implements L1BitcoinDepositor +{ + readonly #extraDataEncoder: CrossChainExtraDataEncoder + + constructor( + config: EthersContractConfig, + chainId: Chains.Ethereum, + l2ChainName: L2Chain + ) { + let deployment: EthersContractDeployment + + switch (chainId) { + case Chains.Ethereum.Sepolia: + deployment = artifactLoader.getSepolia(l2ChainName) + break + case Chains.Ethereum.Mainnet: + deployment = artifactLoader.getMainnet(l2ChainName) + break + default: + throw new Error("Unsupported deployment type") + } + + super(config, deployment) + + this.#extraDataEncoder = new EthereumCrossChainExtraDataEncoder() + } + + // eslint-disable-next-line valid-jsdoc + /** + * @see {L1BitcoinDepositor#getChainIdentifier} + */ + getChainIdentifier(): ChainIdentifier { + return EthereumAddress.from(this._instance.address) + } + + // eslint-disable-next-line valid-jsdoc + /** + * @see {L1BitcoinDepositor#extraDataEncoder} + */ + extraDataEncoder(): CrossChainExtraDataEncoder { + return this.#extraDataEncoder + } + + // eslint-disable-next-line valid-jsdoc + /** + * @see {L1BitcoinDepositor#initializeDeposit} + */ + async initializeDeposit( + depositTx: BitcoinRawTxVectors, + depositOutputIndex: number, + deposit: DepositReceipt, + vault?: ChainIdentifier + ): Promise { + const { fundingTx, reveal } = packRevealDepositParameters( + depositTx, + depositOutputIndex, + deposit, + vault + ) + + if (!deposit.extraData) { + throw new Error("Extra data is required") + } + + const l2DepositOwner = this.extraDataEncoder().decodeDepositOwner( + deposit.extraData + ) + + const tx = await this._instance.initializeDeposit( + fundingTx, + reveal, + `0x${l2DepositOwner.identifierHex}` + ) + + return Hex.from(tx.hash) + } +} + +/** + * Implementation of the Ethereum CrossChainExtraDataEncoder. + * @see {CrossChainExtraDataEncoder} for reference. + */ +export class EthereumCrossChainExtraDataEncoder + implements CrossChainExtraDataEncoder +{ + // eslint-disable-next-line valid-jsdoc + /** + * @see {CrossChainExtraDataEncoder#encodeDepositOwner} + */ + encodeDepositOwner(depositOwner: ChainIdentifier): Hex { + // Make sure we are dealing with an Ethereum address. If not, this + // call will throw. + const address = EthereumAddress.from(depositOwner.identifierHex) + + // Extra data must be 32-byte so prefix the 20-byte address with + // 12 zero bytes. + return Hex.from(`000000000000000000000000${address.identifierHex}`) + } + + // eslint-disable-next-line valid-jsdoc + /** + * @see {CrossChainExtraDataEncoder#decodeDepositOwner} + */ + decodeDepositOwner(extraData: Hex): ChainIdentifier { + // Cut the first 12 zero bytes of the extra data and convert the rest to + // an Ethereum address. + return EthereumAddress.from( + Hex.from(extraData.toBuffer().subarray(12)).toString() + ) + } +} diff --git a/typescript/src/lib/ethereum/tbtc-token.ts b/typescript/src/lib/ethereum/tbtc-token.ts index a70503064..cc6585db2 100644 --- a/typescript/src/lib/ethereum/tbtc-token.ts +++ b/typescript/src/lib/ethereum/tbtc-token.ts @@ -1,5 +1,5 @@ import { TBTC as TBTCTypechain } from "../../../typechain/TBTC" -import { ChainIdentifier, TBTCToken } from "../contracts" +import { ChainIdentifier, Chains, TBTCToken } from "../contracts" import { BigNumber, ContractTransaction, utils } from "ethers" import { BitcoinHashUtils, BitcoinUtxo } from "../bitcoin" import { Hex } from "../utils" @@ -25,18 +25,18 @@ export class EthereumTBTCToken { constructor( config: EthersContractConfig, - deploymentType: "local" | "sepolia" | "mainnet" = "local" + chainId: Chains.Ethereum = Chains.Ethereum.Local ) { let deployment: EthersContractDeployment - switch (deploymentType) { - case "local": + switch (chainId) { + case Chains.Ethereum.Local: deployment = LocalTBTCTokenDeployment break - case "sepolia": + case Chains.Ethereum.Sepolia: deployment = SepoliaTBTCTokenDeployment break - case "mainnet": + case Chains.Ethereum.Mainnet: deployment = MainnetTBTCTokenDeployment break default: diff --git a/typescript/src/lib/ethereum/tbtc-vault.ts b/typescript/src/lib/ethereum/tbtc-vault.ts index e9a62f1fe..7e284ae97 100644 --- a/typescript/src/lib/ethereum/tbtc-vault.ts +++ b/typescript/src/lib/ethereum/tbtc-vault.ts @@ -7,6 +7,7 @@ import { OptimisticMintingRequest, OptimisticMintingRequestedEvent, ChainIdentifier, + Chains, } from "../contracts" import { BigNumber, ContractTransaction } from "ethers" import { BitcoinTxHash } from "../bitcoin" @@ -39,18 +40,18 @@ export class EthereumTBTCVault { constructor( config: EthersContractConfig, - deploymentType: "local" | "sepolia" | "mainnet" = "local" + chainId: Chains.Ethereum = Chains.Ethereum.Local ) { let deployment: EthersContractDeployment - switch (deploymentType) { - case "local": + switch (chainId) { + case Chains.Ethereum.Local: deployment = LocalTBTCVaultDeployment break - case "sepolia": + case Chains.Ethereum.Sepolia: deployment = SepoliaTBTCVaultDeployment break - case "mainnet": + case Chains.Ethereum.Mainnet: deployment = MainnetTBTCVaultDeployment break default: diff --git a/typescript/src/lib/ethereum/wallet-registry.ts b/typescript/src/lib/ethereum/wallet-registry.ts index ee16cac4e..9a70557e8 100644 --- a/typescript/src/lib/ethereum/wallet-registry.ts +++ b/typescript/src/lib/ethereum/wallet-registry.ts @@ -6,6 +6,7 @@ import { DkgResultChallengedEvent, DkgResultSubmittedEvent, ChainIdentifier, + Chains, } from "../contracts" import { backoffRetrier, Hex } from "../utils" import { Event as EthersEvent } from "@ethersproject/contracts" @@ -31,18 +32,18 @@ export class EthereumWalletRegistry { constructor( config: EthersContractConfig, - deploymentType: "local" | "sepolia" | "mainnet" = "local" + chainId: Chains.Ethereum = Chains.Ethereum.Local ) { let deployment: EthersContractDeployment - switch (deploymentType) { - case "local": + switch (chainId) { + case Chains.Ethereum.Local: deployment = LocalWalletRegistryDeployment break - case "sepolia": + case Chains.Ethereum.Sepolia: deployment = SepoliaWalletRegistryDeployment break - case "mainnet": + case Chains.Ethereum.Mainnet: deployment = MainnetWalletRegistryDeployment break default: diff --git a/typescript/src/services/deposits/cross-chain.ts b/typescript/src/services/deposits/cross-chain.ts new file mode 100644 index 000000000..07294361d --- /dev/null +++ b/typescript/src/services/deposits/cross-chain.ts @@ -0,0 +1,110 @@ +import { + ChainIdentifier, + CrossChainContracts, + CrossChainExtraDataEncoder, + DepositorProxy, + DepositReceipt, +} from "../../lib/contracts" +import { BitcoinRawTxVectors } from "../../lib/bitcoin" +import { Hex } from "../../lib/utils" + +/** + * Mode of operation for the cross-chain depositor proxy: + * - [L2Transaction]: The proxy will reveal the deposit using a transaction on + * the L2 chain. The tBTC system is responsible for relaying the deposit to + * the tBTC L1 chain. + * - [L1Transaction]: The proxy will directly reveal the deposit using a + * transaction on the tBTC L1 chain. + */ +export type CrossChainDepositorMode = "L2Transaction" | "L1Transaction" + +/** + * Implementation of the cross chain depositor proxy. This component is used to + * reveal cross-chain deposits whose target chain is not the same as the L1 + * chain the tBTC system is deployed on. + * @see {DepositorProxy} for reference. + */ +export class CrossChainDepositor implements DepositorProxy { + readonly #crossChainContracts: CrossChainContracts + readonly #revealMode: CrossChainDepositorMode + + constructor( + crossChainContracts: CrossChainContracts, + revealMode: CrossChainDepositorMode = "L2Transaction" + ) { + this.#crossChainContracts = crossChainContracts + this.#revealMode = revealMode + } + + /** + * @returns The chain-specific identifier of the contract that will be + * used as the actual L1 depositor embedded in the deposit script. + * In this case, the depositor must be the L1BitcoinDepositor contract + * corresponding to the given L2 chain the deposit is targeting. + * This is because the L1BitcoinDepositor contract reveals the deposit to + * the Bridge contract (on L1) and transfers minted TBTC token to the + * target L2 chain once the deposit is processed. + * @see {DepositorProxy#getChainIdentifier} + */ + getChainIdentifier(): ChainIdentifier { + return this.#crossChainContracts.l1BitcoinDepositor.getChainIdentifier() + } + + /** + * @returns Extra data for the cross-chain deposit script. Actually, this is + * the L2 deposit owner identifier took from the L2BitcoinDepositor + * contract. + * @throws Throws if the L2 deposit owner cannot be resolved. This + * typically happens if the L2BitcoinDepositor operates with + * a read-only signer whose address cannot be resolved. + */ + extraData(): Hex { + const depositOwner = + this.#crossChainContracts.l2BitcoinDepositor.getDepositOwner() + + if (!depositOwner) { + throw new Error("Cannot resolve L2 deposit owner") + } + + return this.#extraDataEncoder().encodeDepositOwner(depositOwner) + } + + #extraDataEncoder(): CrossChainExtraDataEncoder { + switch (this.#revealMode) { + case "L2Transaction": + return this.#crossChainContracts.l2BitcoinDepositor.extraDataEncoder() + case "L1Transaction": + return this.#crossChainContracts.l1BitcoinDepositor.extraDataEncoder() + } + } + + // eslint-disable-next-line valid-jsdoc + /** + * Reveals the given deposit depending on the reveal mode. + * @see {CrossChainDepositorMode} for reveal modes description. + * @see {DepositorProxy#revealDeposit} + */ + revealDeposit( + depositTx: BitcoinRawTxVectors, + depositOutputIndex: number, + deposit: DepositReceipt, + vault?: ChainIdentifier + ): Promise { + switch (this.#revealMode) { + case "L2Transaction": + return this.#crossChainContracts.l2BitcoinDepositor.initializeDeposit( + depositTx, + depositOutputIndex, + deposit, + vault + ) + case "L1Transaction": + return this.#crossChainContracts.l1BitcoinDepositor.initializeDeposit( + depositTx, + depositOutputIndex, + deposit, + vault + ) + } + } +} diff --git a/typescript/src/services/deposits/deposits-service.ts b/typescript/src/services/deposits/deposits-service.ts index 974708941..097caffff 100644 --- a/typescript/src/services/deposits/deposits-service.ts +++ b/typescript/src/services/deposits/deposits-service.ts @@ -1,7 +1,9 @@ import { ChainIdentifier, + CrossChainContracts, DepositorProxy, DepositReceipt, + L2Chain, TBTCContracts, } from "../../lib/contracts" import { @@ -14,6 +16,7 @@ import { import { Hex } from "../../lib/utils" import { Deposit } from "./deposit" import * as crypto from "crypto" +import { CrossChainDepositor } from "./cross-chain" /** * Service exposing features related to tBTC v2 deposits. @@ -36,11 +39,23 @@ export class DepositsService { * Chain-specific identifier of the default depositor used for deposits * initiated by this service. */ - private defaultDepositor: ChainIdentifier | undefined + #defaultDepositor: ChainIdentifier | undefined + /** + * Gets cross-chain contracts for the given supported L2 chain. + * @param _ Name of the L2 chain for which to get cross-chain contracts. + * @returns Cross-chain contracts for the given L2 chain or + * undefined if not initialized. + */ + readonly #crossChainContracts: (_: L2Chain) => CrossChainContracts | undefined - constructor(tbtcContracts: TBTCContracts, bitcoinClient: BitcoinClient) { + constructor( + tbtcContracts: TBTCContracts, + bitcoinClient: BitcoinClient, + crossChainContracts: (_: L2Chain) => CrossChainContracts | undefined + ) { this.tbtcContracts = tbtcContracts this.bitcoinClient = bitcoinClient + this.#crossChainContracts = crossChainContracts } /** @@ -62,7 +77,7 @@ export class DepositsService { bitcoinRecoveryAddress: string, extraData?: Hex ): Promise { - if (this.defaultDepositor === undefined) { + if (this.#defaultDepositor === undefined) { throw new Error( "Default depositor is not set; use setDefaultDepositor first" ) @@ -70,7 +85,7 @@ export class DepositsService { const receipt = await this.generateDepositReceipt( bitcoinRecoveryAddress, - this.defaultDepositor, + this.#defaultDepositor, extraData ) @@ -116,6 +131,49 @@ export class DepositsService { ) } + /** + * Initiates the tBTC v2 cross-chain deposit process. A cross-chain deposit + * is a deposit that targets an L2 chain other than the L1 chain the tBTC + * system is deployed on. Such a deposit is initiated using a transaction + * on the L2 chain. To make it happen, the given L2 cross-chain contracts + * must be initialized along with a L2 signer first. + * @param bitcoinRecoveryAddress P2PKH or P2WPKH Bitcoin address that can + * be used for emergency recovery of the + * deposited funds. + * @param l2ChainName Name of the L2 chain the deposit is targeting. + * @returns Handle to the initiated deposit process. + * @throws Throws an error if one of the following occurs: + * - There are no active wallet in the Bridge contract + * - The Bitcoin recovery address is not a valid P2(W)PKH + * - The cross-chain contracts for the given L2 chain are not + * initialized + * - The L2 deposit owner cannot be resolved. This typically + * happens if the L2 cross-chain contracts operate with a + * read-only signer whose address cannot be resolved. + * @see {TBTC#initializeCrossChain} for cross-chain contracts initialization. + * @dev This is actually a call to initiateDepositWithProxy with a built-in + * depositor proxy. + */ + async initiateCrossChainDeposit( + bitcoinRecoveryAddress: string, + l2ChainName: L2Chain + ): Promise { + const crossChainContracts = this.#crossChainContracts(l2ChainName) + if (!crossChainContracts) { + throw new Error( + `Cross-chain contracts for ${l2ChainName} not initialized` + ) + } + + const depositorProxy = new CrossChainDepositor(crossChainContracts) + + return this.initiateDepositWithProxy( + bitcoinRecoveryAddress, + depositorProxy, + depositorProxy.extraData() + ) + } + private async generateDepositReceipt( bitcoinRecoveryAddress: string, depositor: ChainIdentifier, @@ -195,6 +253,6 @@ export class DepositsService { * Make sure you know what you are doing while using this method. */ setDefaultDepositor(defaultDepositor: ChainIdentifier) { - this.defaultDepositor = defaultDepositor + this.#defaultDepositor = defaultDepositor } } diff --git a/typescript/src/services/deposits/index.ts b/typescript/src/services/deposits/index.ts index d326e4023..7b12de781 100644 --- a/typescript/src/services/deposits/index.ts +++ b/typescript/src/services/deposits/index.ts @@ -1,3 +1,4 @@ +export * from "./cross-chain" export * from "./deposit" export * from "./deposits-service" export * from "./funding" diff --git a/typescript/src/services/tbtc.ts b/typescript/src/services/tbtc.ts index 706f8a711..9e82eaf09 100644 --- a/typescript/src/services/tbtc.ts +++ b/typescript/src/services/tbtc.ts @@ -1,15 +1,24 @@ import { DepositsService } from "./deposits" import { MaintenanceService } from "./maintenance" import { RedemptionsService } from "./redemptions" -import { TBTCContracts } from "../lib/contracts" +import { + Chains, + CrossChainContracts, + CrossChainContractsLoader, + L1CrossChainContracts, + L2Chain, + L2CrossChainContracts, + TBTCContracts, +} from "../lib/contracts" import { BitcoinClient, BitcoinNetwork } from "../lib/bitcoin" import { ethereumAddressFromSigner, - EthereumNetwork, EthereumSigner, - loadEthereumContracts, + ethereumCrossChainContractsLoader, + loadEthereumCoreContracts, } from "../lib/ethereum" import { ElectrumClient } from "../lib/electrum" +import { loadBaseCrossChainContracts } from "../lib/base" /** * Entrypoint component of the tBTC v2 SDK. @@ -36,16 +45,33 @@ export class TBTC { * Bitcoin client handle for low-level access. */ public readonly bitcoinClient: BitcoinClient + /** + * Reference to the cross-chain contracts loader. + */ + readonly #crossChainContractsLoader?: CrossChainContractsLoader + /** + * Mapping of cross-chain contracts for different supported L2 chains. + * Each set of cross-chain contracts must be first initialized using + * the `initializeCrossChain` method. + */ + readonly #crossChainContracts: Map private constructor( tbtcContracts: TBTCContracts, - bitcoinClient: BitcoinClient + bitcoinClient: BitcoinClient, + crossChainContractsLoader?: CrossChainContractsLoader ) { - this.deposits = new DepositsService(tbtcContracts, bitcoinClient) + this.deposits = new DepositsService( + tbtcContracts, + bitcoinClient, + (l2ChainName) => this.crossChainContracts(l2ChainName) + ) this.maintenance = new MaintenanceService(tbtcContracts, bitcoinClient) this.redemptions = new RedemptionsService(tbtcContracts, bitcoinClient) this.tbtcContracts = tbtcContracts this.bitcoinClient = bitcoinClient + this.#crossChainContractsLoader = crossChainContractsLoader + this.#crossChainContracts = new Map() } /** @@ -58,7 +84,11 @@ export class TBTC { * Ethereum mainnet. */ static async initializeMainnet(signer: EthereumSigner): Promise { - return TBTC.initializeEthereum(signer, "mainnet", BitcoinNetwork.Mainnet) + return TBTC.initializeEthereum( + signer, + Chains.Ethereum.Mainnet, + BitcoinNetwork.Mainnet + ) } /** @@ -71,7 +101,11 @@ export class TBTC { * Ethereum mainnet. */ static async initializeSepolia(signer: EthereumSigner): Promise { - return TBTC.initializeEthereum(signer, "sepolia", BitcoinNetwork.Testnet) + return TBTC.initializeEthereum( + signer, + Chains.Ethereum.Sepolia, + BitcoinNetwork.Testnet + ) } /** @@ -79,7 +113,7 @@ export class TBTC { * The initialized instance uses default Electrum servers to interact * with Bitcoin network. * @param signer Ethereum signer. - * @param ethereumNetwork Ethereum network. + * @param ethereumChainId Ethereum chain ID. * @param bitcoinNetwork Bitcoin network. * @returns Initialized tBTC v2 SDK entrypoint. * @throws Throws an error if the underlying signer's Ethereum network is @@ -87,14 +121,26 @@ export class TBTC { */ private static async initializeEthereum( signer: EthereumSigner, - ethereumNetwork: EthereumNetwork, + ethereumChainId: Chains.Ethereum, bitcoinNetwork: BitcoinNetwork ): Promise { const signerAddress = await ethereumAddressFromSigner(signer) - const tbtcContracts = await loadEthereumContracts(signer, ethereumNetwork) + const tbtcContracts = await loadEthereumCoreContracts( + signer, + ethereumChainId + ) + const crossChainContractsLoader = await ethereumCrossChainContractsLoader( + signer, + ethereumChainId + ) + const bitcoinClient = ElectrumClient.fromDefaultConfig(bitcoinNetwork) - const tbtc = new TBTC(tbtcContracts, bitcoinClient) + const tbtc = new TBTC( + tbtcContracts, + bitcoinClient, + crossChainContractsLoader + ) // If signer address can be resolved, set it as default depositor. if (signerAddress !== undefined) { @@ -120,4 +166,71 @@ export class TBTC { ): Promise { return new TBTC(tbtcContracts, bitcoinClient) } + + /** + * Initializes cross-chain contracts for the given L2 chain, using the + * given signer. Updates the signer on subsequent calls. + * @param l2ChainName Name of the L2 chain for which to initialize + * cross-chain contracts. + * @param l2Signer Signer to use with the L2 chain contracts. + * @returns Void promise. + * @throws Throws an error if: + * - Cross-chain contracts loader is not available for this TBTC SDK instance, + * - Chain mapping between the L1 and the given L2 chain is not defined. + * @dev In case this function needs to support non-EVM L2 chains that can't + * use EthereumSigner as a signer type, the l2Signer parameter should + * probably be turned into a union of multiple supported types or + * generalized in some other way. + */ + async initializeCrossChain( + l2ChainName: L2Chain, + l2Signer: EthereumSigner + ): Promise { + if (!this.#crossChainContractsLoader) { + throw new Error( + "Cross-chain contracts loader not available for this instance" + ) + } + + const chainMapping = this.#crossChainContractsLoader.loadChainMapping() + if (!chainMapping) { + throw new Error("Chain mapping between L1 and L2 chains not defined") + } + + const l1CrossChainContracts: L1CrossChainContracts = + await this.#crossChainContractsLoader.loadL1Contracts(l2ChainName) + let l2CrossChainContracts: L2CrossChainContracts + + switch (l2ChainName) { + case "Base": + const baseChainId = chainMapping.base + if (!baseChainId) { + throw new Error("Base chain ID not available in chain mapping") + } + l2CrossChainContracts = await loadBaseCrossChainContracts( + l2Signer, + baseChainId + ) + break + default: + throw new Error("Unsupported L2 chain") + } + + this.#crossChainContracts.set(l2ChainName, { + ...l1CrossChainContracts, + ...l2CrossChainContracts, + }) + } + + /** + * Gets cross-chain contracts for the given supported L2 chain. + * The given L2 chain contracts must be first initialized using the + * `initializeCrossChain` method. + * @param l2ChainName Name of the L2 chain for which to get cross-chain contracts. + * @returns Cross-chain contracts for the given L2 chain or + * undefined if not initialized. + */ + crossChainContracts(l2ChainName: L2Chain): CrossChainContracts | undefined { + return this.#crossChainContracts.get(l2ChainName) + } } diff --git a/typescript/test/lib/base.test.ts b/typescript/test/lib/base.test.ts new file mode 100644 index 000000000..d28417ea9 --- /dev/null +++ b/typescript/test/lib/base.test.ts @@ -0,0 +1,177 @@ +import { + deployMockContract, + MockContract, +} from "@ethereum-waffle/mock-contract" +import { + BaseL2BitcoinDepositor, + BaseL2TBTCToken, + BitcoinRawTxVectors, + ChainIdentifier, + Chains, + DepositReceipt, + EthereumAddress, + Hex, +} from "../../src" +import { MockProvider } from "@ethereum-waffle/provider" +import { assertContractCalledWith } from "../utils/helpers" +import { expect } from "chai" +import { BigNumber } from "ethers" + +// ABI imports. +import { abi as BaseL2BitcoinDepositorABI } from "../../src/lib/base/artifacts/baseSepolia/BaseL2BitcoinDepositor.json" +import { abi as BaseL2TBTCTokenABI } from "../../src/lib/base/artifacts/baseSepolia/BaseTBTC.json" + +describe("Base", () => { + describe("BaseL2BitcoinDepositor", () => { + let depositorContract: MockContract + let depositorHandle: BaseL2BitcoinDepositor + + beforeEach(async () => { + const [signer] = new MockProvider().getWallets() + + depositorContract = await deployMockContract( + signer, + `${JSON.stringify(BaseL2BitcoinDepositorABI)}` + ) + + depositorHandle = new BaseL2BitcoinDepositor( + { + address: depositorContract.address, + signerOrProvider: signer, + }, + Chains.Base.BaseSepolia + ) + }) + + describe("initializeDeposit", () => { + // Just short byte strings for clarity. + const depositTx: BitcoinRawTxVectors = { + version: Hex.from("00000000"), + inputs: Hex.from("11111111"), + outputs: Hex.from("22222222"), + locktime: Hex.from("33333333"), + } + const depositOutputIndex: number = 2 + const deposit: DepositReceipt = { + depositor: EthereumAddress.from( + "934b98637ca318a4d6e7ca6ffd1690b8e77df637" + ), + walletPublicKeyHash: Hex.from( + "8db50eb52063ea9d98b3eac91489a90f738986f6" + ), + refundPublicKeyHash: Hex.from( + "28e081f285138ccbe389c1eb8985716230129f89" + ), + blindingFactor: Hex.from("f9f0c90d00039523"), + refundLocktime: Hex.from("60bcea61"), + extraData: Hex.from( + "00000000000000000000000091fe5b7027c0cA767270bB1A474bA1338BA2A4d2" + ), + } + const vault: ChainIdentifier = EthereumAddress.from( + "82883a4c7a8dd73ef165deb402d432613615ced4" + ) + + context( + "when L2 deposit owner is properly encoded in the extra data", + () => { + beforeEach(async () => { + await depositorContract.mock.initializeDeposit.returns() + + await depositorHandle.initializeDeposit( + depositTx, + depositOutputIndex, + deposit, + vault + ) + }) + + it("should initialize the deposit", async () => { + assertContractCalledWith(depositorContract, "initializeDeposit", [ + { + version: "0x00000000", + inputVector: "0x11111111", + outputVector: "0x22222222", + locktime: "0x33333333", + }, + { + fundingOutputIndex: 2, + blindingFactor: "0xf9f0c90d00039523", + walletPubKeyHash: "0x8db50eb52063ea9d98b3eac91489a90f738986f6", + refundPubKeyHash: "0x28e081f285138ccbe389c1eb8985716230129f89", + refundLocktime: "0x60bcea61", + vault: "0x82883a4c7a8dd73ef165deb402d432613615ced4", + }, + "0x91fe5b7027c0cA767270bB1A474bA1338BA2A4d2", + ]) + }) + } + ) + + context( + "when L2 deposit owner is not properly encoded in the extra data", + () => { + it("should throw", async () => { + await expect( + depositorHandle.initializeDeposit( + depositTx, + depositOutputIndex, + { + ...deposit, + extraData: undefined, // Set empty extra data. + }, + vault + ) + ).to.be.rejectedWith("Extra data is required") + }) + } + ) + }) + }) + + describe("BaseL2TBTCToken", () => { + let tokenContract: MockContract + let tokenHandle: BaseL2TBTCToken + + beforeEach(async () => { + const [signer] = new MockProvider().getWallets() + + tokenContract = await deployMockContract( + signer, + `${JSON.stringify(BaseL2TBTCTokenABI)}` + ) + + tokenHandle = new BaseL2TBTCToken( + { + address: tokenContract.address, + signerOrProvider: signer, + }, + Chains.Base.BaseSepolia + ) + }) + + describe("balanceOf", () => { + let balance: BigNumber + + const identifier: ChainIdentifier = EthereumAddress.from( + "934b98637ca318a4d6e7ca6ffd1690b8e77df637" + ) + + beforeEach(async () => { + await tokenContract.mock.balanceOf.returns(10) + + balance = await tokenHandle.balanceOf(identifier) + }) + + it("should call the contract with the right parameter", async () => { + assertContractCalledWith(tokenContract, "balanceOf", [ + "0x934b98637ca318a4d6e7ca6ffd1690b8e77df637", + ]) + }) + + it("should return the balance", async () => { + expect(balance).to.equal(10) + }) + }) + }) +}) diff --git a/typescript/test/lib/ethereum.test.ts b/typescript/test/lib/ethereum.test.ts index b4fb9650a..3f65a4c97 100644 --- a/typescript/test/lib/ethereum.test.ts +++ b/typescript/test/lib/ethereum.test.ts @@ -5,20 +5,30 @@ import { EthereumBridge, EthereumTBTCToken, ethereumAddressFromSigner, - ethereumNetworkFromSigner, Hex, + chainIdFromSigner, + Chains, + BitcoinRawTxVectors, + DepositReceipt, + ChainIdentifier, + EthereumL1BitcoinDepositor, + EthereumCrossChainExtraDataEncoder, } from "../../src" import { deployMockContract, MockContract, } from "@ethereum-waffle/mock-contract" -import chai, { assert, expect } from "chai" +import chai, { expect } from "chai" import { BigNumber, Wallet, constants, getDefaultProvider, utils } from "ethers" +import { MockProvider } from "@ethereum-waffle/provider" +import { waffleChai } from "@ethereum-waffle/chai" +import { assertContractCalledWith } from "../utils/helpers" + +// ABI imports. import { abi as BridgeABI } from "@keep-network/tbtc-v2/artifacts/Bridge.json" import { abi as TBTCTokenABI } from "@keep-network/tbtc-v2/artifacts/TBTC.json" import { abi as WalletRegistryABI } from "@keep-network/ecdsa/artifacts/WalletRegistry.json" -import { MockProvider } from "@ethereum-waffle/provider" -import { waffleChai } from "@ethereum-waffle/chai" +import { abi as BaseL1BitcoinDepositorABI } from "../../src/lib/ethereum/artifacts/sepolia/BaseL1BitcoinDepositor.json" chai.use(waffleChai) @@ -559,35 +569,6 @@ describe("Ethereum", () => { }) }) - // eslint-disable-next-line valid-jsdoc - /** - * Custom assertion used to check whether the given contract function was - * called with correct parameters. This is a workaround for Waffle's - * `calledOnContractWith` assertion bug described in the following issue: - * https://github.com/TrueFiEng/Waffle/issues/468 - * @param contract Contract handle - * @param functionName Name of the checked function - * @param parameters Array of function's parameters - */ - function assertContractCalledWith( - contract: MockContract, - functionName: string, - parameters: any[] - ) { - const functionCallData = contract.interface.encodeFunctionData( - functionName, - parameters - ) - - assert( - (contract.provider as unknown as MockProvider).callHistory.some( - (call) => - call.address === contract.address && call.data === functionCallData - ), - "Expected contract function was not called" - ) - } - describe("EthereumTBTCToken", () => { let tbtcToken: MockContract let tokenHandle: EthereumTBTCToken @@ -674,6 +655,183 @@ describe("Ethereum", () => { }) }) + describe("EthereumL1BitcoinDepositor", () => { + let depositorContract: MockContract + let depositorHandle: EthereumL1BitcoinDepositor + + beforeEach(async () => { + const [signer] = new MockProvider().getWallets() + + depositorContract = await deployMockContract( + signer, + // Use Base for testing but this can be any supported L2 chain. + `${JSON.stringify(BaseL1BitcoinDepositorABI)}` + ) + + depositorHandle = new EthereumL1BitcoinDepositor( + { + address: depositorContract.address, + signerOrProvider: signer, + }, + Chains.Ethereum.Sepolia, + "Base" + ) + }) + + describe("initializeDeposit", () => { + // Just short byte strings for clarity. + const depositTx: BitcoinRawTxVectors = { + version: Hex.from("00000000"), + inputs: Hex.from("11111111"), + outputs: Hex.from("22222222"), + locktime: Hex.from("33333333"), + } + const depositOutputIndex: number = 2 + const deposit: DepositReceipt = { + depositor: EthereumAddress.from( + "934b98637ca318a4d6e7ca6ffd1690b8e77df637" + ), + walletPublicKeyHash: Hex.from( + "8db50eb52063ea9d98b3eac91489a90f738986f6" + ), + refundPublicKeyHash: Hex.from( + "28e081f285138ccbe389c1eb8985716230129f89" + ), + blindingFactor: Hex.from("f9f0c90d00039523"), + refundLocktime: Hex.from("60bcea61"), + extraData: Hex.from( + "00000000000000000000000091fe5b7027c0cA767270bB1A474bA1338BA2A4d2" + ), + } + const vault: ChainIdentifier = EthereumAddress.from( + "82883a4c7a8dd73ef165deb402d432613615ced4" + ) + + context( + "when L2 deposit owner is properly encoded in the extra data", + () => { + beforeEach(async () => { + await depositorContract.mock.initializeDeposit.returns() + + await depositorHandle.initializeDeposit( + depositTx, + depositOutputIndex, + deposit, + vault + ) + }) + + it("should initialize the deposit", async () => { + assertContractCalledWith(depositorContract, "initializeDeposit", [ + { + version: "0x00000000", + inputVector: "0x11111111", + outputVector: "0x22222222", + locktime: "0x33333333", + }, + { + fundingOutputIndex: 2, + blindingFactor: "0xf9f0c90d00039523", + walletPubKeyHash: "0x8db50eb52063ea9d98b3eac91489a90f738986f6", + refundPubKeyHash: "0x28e081f285138ccbe389c1eb8985716230129f89", + refundLocktime: "0x60bcea61", + vault: "0x82883a4c7a8dd73ef165deb402d432613615ced4", + }, + "0x91fe5b7027c0cA767270bB1A474bA1338BA2A4d2", + ]) + }) + } + ) + + context( + "when L2 deposit owner is not properly encoded in the extra data", + () => { + it("should throw", async () => { + await expect( + depositorHandle.initializeDeposit( + depositTx, + depositOutputIndex, + { + ...deposit, + extraData: undefined, // Set empty extra data. + }, + vault + ) + ).to.be.rejectedWith("Extra data is required") + }) + } + ) + }) + }) + + describe("EthereumCrossChainExtraDataEncoder", () => { + let encoder: EthereumCrossChainExtraDataEncoder + + beforeEach(async () => { + encoder = new EthereumCrossChainExtraDataEncoder() + }) + + describe("encodeDepositOwner", () => { + context("when the deposit owner is a proper Ethereum address", () => { + it("should encode the deposit owner", () => { + const depositOwner = EthereumAddress.from( + "91fe5b7027c0cA767270bB1A474bA1338BA2A4d2" + ) + + expect(encoder.encodeDepositOwner(depositOwner)).to.be.eql( + Hex.from( + "00000000000000000000000091fe5b7027c0cA767270bB1A474bA1338BA2A4d2" + ) + ) + }) + }) + + context("when the deposit owner is not a proper Ethereum address", () => { + it("should throw", () => { + // Build a crap address. + const depositOwner = { + identifierHex: "1234", + equals: () => false, + } + + expect(() => encoder.encodeDepositOwner(depositOwner)).to.throw( + "Invalid Ethereum address" + ) + }) + }) + }) + + describe("decodeDepositOwner", () => { + context("when the extra data holds a proper Ethereum address", () => { + it("should decode the deposit owner", () => { + const extraData = Hex.from( + "00000000000000000000000091fe5b7027c0cA767270bB1A474bA1338BA2A4d2" + ) + + const actualAddress = encoder.decodeDepositOwner(extraData) + const expectedAddress = EthereumAddress.from( + "91fe5b7027c0cA767270bB1A474bA1338BA2A4d2" + ) + expect(expectedAddress.equals(actualAddress)).to.be.true + }) + }) + + context( + "when the extra data doesn't hold a proper Ethereum address", + () => { + it("should throw", () => { + // Build crap extra data. + const extraData = Hex.from("0000000000000000000000001234") + + expect(() => encoder.decodeDepositOwner(extraData)).to.throw( + "Invalid Ethereum address" + ) + }) + } + ) + }) + }) + describe("ethereumAddressFromSigner", () => { context("when the signer is a wallet", () => { const [mockSigner] = new MockProvider().getWallets() @@ -692,20 +850,18 @@ describe("Ethereum", () => { }) }) - describe("ethereumNetworkFromSigner", () => { + describe("chainIdFromSigner", () => { context("when the signer is a wallet", () => { const [mockSigner] = new MockProvider().getWallets() it("should return the signer's network", async () => { - expect(await ethereumNetworkFromSigner(mockSigner)).to.be.eql("local") + expect(await chainIdFromSigner(mockSigner)).to.be.eql("1337") }) }) context("when the signer is a provider", () => { const mockProvider = getDefaultProvider() it("should return the signer's network", async () => { - expect(await ethereumNetworkFromSigner(mockProvider)).to.be.eql( - "mainnet" - ) + expect(await chainIdFromSigner(mockProvider)).to.be.eql("1") }) }) }) diff --git a/typescript/test/services/deposits.test.ts b/typescript/test/services/deposits.test.ts index f7f08879c..05cdbdbc1 100644 --- a/typescript/test/services/deposits.test.ts +++ b/typescript/test/services/deposits.test.ts @@ -22,10 +22,15 @@ import { DepositsService, EthereumAddress, extractBitcoinRawTxVectors, + L2Chain, + CrossChainDepositor, + Hex, + CrossChainContracts, + ChainIdentifier, + BitcoinRawTxVectors, } from "../../src" import { MockBitcoinClient } from "../utils/mock-bitcoin-client" import { MockTBTCContracts } from "../utils/mock-tbtc-contracts" -import { Hex } from "../../src/lib/utils" import { txToJSON } from "../utils/helpers" import { depositRefundOfNonWitnessDepositAndWitnessRefunderAddress, @@ -34,6 +39,12 @@ import { refunderPrivateKey, } from "../data/deposit-refund" import { MockDepositorProxy } from "../utils/mock-depositor-proxy" +import { + MockCrossChainExtraDataEncoder, + MockL1BitcoinDepositor, + MockL2BitcoinDepositor, + MockL2TBTCToken, +} from "../utils/mock-cross-chain" describe("Deposits", () => { const depositCreatedAt: number = 1640181600 @@ -1620,7 +1631,12 @@ describe("Deposits", () => { let depositService: DepositsService beforeEach(async () => { - depositService = new DepositsService(tbtcContracts, bitcoinClient) + depositService = new DepositsService( + tbtcContracts, + bitcoinClient, + // Mock cross-chain contracts resolver. + (_: L2Chain) => undefined + ) }) context("when default depositor is not set", () => { @@ -1801,7 +1817,12 @@ describe("Deposits", () => { let depositService: DepositsService beforeEach(async () => { - depositService = new DepositsService(tbtcContracts, bitcoinClient) + depositService = new DepositsService( + tbtcContracts, + bitcoinClient, + // Mock cross-chain contracts resolver. + (_: L2Chain) => undefined + ) }) context("when active wallet is not set", () => { @@ -1967,6 +1988,208 @@ describe("Deposits", () => { }) }) }) + + describe("initiateCrossChainDeposit", () => { + const l2DepositOwner = EthereumAddress.from( + "934b98637ca318a4d6e7ca6ffd1690b8e77df637" + ) + const bitcoinClient = new MockBitcoinClient() + const tbtcContracts = new MockTBTCContracts() + let depositService: DepositsService + + context("when cross-chain contracts are not initialized", () => { + beforeEach(async () => { + depositService = new DepositsService( + tbtcContracts, + bitcoinClient, + // Mock cross-chain contracts resolver that always returns undefined. + (_: L2Chain) => undefined + ) + }) + + it("should throw", async () => { + await expect( + depositService.initiateCrossChainDeposit( + "mjc2zGWypwpNyDi4ZxGbBNnUA84bfgiwYc", + "Base" + ) + ).to.be.rejectedWith("Cross-chain contracts for Base not initialized") + }) + }) + + context("when cross-chain contracts are initialized", () => { + let l2BitcoinDepositor: MockL2BitcoinDepositor + let l1BitcoinDepositor: MockL1BitcoinDepositor + let crossChainContracts: CrossChainContracts + + beforeEach(async () => { + const l2BitcoinDepositorEncoder = new MockCrossChainExtraDataEncoder() + // Set valid 32-byte extra data as initiateCrossChainDeposit + // performs length and content checks on the extra data. + l2BitcoinDepositorEncoder.setEncoding( + l2DepositOwner, + Hex.from(`000000000000000000000000${l2DepositOwner.identifierHex}`) + ) + l2BitcoinDepositor = new MockL2BitcoinDepositor( + EthereumAddress.from("49D1e49013Df517Ea30306DE2F462F2D0170212f"), + l2BitcoinDepositorEncoder + ) + + l1BitcoinDepositor = new MockL1BitcoinDepositor( + EthereumAddress.from("F4c1B212B37775769c73353264ac48dD7fA5B71E"), + new MockCrossChainExtraDataEncoder() + ) + + crossChainContracts = { + l2TbtcToken: new MockL2TBTCToken(), + l2BitcoinDepositor: l2BitcoinDepositor, + l1BitcoinDepositor: l1BitcoinDepositor, + } + + const crossChainContractsResolver = ( + l2ChainName: L2Chain + ): CrossChainContracts | undefined => { + if (l2ChainName === "Base") { + return crossChainContracts + } + } + + depositService = new DepositsService( + tbtcContracts, + bitcoinClient, + crossChainContractsResolver + ) + }) + + context("when L2 deposit owner cannot be resolved", () => { + it("should throw", async () => { + await expect( + depositService.initiateCrossChainDeposit( + "mjc2zGWypwpNyDi4ZxGbBNnUA84bfgiwYc", + "Base" + ) + ).to.be.rejectedWith("Cannot resolve L2 deposit owner") + }) + }) + + context("when L2 deposit owner can be resolved", () => { + beforeEach(async () => { + crossChainContracts.l2BitcoinDepositor.setDepositOwner( + l2DepositOwner + ) + }) + + context("when active wallet is not set", () => { + it("should throw", async () => { + await expect( + depositService.initiateCrossChainDeposit( + "mjc2zGWypwpNyDi4ZxGbBNnUA84bfgiwYc", + "Base" + ) + ).to.be.rejectedWith("Could not get active wallet public key") + }) + }) + + context("when active wallet is set", () => { + beforeEach(async () => { + tbtcContracts.bridge.setActiveWalletPublicKey( + Hex.from( + "03989d253b17a6a0f41838b84ff0d20e8898f9d7b1a98f2564da4cc29dcf8581d9" + ) + ) + }) + + context("when recovery address is incorrect", () => { + it("should throw", async () => { + await expect( + depositService.initiateCrossChainDeposit( + "2N5WZpig3vgpSdjSherS2Lv7GnPuxCvkQjT", // p2sh address + "Base" + ) + ).to.be.rejectedWith( + "Bitcoin recovery address must be P2PKH or P2WPKH" + ) + }) + }) + + context("when recovery address is correct", () => { + const assertCommonDepositProperties = ( + receipt: DepositReceipt + ) => { + expect(receipt.depositor).to.be.equal( + l1BitcoinDepositor.getChainIdentifier() + ) + + expect(receipt.walletPublicKeyHash).to.be.deep.equal( + Hex.from("8db50eb52063ea9d98b3eac91489a90f738986f6") + ) + + // Expect the refund locktime to be in the future. + const receiptTimestamp = BigNumber.from( + receipt.refundLocktime.reverse().toPrefixedString() + ).toNumber() + const currentTimestamp = Math.floor(new Date().getTime() / 1000) + expect(receiptTimestamp).to.be.greaterThan(currentTimestamp) + + // Expect blinding factor to be set and 8-byte long. + expect(receipt.blindingFactor).not.to.be.undefined + expect(receipt.blindingFactor.toBuffer().length).to.be.equal(8) + + expect(receipt.extraData).to.be.eql( + Hex.from( + `000000000000000000000000${l2DepositOwner.identifierHex}` + ) + ) + } + + context("when recovery address is P2PKH", () => { + let deposit: Deposit + + beforeEach(async () => { + deposit = await depositService.initiateCrossChainDeposit( + "mjc2zGWypwpNyDi4ZxGbBNnUA84bfgiwYc", + "Base" + ) + }) + + it("should initiate deposit correctly", async () => { + // Inspect the deposit object by looking at its receipt. + const receipt = deposit.getReceipt() + + assertCommonDepositProperties(receipt) + + expect(receipt.refundPublicKeyHash).to.be.deep.equal( + Hex.from("2cd680318747b720d67bf4246eb7403b476adb34") + ) + }) + }) + + context("when recovery address is P2WPKH", () => { + let deposit: Deposit + + beforeEach(async () => { + deposit = await depositService.initiateCrossChainDeposit( + "tb1qumuaw3exkxdhtut0u85latkqfz4ylgwstkdzsx", + "Base" + ) + }) + + it("should initiate deposit correctly", async () => { + // Inspect the deposit object by looking at its receipt. + const receipt = deposit.getReceipt() + + assertCommonDepositProperties(receipt) + + expect(receipt.refundPublicKeyHash).to.be.deep.equal( + Hex.from("e6f9d74726b19b75f16fe1e9feaec048aa4fa1d0") + ) + }) + }) + }) + }) + }) + }) + }) }) describe("DepositRefund", () => { @@ -2136,4 +2359,205 @@ describe("Deposits", () => { }) }) }) + + describe("CrossChainDepositor", () => { + const l2DepositOwner = EthereumAddress.from( + "a7C94958CDC477feE1F7D78705275238134699F5" + ) + + let l2BitcoinDepositor: MockL2BitcoinDepositor + let l1BitcoinDepositor: MockL1BitcoinDepositor + let crossChainContracts: CrossChainContracts + let depositor: CrossChainDepositor + + beforeEach(async () => { + const l2BitcoinDepositorAddress = EthereumAddress.from( + "49D1e49013Df517Ea30306DE2F462F2D0170212f" + ) + const l2BitcoinDepositorEncoder = new MockCrossChainExtraDataEncoder() + l2BitcoinDepositorEncoder.setEncoding(l2DepositOwner, Hex.from("00E2")) + l2BitcoinDepositor = new MockL2BitcoinDepositor( + l2BitcoinDepositorAddress, + l2BitcoinDepositorEncoder + ) + + const l1BitcoinDepositorAddress = EthereumAddress.from( + "F4c1B212B37775769c73353264ac48dD7fA5B71E" + ) + const l1BitcoinDepositorEncoder = new MockCrossChainExtraDataEncoder() + l1BitcoinDepositorEncoder.setEncoding(l2DepositOwner, Hex.from("00E1")) + l1BitcoinDepositor = new MockL1BitcoinDepositor( + l1BitcoinDepositorAddress, + l1BitcoinDepositorEncoder + ) + + crossChainContracts = { + l2TbtcToken: new MockL2TBTCToken(), + l2BitcoinDepositor: l2BitcoinDepositor, + l1BitcoinDepositor: l1BitcoinDepositor, + } + + depositor = new CrossChainDepositor(crossChainContracts) + }) + + describe("getChainIdentifier", () => { + it("should return the chain identifier of L1BitcoinDepositor contract", () => { + const actual = depositor.getChainIdentifier() + const expected = + crossChainContracts.l1BitcoinDepositor.getChainIdentifier() + + expect(expected.equals(actual)).to.be.true + }) + }) + + describe("extraData", () => { + context( + "when the deposit owner is not set in the L2BitcoinDepositor contract", + () => { + it("should throw", () => { + expect(() => depositor.extraData()).to.throw( + "Cannot resolve L2 deposit owner" + ) + }) + } + ) + + context( + "when the deposit owner is set in the L2BitcoinDepositor contract", + () => { + beforeEach(async () => { + crossChainContracts.l2BitcoinDepositor.setDepositOwner( + l2DepositOwner + ) + }) + + context("when reveal mode is L2Transaction", () => { + beforeEach(async () => { + depositor = new CrossChainDepositor( + crossChainContracts, + "L2Transaction" + ) + }) + + it("should return the extra data encoded using the L2BitcoinDepositor contract", async () => { + const actual = depositor.extraData() + const expected = Hex.from("00E2") + + expect(expected.equals(actual)).to.be.true + }) + }) + + context("when reveal mode is L1Transaction", () => { + beforeEach(async () => { + depositor = new CrossChainDepositor( + crossChainContracts, + "L1Transaction" + ) + }) + + it("should return the extra data encoded using the L1BitcoinDepositor contract", async () => { + const actual = depositor.extraData() + const expected = Hex.from("00E1") + + expect(expected.equals(actual)).to.be.true + }) + }) + } + ) + }) + + describe("revealDeposit", () => { + // Just short byte strings for clarity. + const depositTx: BitcoinRawTxVectors = { + version: Hex.from("00000000"), + inputs: Hex.from("11111111"), + outputs: Hex.from("22222222"), + locktime: Hex.from("33333333"), + } + const depositOutputIndex: number = 2 + const deposit: DepositReceipt = { + depositor: EthereumAddress.from( + "934b98637ca318a4d6e7ca6ffd1690b8e77df637" + ), + walletPublicKeyHash: Hex.from( + "8db50eb52063ea9d98b3eac91489a90f738986f6" + ), + refundPublicKeyHash: Hex.from( + "28e081f285138ccbe389c1eb8985716230129f89" + ), + blindingFactor: Hex.from("f9f0c90d00039523"), + refundLocktime: Hex.from("60bcea61"), + extraData: Hex.from( + `000000000000000000000000${l2DepositOwner.identifierHex}` + ), + } + const vault: ChainIdentifier = EthereumAddress.from( + "82883a4c7a8dd73ef165deb402d432613615ced4" + ) + + context("when reveal mode is L2Transaction", () => { + beforeEach(async () => { + depositor = new CrossChainDepositor( + crossChainContracts, + "L2Transaction" + ) + + await depositor.revealDeposit( + depositTx, + depositOutputIndex, + deposit, + vault + ) + }) + + it("should reveal the deposit using the L2BitcoinDepositor contract", async () => { + expect(l1BitcoinDepositor.initializeDepositCalls.length).to.be.equal( + 0 + ) + + expect(l2BitcoinDepositor.initializeDepositCalls.length).to.be.equal( + 1 + ) + expect(l2BitcoinDepositor.initializeDepositCalls[0]).to.be.eql({ + depositTx, + depositOutputIndex, + deposit, + vault, + }) + }) + }) + + context("when reveal mode is L1Transaction", () => { + beforeEach(async () => { + depositor = new CrossChainDepositor( + crossChainContracts, + "L1Transaction" + ) + + await depositor.revealDeposit( + depositTx, + depositOutputIndex, + deposit, + vault + ) + }) + + it("should reveal the deposit using the L1BitcoinDepositor contract", async () => { + expect(l2BitcoinDepositor.initializeDepositCalls.length).to.be.equal( + 0 + ) + + expect(l1BitcoinDepositor.initializeDepositCalls.length).to.be.equal( + 1 + ) + expect(l1BitcoinDepositor.initializeDepositCalls[0]).to.be.eql({ + depositTx, + depositOutputIndex, + deposit, + vault, + }) + }) + }) + }) + }) }) diff --git a/typescript/test/utils/helpers.ts b/typescript/test/utils/helpers.ts index 8378ea344..3175bea9d 100644 --- a/typescript/test/utils/helpers.ts +++ b/typescript/test/utils/helpers.ts @@ -1,5 +1,8 @@ import { BitcoinNetwork, toBitcoinJsLibNetwork, Hex } from "../../src" import { Transaction, address } from "bitcoinjs-lib" +import { MockContract } from "@ethereum-waffle/mock-contract" +import { assert } from "chai" +import { MockProvider } from "@ethereum-waffle/provider" /** * Represents a structured JSON format for a Bitcoin transaction. It includes @@ -57,3 +60,32 @@ export function txToJSON( return txJSON } + +// eslint-disable-next-line valid-jsdoc +/** + * Custom assertion used to check whether the given contract function was + * called with correct parameters. This is a workaround for Waffle's + * `calledOnContractWith` assertion bug described in the following issue: + * https://github.com/TrueFiEng/Waffle/issues/468 + * @param contract Contract handle + * @param functionName Name of the checked function + * @param parameters Array of function's parameters + */ +export function assertContractCalledWith( + contract: MockContract, + functionName: string, + parameters: any[] +) { + const functionCallData = contract.interface.encodeFunctionData( + functionName, + parameters + ) + + assert( + (contract.provider as unknown as MockProvider).callHistory.some( + (call) => + call.address === contract.address && call.data === functionCallData + ), + "Expected contract function was not called" + ) +} diff --git a/typescript/test/utils/mock-cross-chain.ts b/typescript/test/utils/mock-cross-chain.ts new file mode 100644 index 000000000..e9ed8e3f6 --- /dev/null +++ b/typescript/test/utils/mock-cross-chain.ts @@ -0,0 +1,136 @@ +import { + ChainIdentifier, + L2TBTCToken, + L1BitcoinDepositor, + L2BitcoinDepositor, + CrossChainExtraDataEncoder, + BitcoinRawTxVectors, + DepositReceipt, + Hex, +} from "../../src" +import { BigNumber } from "ethers" + +export class MockL2TBTCToken implements L2TBTCToken { + balanceOf(identifier: ChainIdentifier): Promise { + throw new Error("Not supported") + } + + getChainIdentifier(): ChainIdentifier { + throw new Error("Not supported") + } +} + +export class MockL2BitcoinDepositor implements L2BitcoinDepositor { + readonly #chainIdentifier: ChainIdentifier + readonly #encoder: CrossChainExtraDataEncoder + #depositOwner: ChainIdentifier | undefined + public readonly initializeDepositCalls: InitializeDepositCall[] = [] + + constructor( + chainIdentifier: ChainIdentifier, + encoder: CrossChainExtraDataEncoder + ) { + this.#chainIdentifier = chainIdentifier + this.#encoder = encoder + } + + extraDataEncoder(): CrossChainExtraDataEncoder { + return this.#encoder + } + + getChainIdentifier(): ChainIdentifier { + return this.#chainIdentifier + } + + getDepositOwner(): ChainIdentifier | undefined { + return this.#depositOwner + } + + setDepositOwner(depositOwner: ChainIdentifier): void { + this.#depositOwner = depositOwner + } + + initializeDeposit( + depositTx: BitcoinRawTxVectors, + depositOutputIndex: number, + deposit: DepositReceipt, + vault?: ChainIdentifier + ): Promise { + this.initializeDepositCalls.push({ + depositTx, + depositOutputIndex, + deposit, + vault, + }) + + return Promise.resolve(Hex.from("0x02")) + } +} + +export class MockL1BitcoinDepositor implements L1BitcoinDepositor { + readonly #chainIdentifier: ChainIdentifier + readonly #encoder: CrossChainExtraDataEncoder + public readonly initializeDepositCalls: InitializeDepositCall[] = [] + + constructor( + chainIdentifier: ChainIdentifier, + encoder: CrossChainExtraDataEncoder + ) { + this.#chainIdentifier = chainIdentifier + this.#encoder = encoder + } + + extraDataEncoder(): CrossChainExtraDataEncoder { + return this.#encoder + } + + getChainIdentifier(): ChainIdentifier { + return this.#chainIdentifier + } + + initializeDeposit( + depositTx: BitcoinRawTxVectors, + depositOutputIndex: number, + deposit: DepositReceipt, + vault?: ChainIdentifier + ): Promise { + this.initializeDepositCalls.push({ + depositTx, + depositOutputIndex, + deposit, + vault, + }) + + return Promise.resolve(Hex.from("0x01")) + } +} + +export class MockCrossChainExtraDataEncoder + implements CrossChainExtraDataEncoder +{ + #encodings: Map = new Map() + + setEncoding(depositOwner: ChainIdentifier, extraData: Hex): void { + this.#encodings.set(depositOwner.identifierHex, extraData) + } + + encodeDepositOwner(depositOwner: ChainIdentifier): Hex { + const extraData = this.#encodings.get(depositOwner.identifierHex) + if (!extraData) { + throw new Error("Encoding not found") + } + + return extraData + } + + decodeDepositOwner(data: Hex): ChainIdentifier { + throw new Error("Not supported") + } +} + +type InitializeDepositCall = { + depositTx: BitcoinRawTxVectors + depositOutputIndex: number + deposit: DepositReceipt + vault?: ChainIdentifier +} diff --git a/typescript/yarn.lock b/typescript/yarn.lock index 5e86c6ab9..07666f31a 100644 --- a/typescript/yarn.lock +++ b/typescript/yarn.lock @@ -1516,7 +1516,18 @@ resolved "https://registry.yarnpkg.com/@keep-network/bitcoin-spv-sol/-/bitcoin-spv-sol-3.4.0-solc-0.8.tgz#8b44c246ffab8ea993efe196f6bf385b1a3b84dc" integrity sha512-KlpY9BbasyLvYXSS7dsJktgRChu/yjdFLOX8ldGA/pltLicCm/l0F4oqxL8wSws9XD12vq9x0B5qzPygVLB2TQ== -"@keep-network/ecdsa@2.1.0-dev.17", "@keep-network/ecdsa@development": +"@keep-network/ecdsa@2.1.0-dev.19": + version "2.1.0-dev.19" + resolved "https://registry.yarnpkg.com/@keep-network/ecdsa/-/ecdsa-2.1.0-dev.19.tgz#749af8bd65f70135d1734f7c5f9bff82ae308fdb" + integrity sha512-cyqRqK/sOqyaXZWY/O9ij6EINQuJ+bHLMiuufOFyP5YCj4GCuNqOcCytGAZPT+mED/0J/xn0vm+fgiCBq/uJkQ== + dependencies: + "@keep-network/random-beacon" "2.1.0-dev.18" + "@keep-network/sortition-pools" "^2.0.0-pre.16" + "@openzeppelin/contracts" "^4.6.0" + "@openzeppelin/contracts-upgradeable" "^4.6.0" + "@threshold-network/solidity-contracts" "1.3.0-dev.12" + +"@keep-network/ecdsa@development": version "2.1.0-dev.17" resolved "https://registry.yarnpkg.com/@keep-network/ecdsa/-/ecdsa-2.1.0-dev.17.tgz#2e6abea11c094adfa9f52dfe0e7d3befa5fe2dfb" integrity sha512-48zLogWDObqf3uGffDd8N2iP7m3rBinF+tAl7DidY/87eqWNydhpbO4j1H5i9vZ+Axi6nOQcuvpLlS7p9pjOFw== @@ -1567,6 +1578,16 @@ "@thesis/solidity-contracts" "github:thesis/solidity-contracts#4985bcf" "@threshold-network/solidity-contracts" "1.3.0-dev.8" +"@keep-network/random-beacon@2.1.0-dev.18": + version "2.1.0-dev.18" + resolved "https://registry.yarnpkg.com/@keep-network/random-beacon/-/random-beacon-2.1.0-dev.18.tgz#2647731eea35f931afb565988cc8d8cf6a34f6b7" + integrity sha512-UrVq///+jqOLQ5k8/aFvD1ZUMvVe49iS81U8mDoi9A005FiQzKUK9QFKv3Z0h6joG4prF/hlABRTEQ1UA7tgRA== + dependencies: + "@keep-network/sortition-pools" "^2.0.0-pre.16" + "@openzeppelin/contracts" "4.7.3" + "@thesis/solidity-contracts" "github:thesis/solidity-contracts#4985bcf" + "@threshold-network/solidity-contracts" "1.3.0-dev.11" + "@keep-network/sortition-pools@1.2.0-dev.1": version "1.2.0-dev.1" resolved "https://registry.yarnpkg.com/@keep-network/sortition-pools/-/sortition-pools-1.2.0-dev.1.tgz#2ee371f1dd1ff71f6d05c9ddc2a83a4a93ff56b3" @@ -1583,13 +1604,13 @@ "@thesis/solidity-contracts" "github:thesis/solidity-contracts#4985bcf" "@keep-network/tbtc-v2@development": - version "1.6.0-dev.14" - resolved "https://registry.yarnpkg.com/@keep-network/tbtc-v2/-/tbtc-v2-1.6.0-dev.14.tgz#45e5ec1ca44bd47c8beb246b9718ce93b191b4e7" - integrity sha512-opUFWtQ3tSPCG0z9FcsOVTp4ATA+XyL2nQK9GgJ6BRfVv3RAYKM9Z97NFcAE9bjcbfwvYKg8P64YY680e9XFvA== + version "1.7.0-dev.1" + resolved "https://registry.yarnpkg.com/@keep-network/tbtc-v2/-/tbtc-v2-1.7.0-dev.1.tgz#6bac04acb7b63c015940716d6411e9bdd18e7ff8" + integrity sha512-T8hT8YVTP+WvzSC/xEMvWKIuVdiOoVWMoew2zNWAgryotP+Kmhx7zCcEJ9EjsI2LV03FwQO3uvvVjTA89PPieg== dependencies: "@keep-network/bitcoin-spv-sol" "3.4.0-solc-0.8" - "@keep-network/ecdsa" "2.1.0-dev.17" - "@keep-network/random-beacon" "2.1.0-dev.17" + "@keep-network/ecdsa" "2.1.0-dev.19" + "@keep-network/random-beacon" "2.1.0-dev.18" "@keep-network/tbtc" "1.1.2-dev.1" "@openzeppelin/contracts" "^4.8.1" "@openzeppelin/contracts-upgradeable" "^4.8.1" @@ -1955,6 +1976,16 @@ "@openzeppelin/contracts-upgradeable" "~4.5.2" "@thesis/solidity-contracts" "github:thesis/solidity-contracts#4985bcf" +"@threshold-network/solidity-contracts@1.3.0-dev.12": + version "1.3.0-dev.12" + resolved "https://registry.yarnpkg.com/@threshold-network/solidity-contracts/-/solidity-contracts-1.3.0-dev.12.tgz#55e2d789ac6cd2180f8f55cd876a5bdd0a9b45e6" + integrity sha512-06EF583uEwko3ik7qjnMOg+sJ+Vb7YWkqag4a9xZq8Mmy8rifpmLjnfDKCVGeKbUis3uI++pTGC9U/EfvVOrlQ== + dependencies: + "@keep-network/keep-core" ">1.8.1-dev <1.8.1-goerli" + "@openzeppelin/contracts" "~4.5.0" + "@openzeppelin/contracts-upgradeable" "~4.5.2" + "@thesis/solidity-contracts" "github:thesis/solidity-contracts#4985bcf" + "@threshold-network/solidity-contracts@1.3.0-dev.8": version "1.3.0-dev.8" resolved "https://registry.yarnpkg.com/@threshold-network/solidity-contracts/-/solidity-contracts-1.3.0-dev.8.tgz#6de25dc6ce374cfbdf3b67c72097044631222f3a"