1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
import * as _ from 'lodash';
import BigNumber from 'bignumber.js';
import {Web3Wrapper} from '../web3_wrapper';
import {ContractWrapper} from './contract_wrapper';
import {TokenWrapper} from './token_wrapper';
import {EtherTokenContract, ZeroExError} from '../types';
import {assert} from '../utils/assert';
import {artifacts} from '../artifacts';
/**
* This class includes all the functionality related to interacting with a wrapped Ether ERC20 token contract.
* The caller can convert ETH into the equivalent number of wrapped ETH ERC20 tokens and back.
*/
export class EtherTokenWrapper extends ContractWrapper {
private _etherTokenContractIfExists?: EtherTokenContract;
private _tokenWrapper: TokenWrapper;
private _contractAddressIfExists?: string;
constructor(web3Wrapper: Web3Wrapper, tokenWrapper: TokenWrapper, contractAddressIfExists?: string) {
super(web3Wrapper);
this._tokenWrapper = tokenWrapper;
this._contractAddressIfExists = contractAddressIfExists;
}
/**
* Deposit ETH into the Wrapped ETH smart contract and issues the equivalent number of wrapped ETH tokens
* to the depositor address. These wrapped ETH tokens can be used in 0x trades and are redeemable for 1-to-1
* for ETH.
* @param amountInWei Amount of ETH in Wei the caller wishes to deposit.
* @param depositor The hex encoded user Ethereum address that would like to make the deposit.
* @return Transaction hash.
*/
public async depositAsync(amountInWei: BigNumber, depositor: string): Promise<string> {
assert.isValidBaseUnitAmount('amountInWei', amountInWei);
await assert.isSenderAddressAsync('depositor', depositor, this._web3Wrapper);
const ethBalanceInWei = await this._web3Wrapper.getBalanceInWeiAsync(depositor);
assert.assert(ethBalanceInWei.gte(amountInWei), ZeroExError.InsufficientEthBalanceForDeposit);
const wethContract = await this._getEtherTokenContractAsync();
const txHash = await wethContract.deposit.sendTransactionAsync({
from: depositor,
value: amountInWei,
});
return txHash;
}
/**
* Withdraw ETH to the withdrawer's address from the wrapped ETH smart contract in exchange for the
* equivalent number of wrapped ETH tokens.
* @param amountInWei Amount of ETH in Wei the caller wishes to withdraw.
* @param withdrawer The hex encoded user Ethereum address that would like to make the withdrawl.
* @return Transaction hash.
*/
public async withdrawAsync(amountInWei: BigNumber, withdrawer: string): Promise<string> {
assert.isValidBaseUnitAmount('amountInWei', amountInWei);
await assert.isSenderAddressAsync('withdrawer', withdrawer, this._web3Wrapper);
const wethContractAddress = this.getContractAddress();
const WETHBalanceInBaseUnits = await this._tokenWrapper.getBalanceAsync(wethContractAddress, withdrawer);
assert.assert(WETHBalanceInBaseUnits.gte(amountInWei), ZeroExError.InsufficientWEthBalanceForWithdrawal);
const wethContract = await this._getEtherTokenContractAsync();
const txHash = await wethContract.withdraw.sendTransactionAsync(amountInWei, {
from: withdrawer,
});
return txHash;
}
/**
* Retrieves the Wrapped Ether token contract address
* @return The Wrapped Ether token contract address
*/
public getContractAddress(): string {
const networkId = this._web3Wrapper.getNetworkId();
if (_.isUndefined(this._contractAddressIfExists)) {
const contractAddress = artifacts.EtherTokenArtifact.networks[networkId].address;
if (_.isUndefined(contractAddress)) {
throw new Error(ZeroExError.ExchangeContractDoesNotExist);
}
return contractAddress;
} else {
return this._contractAddressIfExists;
}
}
private _invalidateContractInstance(): void {
delete this._etherTokenContractIfExists;
}
private async _getEtherTokenContractAsync(): Promise<EtherTokenContract> {
if (!_.isUndefined(this._etherTokenContractIfExists)) {
return this._etherTokenContractIfExists;
}
const contractInstance = await this._instantiateContractIfExistsAsync<EtherTokenContract>(
artifacts.EtherTokenArtifact, this._contractAddressIfExists,
);
this._etherTokenContractIfExists = contractInstance as EtherTokenContract;
return this._etherTokenContractIfExists;
}
}
|