Compare commits
	
		
			29 Commits
		
	
	
		
			@0x/contra
			...
			protocol@2
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					2f1b520409 | ||
| 
						 | 
					21b4eb3d26 | ||
| 
						 | 
					644f6c7d28 | ||
| 
						 | 
					0647b9e4f8 | ||
| 
						 | 
					82d42eeede | ||
| 
						 | 
					6ef4d95043 | ||
| 
						 | 
					6044140f86 | ||
| 
						 | 
					4da1ef0f56 | ||
| 
						 | 
					8c668a3918 | ||
| 
						 | 
					f1ff1cde39 | ||
| 
						 | 
					1668a24e31 | ||
| 
						 | 
					4b7c376d96 | ||
| 
						 | 
					bb4a9c656c | ||
| 
						 | 
					6ab07b6304 | ||
| 
						 | 
					8903f1ab01 | ||
| 
						 | 
					415535612a | ||
| 
						 | 
					5248a135c3 | ||
| 
						 | 
					602290925c | ||
| 
						 | 
					01813746e8 | ||
| 
						 | 
					7d668d8801 | ||
| 
						 | 
					797a00a33a | ||
| 
						 | 
					4b3d98f43c | ||
| 
						 | 
					9ff77c1cd5 | ||
| 
						 | 
					18a8351671 | ||
| 
						 | 
					9a994dfcd3 | ||
| 
						 | 
					b7adc5a889 | ||
| 
						 | 
					10b0d7f363 | ||
| 
						 | 
					e2c905a15f | ||
| 
						 | 
					8589ba728c | 
@@ -1,4 +1,13 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1637102971,
 | 
			
		||||
        "version": "3.3.23",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1635903615,
 | 
			
		||||
        "version": "3.3.22",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v3.3.23 - _November 16, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.3.22 - _November 3, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-erc20",
 | 
			
		||||
    "version": "3.3.22",
 | 
			
		||||
    "version": "3.3.23",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -53,8 +53,8 @@
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@0x/abi-gen": "^5.6.2",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.40",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.4.13",
 | 
			
		||||
        "@0x/contracts-utils": "^4.8.3",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.4.14",
 | 
			
		||||
        "@0x/contracts-utils": "^4.8.4",
 | 
			
		||||
        "@0x/dev-utils": "^4.2.9",
 | 
			
		||||
        "@0x/sol-compiler": "^4.7.5",
 | 
			
		||||
        "@0x/ts-doc-gen": "^0.0.28",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,13 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1637102971,
 | 
			
		||||
        "version": "5.4.14",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1635903615,
 | 
			
		||||
        "version": "5.4.13",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v5.4.14 - _November 16, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v5.4.13 - _November 3, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-test-utils",
 | 
			
		||||
    "version": "5.4.13",
 | 
			
		||||
    "version": "5.4.14",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -44,7 +44,7 @@
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0x/assert": "^3.0.29",
 | 
			
		||||
        "@0x/base-contract": "^6.4.2",
 | 
			
		||||
        "@0x/contract-addresses": "^6.8.1",
 | 
			
		||||
        "@0x/contract-addresses": "^6.9.0",
 | 
			
		||||
        "@0x/dev-utils": "^4.2.9",
 | 
			
		||||
        "@0x/json-schemas": "^6.3.0",
 | 
			
		||||
        "@0x/order-utils": "^10.4.28",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,13 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1637102971,
 | 
			
		||||
        "version": "1.4.6",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1635903615,
 | 
			
		||||
        "version": "1.4.5",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v1.4.6 - _November 16, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.4.5 - _November 3, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-treasury",
 | 
			
		||||
    "version": "1.4.5",
 | 
			
		||||
    "version": "1.4.6",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -47,12 +47,12 @@
 | 
			
		||||
    "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/treasury",
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@0x/abi-gen": "^5.6.2",
 | 
			
		||||
        "@0x/contract-addresses": "^6.8.1",
 | 
			
		||||
        "@0x/contract-addresses": "^6.9.0",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^3.7.19",
 | 
			
		||||
        "@0x/contracts-erc20": "^3.3.22",
 | 
			
		||||
        "@0x/contracts-erc20": "^3.3.23",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.40",
 | 
			
		||||
        "@0x/contracts-staking": "^2.0.45",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.4.13",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.4.14",
 | 
			
		||||
        "@0x/sol-compiler": "^4.7.5",
 | 
			
		||||
        "@0x/ts-doc-gen": "^0.0.28",
 | 
			
		||||
        "@0x/tslint-config": "^4.1.4",
 | 
			
		||||
@@ -73,7 +73,7 @@
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0x/base-contract": "^6.4.2",
 | 
			
		||||
        "@0x/protocol-utils": "^1.9.4",
 | 
			
		||||
        "@0x/protocol-utils": "^1.9.5",
 | 
			
		||||
        "@0x/subproviders": "^6.6.0",
 | 
			
		||||
        "@0x/types": "^3.3.4",
 | 
			
		||||
        "@0x/typescript-typings": "^5.2.1",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,13 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1637102971,
 | 
			
		||||
        "version": "4.8.4",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1635903615,
 | 
			
		||||
        "version": "4.8.3",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v4.8.4 - _November 16, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v4.8.3 - _November 3, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-utils",
 | 
			
		||||
    "version": "4.8.3",
 | 
			
		||||
    "version": "4.8.4",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -52,7 +52,7 @@
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@0x/abi-gen": "^5.6.2",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.40",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.4.13",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.4.14",
 | 
			
		||||
        "@0x/dev-utils": "^4.2.9",
 | 
			
		||||
        "@0x/order-utils": "^10.4.28",
 | 
			
		||||
        "@0x/sol-compiler": "^4.7.5",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,23 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1637102971,
 | 
			
		||||
        "version": "0.29.5",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "0.29.4",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Prevent EP ETH balance from reducing when executin mtxs",
 | 
			
		||||
                "pr": 365
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1637065617
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "0.29.3",
 | 
			
		||||
        "changes": [
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v0.29.5 - _November 16, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v0.29.4 - _November 16, 2021_
 | 
			
		||||
 | 
			
		||||
    * Prevent EP ETH balance from reducing when executin mtxs (#365)
 | 
			
		||||
 | 
			
		||||
## v0.29.3 - _November 3, 2021_
 | 
			
		||||
 | 
			
		||||
    * Register transformERC20() and remove transformERC20Staging() (#355)
 | 
			
		||||
 
 | 
			
		||||
@@ -78,7 +78,7 @@ contract MetaTransactionsFeature is
 | 
			
		||||
    /// @dev Name of this feature.
 | 
			
		||||
    string public constant override FEATURE_NAME = "MetaTransactions";
 | 
			
		||||
    /// @dev Version of this feature.
 | 
			
		||||
    uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 2, 0);
 | 
			
		||||
    uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 2, 1);
 | 
			
		||||
    /// @dev EIP712 typehash of the `MetaTransactionData` struct.
 | 
			
		||||
    bytes32 public immutable MTX_EIP712_TYPEHASH = keccak256(
 | 
			
		||||
        "MetaTransactionData("
 | 
			
		||||
@@ -105,6 +105,17 @@ contract MetaTransactionsFeature is
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Ensures that the ETH balance of `this` does not go below the
 | 
			
		||||
    ///      initial ETH balance before the call (excluding ETH attached to the call).
 | 
			
		||||
    modifier doesNotReduceEthBalance() {
 | 
			
		||||
        uint256 initialBalance = address(this).balance - msg.value;
 | 
			
		||||
        _;
 | 
			
		||||
        require(
 | 
			
		||||
            initialBalance <= address(this).balance,
 | 
			
		||||
            "MetaTransactionsFeature/ETH_LEAK"
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    constructor(address zeroExAddress)
 | 
			
		||||
        public
 | 
			
		||||
        FixinCommon()
 | 
			
		||||
@@ -140,6 +151,7 @@ contract MetaTransactionsFeature is
 | 
			
		||||
        payable
 | 
			
		||||
        override
 | 
			
		||||
        nonReentrant(REENTRANCY_MTX)
 | 
			
		||||
        doesNotReduceEthBalance
 | 
			
		||||
        refundsAttachedEth
 | 
			
		||||
        returns (bytes memory returnResult)
 | 
			
		||||
    {
 | 
			
		||||
@@ -164,6 +176,7 @@ contract MetaTransactionsFeature is
 | 
			
		||||
        payable
 | 
			
		||||
        override
 | 
			
		||||
        nonReentrant(REENTRANCY_MTX)
 | 
			
		||||
        doesNotReduceEthBalance
 | 
			
		||||
        refundsAttachedEth
 | 
			
		||||
        returns (bytes[] memory returnResults)
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
@@ -46,6 +46,10 @@ contract TestMetaTransactionsTransformERC20Feature is
 | 
			
		||||
        payable
 | 
			
		||||
        returns (uint256 outputTokenAmount)
 | 
			
		||||
    {
 | 
			
		||||
        if (msg.value == 555) {
 | 
			
		||||
            tx.origin.transfer(1);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (msg.value == 666) {
 | 
			
		||||
            revert('FAIL');
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-zero-ex",
 | 
			
		||||
    "version": "0.29.3",
 | 
			
		||||
    "version": "0.29.5",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -56,10 +56,10 @@
 | 
			
		||||
    "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/zero-ex",
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@0x/abi-gen": "^5.6.2",
 | 
			
		||||
        "@0x/contract-addresses": "^6.8.1",
 | 
			
		||||
        "@0x/contracts-erc20": "^3.3.22",
 | 
			
		||||
        "@0x/contract-addresses": "^6.9.0",
 | 
			
		||||
        "@0x/contracts-erc20": "^3.3.23",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.40",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.4.13",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.4.14",
 | 
			
		||||
        "@0x/dev-utils": "^4.2.9",
 | 
			
		||||
        "@0x/order-utils": "^10.4.28",
 | 
			
		||||
        "@0x/sol-compiler": "^4.7.5",
 | 
			
		||||
@@ -83,7 +83,7 @@
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0x/base-contract": "^6.4.2",
 | 
			
		||||
        "@0x/protocol-utils": "^1.9.4",
 | 
			
		||||
        "@0x/protocol-utils": "^1.9.5",
 | 
			
		||||
        "@0x/subproviders": "^6.6.0",
 | 
			
		||||
        "@0x/types": "^3.3.4",
 | 
			
		||||
        "@0x/typescript-typings": "^5.2.1",
 | 
			
		||||
 
 | 
			
		||||
@@ -38,6 +38,7 @@ blockchainTests.resets('MetaTransactions feature', env => {
 | 
			
		||||
    let nativeOrdersFeature: TestMetaTransactionsNativeOrdersFeatureContract;
 | 
			
		||||
 | 
			
		||||
    const MAX_FEE_AMOUNT = new BigNumber('1e18');
 | 
			
		||||
    const TRANSFORM_ERC20_ONE_WEI_VALUE = new BigNumber(555);
 | 
			
		||||
    const TRANSFORM_ERC20_FAILING_VALUE = new BigNumber(666);
 | 
			
		||||
    const TRANSFORM_ERC20_REENTER_VALUE = new BigNumber(777);
 | 
			
		||||
    const TRANSFORM_ERC20_BATCH_REENTER_VALUE = new BigNumber(888);
 | 
			
		||||
@@ -597,7 +598,7 @@ blockchainTests.resets('MetaTransactions feature', env => {
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('cannot reenter `executeMetaTransaction()`', async () => {
 | 
			
		||||
        it('cannot reduce initial ETH balance', async () => {
 | 
			
		||||
            const args = getRandomTransformERC20Args();
 | 
			
		||||
            const mtx = getRandomMetaTransaction({
 | 
			
		||||
                callData: transformERC20Feature
 | 
			
		||||
@@ -609,58 +610,23 @@ blockchainTests.resets('MetaTransactions feature', env => {
 | 
			
		||||
                        args.transformations,
 | 
			
		||||
                    )
 | 
			
		||||
                    .getABIEncodedTransactionData(),
 | 
			
		||||
                value: TRANSFORM_ERC20_REENTER_VALUE,
 | 
			
		||||
                value: TRANSFORM_ERC20_ONE_WEI_VALUE,
 | 
			
		||||
            });
 | 
			
		||||
            const mtxHash = mtx.getHash();
 | 
			
		||||
            const signature = await mtx.getSignatureWithProviderAsync(env.provider);
 | 
			
		||||
            const callOpts = {
 | 
			
		||||
                gasPrice: mtx.maxGasPrice,
 | 
			
		||||
                value: mtx.value,
 | 
			
		||||
            };
 | 
			
		||||
            const tx = feature.executeMetaTransaction(mtx, signature).awaitTransactionSuccessAsync(callOpts);
 | 
			
		||||
            return expect(tx).to.revertWith(
 | 
			
		||||
                new ZeroExRevertErrors.MetaTransactions.MetaTransactionCallFailedError(
 | 
			
		||||
                    mtxHash,
 | 
			
		||||
                    undefined,
 | 
			
		||||
                    new ZeroExRevertErrors.Common.IllegalReentrancyError(
 | 
			
		||||
                        feature.getSelector('executeMetaTransaction'),
 | 
			
		||||
                        REENTRANCY_FLAG_MTX,
 | 
			
		||||
                    ).encode(),
 | 
			
		||||
                ),
 | 
			
		||||
            // Send pre-existing ETH to the EP.
 | 
			
		||||
            await env.web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await env.web3Wrapper.sendTransactionAsync({
 | 
			
		||||
                    from: owner,
 | 
			
		||||
                    to: zeroEx.address,
 | 
			
		||||
                    value: new BigNumber(1),
 | 
			
		||||
                }),
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('cannot reenter `batchExecuteMetaTransactions()`', async () => {
 | 
			
		||||
            const args = getRandomTransformERC20Args();
 | 
			
		||||
            const mtx = getRandomMetaTransaction({
 | 
			
		||||
                callData: transformERC20Feature
 | 
			
		||||
                    .transformERC20(
 | 
			
		||||
                        args.inputToken,
 | 
			
		||||
                        args.outputToken,
 | 
			
		||||
                        args.inputTokenAmount,
 | 
			
		||||
                        args.minOutputTokenAmount,
 | 
			
		||||
                        args.transformations,
 | 
			
		||||
                    )
 | 
			
		||||
                    .getABIEncodedTransactionData(),
 | 
			
		||||
                value: TRANSFORM_ERC20_BATCH_REENTER_VALUE,
 | 
			
		||||
            });
 | 
			
		||||
            const mtxHash = mtx.getHash();
 | 
			
		||||
            const signature = await mtx.getSignatureWithProviderAsync(env.provider);
 | 
			
		||||
            const callOpts = {
 | 
			
		||||
                gasPrice: mtx.maxGasPrice,
 | 
			
		||||
                value: mtx.value,
 | 
			
		||||
            };
 | 
			
		||||
            const tx = feature.executeMetaTransaction(mtx, signature).awaitTransactionSuccessAsync(callOpts);
 | 
			
		||||
            return expect(tx).to.revertWith(
 | 
			
		||||
                new ZeroExRevertErrors.MetaTransactions.MetaTransactionCallFailedError(
 | 
			
		||||
                    mtxHash,
 | 
			
		||||
                    undefined,
 | 
			
		||||
                    new ZeroExRevertErrors.Common.IllegalReentrancyError(
 | 
			
		||||
                        feature.getSelector('batchExecuteMetaTransactions'),
 | 
			
		||||
                        REENTRANCY_FLAG_MTX,
 | 
			
		||||
                    ).encode(),
 | 
			
		||||
                ),
 | 
			
		||||
            );
 | 
			
		||||
            return expect(tx).to.revertWith('MetaTransactionsFeature/ETH_LEAK');
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
@@ -817,6 +783,37 @@ blockchainTests.resets('MetaTransactions feature', env => {
 | 
			
		||||
                ),
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('cannot reduce initial ETH balance', async () => {
 | 
			
		||||
            const args = getRandomTransformERC20Args();
 | 
			
		||||
            const mtx = getRandomMetaTransaction({
 | 
			
		||||
                callData: transformERC20Feature
 | 
			
		||||
                    .transformERC20(
 | 
			
		||||
                        args.inputToken,
 | 
			
		||||
                        args.outputToken,
 | 
			
		||||
                        args.inputTokenAmount,
 | 
			
		||||
                        args.minOutputTokenAmount,
 | 
			
		||||
                        args.transformations,
 | 
			
		||||
                    )
 | 
			
		||||
                    .getABIEncodedTransactionData(),
 | 
			
		||||
                value: TRANSFORM_ERC20_ONE_WEI_VALUE,
 | 
			
		||||
            });
 | 
			
		||||
            const signature = await mtx.getSignatureWithProviderAsync(env.provider);
 | 
			
		||||
            const callOpts = {
 | 
			
		||||
                gasPrice: mtx.maxGasPrice,
 | 
			
		||||
                value: mtx.value,
 | 
			
		||||
            };
 | 
			
		||||
            // Send pre-existing ETH to the EP.
 | 
			
		||||
            await env.web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await env.web3Wrapper.sendTransactionAsync({
 | 
			
		||||
                    from: owner,
 | 
			
		||||
                    to: zeroEx.address,
 | 
			
		||||
                    value: new BigNumber(1),
 | 
			
		||||
                }),
 | 
			
		||||
            );
 | 
			
		||||
            const tx = feature.batchExecuteMetaTransactions([mtx], [signature]).awaitTransactionSuccessAsync(callOpts);
 | 
			
		||||
            return expect(tx).to.revertWith('MetaTransactionsFeature/ETH_LEAK');
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('getMetaTransactionExecutedBlock()', () => {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,74 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "version": "16.37.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Changed Sushiswap router address",
 | 
			
		||||
                "pr": 373
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1637349338
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "16.36.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Specify liquid routes for FEI/TRIBE FXS/FRAX and OHM/FRAX",
 | 
			
		||||
                "pr": 371
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1637290768
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "16.35.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Add Beethoven X, MorpheusSwap and JetSwap to Fantom",
 | 
			
		||||
                "pr": 370
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1637206290
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "16.34.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Add support Celo",
 | 
			
		||||
                "pr": 367
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1637102971
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "16.33.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Add support for Uniswap V3 1 bps pools",
 | 
			
		||||
                "pr": 366
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1637065617
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "16.32.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Extended Quote Report",
 | 
			
		||||
                "pr": 361
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1636480845
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1635903615,
 | 
			
		||||
        "version": "16.31.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Added `Curve`, `Curve_V2` and `KyberDmm` to Avalanche",
 | 
			
		||||
                "pr": 363
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1635903615,
 | 
			
		||||
        "version": "16.30.1",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,34 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v16.37.0 - _November 19, 2021_
 | 
			
		||||
 | 
			
		||||
    * Changed Sushiswap router address (#373)
 | 
			
		||||
 | 
			
		||||
## v16.36.0 - _November 19, 2021_
 | 
			
		||||
 | 
			
		||||
    * Specify liquid routes for FEI/TRIBE FXS/FRAX and OHM/FRAX (#371)
 | 
			
		||||
 | 
			
		||||
## v16.35.0 - _November 18, 2021_
 | 
			
		||||
 | 
			
		||||
    * Add Beethoven X, MorpheusSwap and JetSwap to Fantom (#370)
 | 
			
		||||
 | 
			
		||||
## v16.34.0 - _November 16, 2021_
 | 
			
		||||
 | 
			
		||||
    * Add support Celo (#367)
 | 
			
		||||
 | 
			
		||||
## v16.33.0 - _November 16, 2021_
 | 
			
		||||
 | 
			
		||||
    * Add support for Uniswap V3 1 bps pools (#366)
 | 
			
		||||
 | 
			
		||||
## v16.32.0 - _November 9, 2021_
 | 
			
		||||
 | 
			
		||||
    * Extended Quote Report (#361)
 | 
			
		||||
 | 
			
		||||
## v16.31.0 - _November 3, 2021_
 | 
			
		||||
 | 
			
		||||
    * Added `Curve`, `Curve_V2` and `KyberDmm` to Avalanche (#363)
 | 
			
		||||
 | 
			
		||||
## v16.30.1 - _November 3, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 
 | 
			
		||||
@@ -159,8 +159,11 @@ contract KyberDmmSampler
 | 
			
		||||
                    (path[i], path[i + 1])
 | 
			
		||||
                returns (address[] memory allPools)
 | 
			
		||||
            {
 | 
			
		||||
                if (allPools.length == 0) {
 | 
			
		||||
                    return new address[](0);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                uint256 maxSupply = 0;
 | 
			
		||||
                require(allPools.length >= 1, "KyberDMMSampler/NO_POOLS_FOUND");
 | 
			
		||||
                for (uint256 j = 0; j < allPools.length; j++) {
 | 
			
		||||
                    uint256 totalSupply = IKyberDmmPool(allPools[j]).totalSupply();
 | 
			
		||||
                    if (totalSupply > maxSupply) {
 | 
			
		||||
 
 | 
			
		||||
@@ -174,8 +174,9 @@ contract UniswapV3Sampler
 | 
			
		||||
            tokenPath.length - startIndex >= 2,
 | 
			
		||||
            "UniswapV3Sampler/tokenPath too short"
 | 
			
		||||
        );
 | 
			
		||||
        uint24[3] memory validPoolFees = [
 | 
			
		||||
        uint24[4] memory validPoolFees = [
 | 
			
		||||
            // The launch pool fees. Could get hairier if they add more.
 | 
			
		||||
            uint24(0.0001e6),
 | 
			
		||||
            uint24(0.0005e6),
 | 
			
		||||
            uint24(0.003e6),
 | 
			
		||||
            uint24(0.01e6)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/asset-swapper",
 | 
			
		||||
    "version": "16.30.1",
 | 
			
		||||
    "version": "16.37.0",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -60,14 +60,14 @@
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0x/assert": "^3.0.29",
 | 
			
		||||
        "@0x/base-contract": "^6.4.2",
 | 
			
		||||
        "@0x/contract-addresses": "^6.8.1",
 | 
			
		||||
        "@0x/contract-wrappers": "^13.18.2",
 | 
			
		||||
        "@0x/contracts-erc20": "^3.3.22",
 | 
			
		||||
        "@0x/contracts-zero-ex": "^0.29.3",
 | 
			
		||||
        "@0x/contract-addresses": "^6.9.0",
 | 
			
		||||
        "@0x/contract-wrappers": "^13.18.3",
 | 
			
		||||
        "@0x/contracts-erc20": "^3.3.23",
 | 
			
		||||
        "@0x/contracts-zero-ex": "^0.29.5",
 | 
			
		||||
        "@0x/dev-utils": "^4.2.9",
 | 
			
		||||
        "@0x/json-schemas": "^6.3.0",
 | 
			
		||||
        "@0x/neon-router": "^0.2.1",
 | 
			
		||||
        "@0x/protocol-utils": "^1.9.4",
 | 
			
		||||
        "@0x/protocol-utils": "^1.9.5",
 | 
			
		||||
        "@0x/quote-server": "^6.0.6",
 | 
			
		||||
        "@0x/types": "^3.3.4",
 | 
			
		||||
        "@0x/typescript-typings": "^5.2.1",
 | 
			
		||||
@@ -98,10 +98,10 @@
 | 
			
		||||
        "@0x/contracts-exchange": "^3.2.38",
 | 
			
		||||
        "@0x/contracts-exchange-libs": "^4.3.37",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.40",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.4.13",
 | 
			
		||||
        "@0x/contracts-utils": "^4.8.3",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.4.14",
 | 
			
		||||
        "@0x/contracts-utils": "^4.8.4",
 | 
			
		||||
        "@0x/mesh-rpc-client": "^9.4.2",
 | 
			
		||||
        "@0x/migrations": "^8.1.10",
 | 
			
		||||
        "@0x/migrations": "^8.1.12",
 | 
			
		||||
        "@0x/sol-compiler": "^4.7.5",
 | 
			
		||||
        "@0x/subproviders": "^6.6.0",
 | 
			
		||||
        "@0x/ts-doc-gen": "^0.0.28",
 | 
			
		||||
 
 | 
			
		||||
@@ -162,14 +162,20 @@ export {
 | 
			
		||||
export { ProtocolFeeUtils } from './utils/protocol_fee_utils';
 | 
			
		||||
export {
 | 
			
		||||
    BridgeQuoteReportEntry,
 | 
			
		||||
    jsonifyFillData,
 | 
			
		||||
    MultiHopQuoteReportEntry,
 | 
			
		||||
    NativeLimitOrderQuoteReportEntry,
 | 
			
		||||
    NativeRfqOrderQuoteReportEntry,
 | 
			
		||||
    QuoteReport,
 | 
			
		||||
    QuoteReportEntry,
 | 
			
		||||
    ExtendedQuoteReport,
 | 
			
		||||
    ExtendedQuoteReportSources,
 | 
			
		||||
    ExtendedQuoteReportEntry,
 | 
			
		||||
    ExtendedQuoteReportIndexedEntry,
 | 
			
		||||
    ExtendedQuoteReportIndexedEntryOutbound,
 | 
			
		||||
    PriceComparisonsReport,
 | 
			
		||||
} from './utils/quote_report_generator';
 | 
			
		||||
export { QuoteRequestor } from './utils/quote_requestor';
 | 
			
		||||
export { QuoteRequestor, V4RFQIndicativeQuoteMM } from './utils/quote_requestor';
 | 
			
		||||
export { ERC20BridgeSamplerContract, BalanceCheckerContract, FakeTakerContract } from './wrappers';
 | 
			
		||||
import { ERC20BridgeSource } from './utils/market_operation_utils/types';
 | 
			
		||||
export type Native = ERC20BridgeSource.Native;
 | 
			
		||||
 
 | 
			
		||||
@@ -360,8 +360,9 @@ export class ExchangeProxySwapQuoteConsumer implements SwapQuoteConsumerBase {
 | 
			
		||||
 | 
			
		||||
        // Build up the transforms.
 | 
			
		||||
        const transforms = [];
 | 
			
		||||
        if (isFromETH) {
 | 
			
		||||
            // Create a WETH wrapper if coming from ETH.
 | 
			
		||||
        // Create a WETH wrapper if coming from ETH.
 | 
			
		||||
        // Dont add the wethTransformer to CELO. There is no wrap/unwrap logic for CELO.
 | 
			
		||||
        if (isFromETH && this.chainId !== ChainId.Celo) {
 | 
			
		||||
            transforms.push({
 | 
			
		||||
                deploymentNonce: this.transformerNonces.wethTransformer,
 | 
			
		||||
                data: encodeWethTransformerData({
 | 
			
		||||
@@ -413,9 +414,9 @@ export class ExchangeProxySwapQuoteConsumer implements SwapQuoteConsumerBase {
 | 
			
		||||
                }),
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (isToETH) {
 | 
			
		||||
            // Create a WETH unwrapper if going to ETH.
 | 
			
		||||
        // Create a WETH unwrapper if going to ETH.
 | 
			
		||||
        // Dont add the wethTransformer on CELO. There is no wrap/unwrap logic for CELO.
 | 
			
		||||
        if (isToETH && this.chainId !== ChainId.Celo) {
 | 
			
		||||
            transforms.push({
 | 
			
		||||
                deploymentNonce: this.transformerNonces.wethTransformer,
 | 
			
		||||
                data: encodeWethTransformerData({
 | 
			
		||||
@@ -492,10 +493,11 @@ export class ExchangeProxySwapQuoteConsumer implements SwapQuoteConsumerBase {
 | 
			
		||||
                amounts: [],
 | 
			
		||||
            }),
 | 
			
		||||
        });
 | 
			
		||||
        const TO_ETH_ADDRESS = this.chainId === ChainId.Celo ? this.contractAddresses.etherToken : ETH_TOKEN_ADDRESS;
 | 
			
		||||
        const calldataHexString = this._exchangeProxy
 | 
			
		||||
            .transformERC20(
 | 
			
		||||
                isFromETH ? ETH_TOKEN_ADDRESS : sellToken,
 | 
			
		||||
                isToETH ? ETH_TOKEN_ADDRESS : buyToken,
 | 
			
		||||
                isToETH ? TO_ETH_ADDRESS : buyToken,
 | 
			
		||||
                shouldSellEntireBalance ? MAX_UINT256 : sellAmount,
 | 
			
		||||
                minBuyAmount,
 | 
			
		||||
                transforms,
 | 
			
		||||
 
 | 
			
		||||
@@ -505,6 +505,7 @@ function createSwapQuote(
 | 
			
		||||
    const {
 | 
			
		||||
        optimizedOrders,
 | 
			
		||||
        quoteReport,
 | 
			
		||||
        extendedQuoteReportSources,
 | 
			
		||||
        sourceFlags,
 | 
			
		||||
        takerAmountPerEth,
 | 
			
		||||
        makerAmountPerEth,
 | 
			
		||||
@@ -532,6 +533,7 @@ function createSwapQuote(
 | 
			
		||||
        takerAmountPerEth,
 | 
			
		||||
        makerAmountPerEth,
 | 
			
		||||
        quoteReport,
 | 
			
		||||
        extendedQuoteReportSources,
 | 
			
		||||
        isTwoHop,
 | 
			
		||||
        priceComparisonsReport,
 | 
			
		||||
    };
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,7 @@ import {
 | 
			
		||||
    OptimizedMarketOrder,
 | 
			
		||||
    TokenAdjacencyGraph,
 | 
			
		||||
} from './utils/market_operation_utils/types';
 | 
			
		||||
import { PriceComparisonsReport, QuoteReport } from './utils/quote_report_generator';
 | 
			
		||||
import { ExtendedQuoteReportSources, PriceComparisonsReport, QuoteReport } from './utils/quote_report_generator';
 | 
			
		||||
import { MetricsProxy } from './utils/quote_requestor';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -171,6 +171,7 @@ export interface SwapQuoteBase {
 | 
			
		||||
    worstCaseQuoteInfo: SwapQuoteInfo;
 | 
			
		||||
    sourceBreakdown: SwapQuoteOrdersBreakdown;
 | 
			
		||||
    quoteReport?: QuoteReport;
 | 
			
		||||
    extendedQuoteReportSources?: ExtendedQuoteReportSources;
 | 
			
		||||
    priceComparisonsReport?: PriceComparisonsReport;
 | 
			
		||||
    isTwoHop: boolean;
 | 
			
		||||
    makerTokenDecimals: number;
 | 
			
		||||
 
 | 
			
		||||
@@ -11,9 +11,11 @@ import {
 | 
			
		||||
    COMETHSWAP_ROUTER_BY_CHAIN_ID,
 | 
			
		||||
    COMPONENT_POOLS_BY_CHAIN_ID,
 | 
			
		||||
    CRYPTO_COM_ROUTER_BY_CHAIN_ID,
 | 
			
		||||
    CURVE_AVALANCHE_INFOS,
 | 
			
		||||
    CURVE_FANTOM_INFOS,
 | 
			
		||||
    CURVE_MAINNET_INFOS,
 | 
			
		||||
    CURVE_POLYGON_INFOS,
 | 
			
		||||
    CURVE_V2_AVALANCHE_INFOS,
 | 
			
		||||
    CURVE_V2_FANTOM_INFOS,
 | 
			
		||||
    CURVE_V2_MAINNET_INFOS,
 | 
			
		||||
    CURVE_V2_POLYGON_INFOS,
 | 
			
		||||
@@ -28,6 +30,7 @@ import {
 | 
			
		||||
    KYBER_BRIDGED_LIQUIDITY_PREFIX,
 | 
			
		||||
    MAX_DODOV2_POOLS_QUERIED,
 | 
			
		||||
    MAX_KYBER_RESERVES_QUERIED,
 | 
			
		||||
    MORPHEUSSWAP_ROUTER_BY_CHAIN_ID,
 | 
			
		||||
    MSTABLE_POOLS_BY_CHAIN_ID,
 | 
			
		||||
    NERVE_BSC_INFOS,
 | 
			
		||||
    NULL_ADDRESS,
 | 
			
		||||
@@ -47,6 +50,7 @@ import {
 | 
			
		||||
    SUSHISWAP_ROUTER_BY_CHAIN_ID,
 | 
			
		||||
    SWERVE_MAINNET_INFOS,
 | 
			
		||||
    TRADER_JOE_ROUTER_BY_CHAIN_ID,
 | 
			
		||||
    UBESWAP_ROUTER_BY_CHAIN_ID,
 | 
			
		||||
    UNISWAPV2_ROUTER_BY_CHAIN_ID,
 | 
			
		||||
    WAULTSWAP_ROUTER_BY_CHAIN_ID,
 | 
			
		||||
    XSIGMA_MAINNET_INFOS,
 | 
			
		||||
@@ -146,6 +150,15 @@ export function getCurveInfosForPair(chainId: ChainId, takerToken: string, maker
 | 
			
		||||
                            [makerToken, takerToken].filter(v => c.metaTokens?.includes(v)).length > 0),
 | 
			
		||||
                ),
 | 
			
		||||
            );
 | 
			
		||||
        case ChainId.Avalanche:
 | 
			
		||||
            return Object.values(CURVE_AVALANCHE_INFOS).filter(c =>
 | 
			
		||||
                [makerToken, takerToken].every(
 | 
			
		||||
                    t =>
 | 
			
		||||
                        (c.tokens.includes(t) && c.metaTokens === undefined) ||
 | 
			
		||||
                        (c.tokens.includes(t) &&
 | 
			
		||||
                            [makerToken, takerToken].filter(v => c.metaTokens?.includes(v)).length > 0),
 | 
			
		||||
                ),
 | 
			
		||||
            );
 | 
			
		||||
        default:
 | 
			
		||||
            return [];
 | 
			
		||||
    }
 | 
			
		||||
@@ -181,6 +194,15 @@ export function getCurveV2InfosForPair(chainId: ChainId, takerToken: string, mak
 | 
			
		||||
                            [makerToken, takerToken].filter(v => c.metaTokens?.includes(v)).length > 0),
 | 
			
		||||
                ),
 | 
			
		||||
            );
 | 
			
		||||
        case ChainId.Avalanche:
 | 
			
		||||
            return Object.values(CURVE_V2_AVALANCHE_INFOS).filter(c =>
 | 
			
		||||
                [makerToken, takerToken].every(
 | 
			
		||||
                    t =>
 | 
			
		||||
                        (c.tokens.includes(t) && c.metaTokens === undefined) ||
 | 
			
		||||
                        (c.tokens.includes(t) &&
 | 
			
		||||
                            [makerToken, takerToken].filter(v => c.metaTokens?.includes(v)).length > 0),
 | 
			
		||||
                ),
 | 
			
		||||
            );
 | 
			
		||||
        default:
 | 
			
		||||
            return [];
 | 
			
		||||
    }
 | 
			
		||||
@@ -466,6 +488,8 @@ export function uniswapV2LikeRouterAddress(
 | 
			
		||||
        | ERC20BridgeSource.JetSwap
 | 
			
		||||
        | ERC20BridgeSource.TraderJoe
 | 
			
		||||
        | ERC20BridgeSource.Pangolin
 | 
			
		||||
        | ERC20BridgeSource.UbeSwap
 | 
			
		||||
        | ERC20BridgeSource.MorpheusSwap
 | 
			
		||||
        | ERC20BridgeSource.SpookySwap
 | 
			
		||||
        | ERC20BridgeSource.SpiritSwap,
 | 
			
		||||
): string {
 | 
			
		||||
@@ -508,6 +532,10 @@ export function uniswapV2LikeRouterAddress(
 | 
			
		||||
            return PANGOLIN_ROUTER_BY_CHAIN_ID[chainId];
 | 
			
		||||
        case ERC20BridgeSource.TraderJoe:
 | 
			
		||||
            return TRADER_JOE_ROUTER_BY_CHAIN_ID[chainId];
 | 
			
		||||
        case ERC20BridgeSource.UbeSwap:
 | 
			
		||||
            return UBESWAP_ROUTER_BY_CHAIN_ID[chainId];
 | 
			
		||||
        case ERC20BridgeSource.MorpheusSwap:
 | 
			
		||||
            return MORPHEUSSWAP_ROUTER_BY_CHAIN_ID[chainId];
 | 
			
		||||
        case ERC20BridgeSource.SpookySwap:
 | 
			
		||||
            return SPOOKYSWAP_ROUTER_BY_CHAIN_ID[chainId];
 | 
			
		||||
        case ERC20BridgeSource.SpiritSwap:
 | 
			
		||||
 
 | 
			
		||||
@@ -58,6 +58,7 @@ function valueByChainId<T>(rest: Partial<{ [key in ChainId]: T }>, defaultValue:
 | 
			
		||||
        [ChainId.PolygonMumbai]: defaultValue,
 | 
			
		||||
        [ChainId.Avalanche]: defaultValue,
 | 
			
		||||
        [ChainId.Fantom]: defaultValue,
 | 
			
		||||
        [ChainId.Celo]: defaultValue,
 | 
			
		||||
        ...(rest || {}),
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
@@ -136,6 +137,7 @@ export const SELL_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
 | 
			
		||||
            ERC20BridgeSource.FirebirdOneSwap,
 | 
			
		||||
            ERC20BridgeSource.JetSwap,
 | 
			
		||||
            ERC20BridgeSource.ACryptos,
 | 
			
		||||
            ERC20BridgeSource.KyberDmm,
 | 
			
		||||
        ]),
 | 
			
		||||
        [ChainId.Polygon]: new SourceFilters([
 | 
			
		||||
            ERC20BridgeSource.SushiSwap,
 | 
			
		||||
@@ -163,15 +165,26 @@ export const SELL_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
 | 
			
		||||
            ERC20BridgeSource.Pangolin,
 | 
			
		||||
            ERC20BridgeSource.TraderJoe,
 | 
			
		||||
            ERC20BridgeSource.SushiSwap,
 | 
			
		||||
            ERC20BridgeSource.Curve,
 | 
			
		||||
            ERC20BridgeSource.CurveV2,
 | 
			
		||||
            ERC20BridgeSource.KyberDmm,
 | 
			
		||||
        ]),
 | 
			
		||||
        [ChainId.Fantom]: new SourceFilters([
 | 
			
		||||
            ERC20BridgeSource.MultiHop,
 | 
			
		||||
            ERC20BridgeSource.Beethovenx,
 | 
			
		||||
            ERC20BridgeSource.Curve,
 | 
			
		||||
            ERC20BridgeSource.CurveV2,
 | 
			
		||||
            ERC20BridgeSource.JetSwap,
 | 
			
		||||
            ERC20BridgeSource.MorpheusSwap,
 | 
			
		||||
            ERC20BridgeSource.SpiritSwap,
 | 
			
		||||
            ERC20BridgeSource.SpookySwap,
 | 
			
		||||
            ERC20BridgeSource.SushiSwap,
 | 
			
		||||
        ]),
 | 
			
		||||
        [ChainId.Celo]: new SourceFilters([
 | 
			
		||||
            ERC20BridgeSource.UbeSwap,
 | 
			
		||||
            ERC20BridgeSource.SushiSwap,
 | 
			
		||||
            ERC20BridgeSource.MultiHop,
 | 
			
		||||
        ]),
 | 
			
		||||
    },
 | 
			
		||||
    new SourceFilters([]),
 | 
			
		||||
);
 | 
			
		||||
@@ -250,6 +263,7 @@ export const BUY_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
 | 
			
		||||
            ERC20BridgeSource.FirebirdOneSwap,
 | 
			
		||||
            ERC20BridgeSource.JetSwap,
 | 
			
		||||
            ERC20BridgeSource.ACryptos,
 | 
			
		||||
            ERC20BridgeSource.KyberDmm,
 | 
			
		||||
        ]),
 | 
			
		||||
        [ChainId.Polygon]: new SourceFilters([
 | 
			
		||||
            ERC20BridgeSource.SushiSwap,
 | 
			
		||||
@@ -277,15 +291,26 @@ export const BUY_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
 | 
			
		||||
            ERC20BridgeSource.Pangolin,
 | 
			
		||||
            ERC20BridgeSource.TraderJoe,
 | 
			
		||||
            ERC20BridgeSource.SushiSwap,
 | 
			
		||||
            ERC20BridgeSource.Curve,
 | 
			
		||||
            ERC20BridgeSource.CurveV2,
 | 
			
		||||
            ERC20BridgeSource.KyberDmm,
 | 
			
		||||
        ]),
 | 
			
		||||
        [ChainId.Fantom]: new SourceFilters([
 | 
			
		||||
            ERC20BridgeSource.MultiHop,
 | 
			
		||||
            ERC20BridgeSource.Beethovenx,
 | 
			
		||||
            ERC20BridgeSource.Curve,
 | 
			
		||||
            ERC20BridgeSource.CurveV2,
 | 
			
		||||
            ERC20BridgeSource.JetSwap,
 | 
			
		||||
            ERC20BridgeSource.MorpheusSwap,
 | 
			
		||||
            ERC20BridgeSource.SpiritSwap,
 | 
			
		||||
            ERC20BridgeSource.SpookySwap,
 | 
			
		||||
            ERC20BridgeSource.SushiSwap,
 | 
			
		||||
        ]),
 | 
			
		||||
        [ChainId.Celo]: new SourceFilters([
 | 
			
		||||
            ERC20BridgeSource.UbeSwap,
 | 
			
		||||
            ERC20BridgeSource.SushiSwap,
 | 
			
		||||
            ERC20BridgeSource.MultiHop,
 | 
			
		||||
        ]),
 | 
			
		||||
    },
 | 
			
		||||
    new SourceFilters([]),
 | 
			
		||||
);
 | 
			
		||||
@@ -306,6 +331,7 @@ export const FEE_QUOTE_SOURCES_BY_CHAIN_ID = valueByChainId<ERC20BridgeSource[]>
 | 
			
		||||
        [ChainId.Polygon]: [ERC20BridgeSource.QuickSwap, ERC20BridgeSource.SushiSwap],
 | 
			
		||||
        [ChainId.Avalanche]: [ERC20BridgeSource.Pangolin, ERC20BridgeSource.TraderJoe, ERC20BridgeSource.SushiSwap],
 | 
			
		||||
        [ChainId.Fantom]: [ERC20BridgeSource.SpiritSwap, ERC20BridgeSource.SpookySwap, ERC20BridgeSource.SushiSwap],
 | 
			
		||||
        [ChainId.Celo]: [ERC20BridgeSource.UbeSwap, ERC20BridgeSource.SushiSwap],
 | 
			
		||||
    },
 | 
			
		||||
    [],
 | 
			
		||||
);
 | 
			
		||||
@@ -402,9 +428,16 @@ export const MAINNET_TOKENS = {
 | 
			
		||||
    // StableSwap "open pools" (crv.finance)
 | 
			
		||||
    STABLEx: '0xcd91538b91b4ba7797d39a2f66e63810b50a33d0',
 | 
			
		||||
    alUSD: '0xbc6da0fe9ad5f3b0d58160288917aa56653660e9',
 | 
			
		||||
    // Frax ecosystem
 | 
			
		||||
    FRAX: '0x853d955acef822db058eb8505911ed77f175b99e',
 | 
			
		||||
    FXS: '0x3432b6a60d23ca0dfca7761b7ab56459d9c964d0',
 | 
			
		||||
    OHM: '0x383518188c0c6d7730d91b2c03a03c837814a899',
 | 
			
		||||
    //
 | 
			
		||||
    LUSD: '0x5f98805a4e8be255a32880fdec7f6728c6568ba0',
 | 
			
		||||
    // Fei Ecosystem
 | 
			
		||||
    FEI: '0x956f47f50a910163d8bf957cf5846d573e7f87ca',
 | 
			
		||||
    TRIBE: '0xc7283b66eb1eb5fb86327f08e1b5816b0720212b',
 | 
			
		||||
    //
 | 
			
		||||
    DSU: '0x605d26fbd5be761089281d5cec2ce86eea667109',
 | 
			
		||||
    ESS: '0x24ae124c4cc33d6791f8e8b63520ed7107ac8b3e',
 | 
			
		||||
    cvxCRV: '0x62b9c7356a2dc64a1969e19c23e4f579f9810aa7',
 | 
			
		||||
@@ -449,8 +482,19 @@ export const POLYGON_TOKENS = {
 | 
			
		||||
export const AVALANCHE_TOKENS = {
 | 
			
		||||
    WAVAX: '0xb31f66aa3c1e785363f0875a1b74e27b85fd66c7',
 | 
			
		||||
    WETH: '0x49d5c2bdffac6ce2bfdb6640f4f80f226bc10bab',
 | 
			
		||||
    USDT: '0xc7198437980c041c805a1edcba50c1ce5db95118',
 | 
			
		||||
    WBTC: '0x50b7545627a5162f82a992c33b87adc75187b218',
 | 
			
		||||
    DAI: '0xd586e7f844cea2f87f50152665bcbc2c279d8d70',
 | 
			
		||||
    USDC: '0xa7d7079b0fead91f3e65f86e8915cb59c1a4c664',
 | 
			
		||||
    USDT: '0xc7198437980c041c805a1edcba50c1ce5db95118',
 | 
			
		||||
    aDAI: '0x47afa96cdc9fab46904a55a6ad4bf6660b53c38a',
 | 
			
		||||
    aUSDC: '0x46a51127c3ce23fb7ab1de06226147f446e4a857',
 | 
			
		||||
    aUSDT: '0x532e6537fea298397212f09a61e03311686f548e',
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const CELO_TOKENS = {
 | 
			
		||||
    WETH: '0xe919f65739c26a42616b7b8eedc6b5524d1e3ac4',
 | 
			
		||||
    CELO: '0x471ece3750da237f93b8e339c536989b8978a438',
 | 
			
		||||
    mCUSD: '0x64defa3544c695db8c535d289d843a189aa26b98',
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const FANTOM_TOKENS = {
 | 
			
		||||
@@ -524,6 +568,14 @@ export const CURVE_V2_POLYGON_POOLS = {
 | 
			
		||||
    atricrypto3: '0x1d8b86e3d88cdb2d34688e87e72f388cb541b7c8',
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const CURVE_AVALANCHE_POOLS = {
 | 
			
		||||
    aave: '0x7f90122bf0700f9e7e1f688fe926940e8839f353',
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const CURVE_V2_AVALANCHE_POOLS = {
 | 
			
		||||
    atricrypto: '0x58e57ca18b7a47112b877e31929798cd3d703b0f',
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const CURVE_FANTOM_POOLS = {
 | 
			
		||||
    fUSDT: '0x92d5ebf3593a92888c25c0abef126583d4b5312e',
 | 
			
		||||
    twoPool: '0x27e611fd27b276acbd5ffd632e5eaebec9761e40',
 | 
			
		||||
@@ -631,8 +683,10 @@ export const DEFAULT_INTERMEDIATE_TOKENS_BY_CHAIN_ID = valueByChainId<string[]>(
 | 
			
		||||
            AVALANCHE_TOKENS.WETH,
 | 
			
		||||
            AVALANCHE_TOKENS.DAI,
 | 
			
		||||
            AVALANCHE_TOKENS.USDT,
 | 
			
		||||
            AVALANCHE_TOKENS.USDC,
 | 
			
		||||
        ],
 | 
			
		||||
        [ChainId.Fantom]: [FANTOM_TOKENS.WFTM, FANTOM_TOKENS.WETH, FANTOM_TOKENS.DAI, FANTOM_TOKENS.USDC],
 | 
			
		||||
        [ChainId.Celo]: [CELO_TOKENS.mCUSD, CELO_TOKENS.WETH, CELO_TOKENS.CELO],
 | 
			
		||||
    },
 | 
			
		||||
    [],
 | 
			
		||||
);
 | 
			
		||||
@@ -649,6 +703,11 @@ export const DEFAULT_TOKEN_ADJACENCY_GRAPH_BY_CHAIN_ID = valueByChainId<TokenAdj
 | 
			
		||||
                builder.add(MAINNET_TOKENS.MIR, MAINNET_TOKENS.UST);
 | 
			
		||||
                // Convex and Curve
 | 
			
		||||
                builder.add(MAINNET_TOKENS.cvxCRV, MAINNET_TOKENS.CRV).add(MAINNET_TOKENS.CRV, MAINNET_TOKENS.cvxCRV);
 | 
			
		||||
                // FEI TRIBE liquid in UniV2
 | 
			
		||||
                builder.add(MAINNET_TOKENS.FEI, MAINNET_TOKENS.TRIBE).add(MAINNET_TOKENS.TRIBE, MAINNET_TOKENS.FEI);
 | 
			
		||||
                // FRAX ecosystem
 | 
			
		||||
                builder.add(MAINNET_TOKENS.FRAX, MAINNET_TOKENS.FXS).add(MAINNET_TOKENS.FXS, MAINNET_TOKENS.FRAX);
 | 
			
		||||
                builder.add(MAINNET_TOKENS.FRAX, MAINNET_TOKENS.OHM).add(MAINNET_TOKENS.OHM, MAINNET_TOKENS.FRAX);
 | 
			
		||||
            })
 | 
			
		||||
            // Build
 | 
			
		||||
            .build(),
 | 
			
		||||
@@ -664,6 +723,9 @@ export const DEFAULT_TOKEN_ADJACENCY_GRAPH_BY_CHAIN_ID = valueByChainId<TokenAdj
 | 
			
		||||
        [ChainId.Fantom]: new TokenAdjacencyGraphBuilder({
 | 
			
		||||
            default: DEFAULT_INTERMEDIATE_TOKENS_BY_CHAIN_ID[ChainId.Fantom],
 | 
			
		||||
        }).build(),
 | 
			
		||||
        [ChainId.Celo]: new TokenAdjacencyGraphBuilder({
 | 
			
		||||
            default: DEFAULT_INTERMEDIATE_TOKENS_BY_CHAIN_ID[ChainId.Celo],
 | 
			
		||||
        }).build(),
 | 
			
		||||
    },
 | 
			
		||||
    new TokenAdjacencyGraphBuilder({ default: [] }).build(),
 | 
			
		||||
);
 | 
			
		||||
@@ -679,6 +741,7 @@ export const NATIVE_FEE_TOKEN_BY_CHAIN_ID = valueByChainId<string>(
 | 
			
		||||
        [ChainId.Polygon]: getContractAddressesForChainOrThrow(ChainId.Polygon).etherToken,
 | 
			
		||||
        [ChainId.Avalanche]: getContractAddressesForChainOrThrow(ChainId.Avalanche).etherToken,
 | 
			
		||||
        [ChainId.Fantom]: getContractAddressesForChainOrThrow(ChainId.Fantom).etherToken,
 | 
			
		||||
        [ChainId.Celo]: getContractAddressesForChainOrThrow(ChainId.Celo).etherToken,
 | 
			
		||||
    },
 | 
			
		||||
    NULL_ADDRESS,
 | 
			
		||||
);
 | 
			
		||||
@@ -999,6 +1062,37 @@ export const CURVE_V2_POLYGON_INFOS: { [name: string]: CurveInfo } = {
 | 
			
		||||
    }),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const CURVE_AVALANCHE_INFOS: { [name: string]: CurveInfo } = {
 | 
			
		||||
    ['aave_exchangeunderlying']: createCurveExchangeUnderlyingPool({
 | 
			
		||||
        tokens: [AVALANCHE_TOKENS.DAI, AVALANCHE_TOKENS.USDC, AVALANCHE_TOKENS.USDT],
 | 
			
		||||
        pool: CURVE_AVALANCHE_POOLS.aave,
 | 
			
		||||
        gasSchedule: 850e3,
 | 
			
		||||
    }),
 | 
			
		||||
    ['aave_exchange']: createCurveExchangePool({
 | 
			
		||||
        tokens: [AVALANCHE_TOKENS.aDAI, AVALANCHE_TOKENS.aUSDC, AVALANCHE_TOKENS.aUSDT],
 | 
			
		||||
        pool: CURVE_AVALANCHE_POOLS.aave,
 | 
			
		||||
        gasSchedule: 150e3,
 | 
			
		||||
    }),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const CURVE_V2_AVALANCHE_INFOS: { [name: string]: CurveInfo } = {
 | 
			
		||||
    [CURVE_V2_AVALANCHE_POOLS.atricrypto]: {
 | 
			
		||||
        exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying_v2,
 | 
			
		||||
        sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying_v2,
 | 
			
		||||
        buyQuoteFunctionSelector: CurveFunctionSelectors.None,
 | 
			
		||||
        tokens: [
 | 
			
		||||
            AVALANCHE_TOKENS.DAI,
 | 
			
		||||
            AVALANCHE_TOKENS.USDC,
 | 
			
		||||
            AVALANCHE_TOKENS.USDT,
 | 
			
		||||
            AVALANCHE_TOKENS.WBTC,
 | 
			
		||||
            AVALANCHE_TOKENS.WETH,
 | 
			
		||||
        ],
 | 
			
		||||
        metaTokens: undefined,
 | 
			
		||||
        poolAddress: CURVE_V2_AVALANCHE_POOLS.atricrypto,
 | 
			
		||||
        gasSchedule: 1300e3,
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// TODO: modify gasSchedule
 | 
			
		||||
export const CURVE_FANTOM_INFOS: { [name: string]: CurveInfo } = {
 | 
			
		||||
    [CURVE_FANTOM_POOLS.ren]: createCurveExchangePool({
 | 
			
		||||
@@ -1320,6 +1414,7 @@ export const SUSHISWAP_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
 | 
			
		||||
        [ChainId.Polygon]: '0x1b02da8cb0d097eb8d57a175b88c7d8b47997506',
 | 
			
		||||
        [ChainId.Avalanche]: '0x1b02da8cb0d097eb8d57a175b88c7d8b47997506',
 | 
			
		||||
        [ChainId.Fantom]: '0x1b02da8cb0d097eb8d57a175b88c7d8b47997506',
 | 
			
		||||
        [ChainId.Celo]: '0x1421bde4b10e8dd459b3bcb598810b1337d56842',
 | 
			
		||||
    },
 | 
			
		||||
    NULL_ADDRESS,
 | 
			
		||||
);
 | 
			
		||||
@@ -1389,6 +1484,9 @@ export const KYBER_DMM_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
 | 
			
		||||
    {
 | 
			
		||||
        [ChainId.Mainnet]: '0x1c87257f5e8609940bc751a07bb085bb7f8cdbe6',
 | 
			
		||||
        [ChainId.Polygon]: '0x546c79662e028b661dfb4767664d0273184e4dd1',
 | 
			
		||||
        [ChainId.BSC]: '0x78df70615ffc8066cc0887917f2cd72092c86409',
 | 
			
		||||
        [ChainId.Avalanche]: '0x8efa5a9ad6d594cf76830267077b78ce0bc5a5f8',
 | 
			
		||||
        [ChainId.Fantom]: '0x5d5a5a0a465129848c2549669e12cdc2f8de039a',
 | 
			
		||||
    },
 | 
			
		||||
    NULL_ADDRESS,
 | 
			
		||||
);
 | 
			
		||||
@@ -1538,6 +1636,13 @@ export const BALANCER_V2_VAULT_ADDRESS_BY_CHAIN = valueByChainId<string>(
 | 
			
		||||
    NULL_ADDRESS,
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
export const BEETHOVEN_X_VAULT_ADDRESS_BY_CHAIN = valueByChainId<string>(
 | 
			
		||||
    {
 | 
			
		||||
        [ChainId.Fantom]: '0x20dd72ed959b6147912c2e529f0a0c651c33c9ce',
 | 
			
		||||
    },
 | 
			
		||||
    NULL_ADDRESS,
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
export const LIDO_INFO_BY_CHAIN = valueByChainId<LidoInfo>(
 | 
			
		||||
    {
 | 
			
		||||
        [ChainId.Mainnet]: {
 | 
			
		||||
@@ -1562,6 +1667,13 @@ export const BALANCER_V2_SUBGRAPH_URL_BY_CHAIN = valueByChainId<string>(
 | 
			
		||||
    'https://api.thegraph.com/subgraphs/name/balancer-labs/balancer-v2',
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
export const BEETHOVEN_X_SUBGRAPH_URL_BY_CHAIN = valueByChainId<string>(
 | 
			
		||||
    {
 | 
			
		||||
        [ChainId.Fantom]: 'https://graph-node.beets-ftm-node.com/subgraphs/name/beethovenx-v4',
 | 
			
		||||
    },
 | 
			
		||||
    'https://graph-node.beets-ftm-node.com/subgraphs/name/beethovenx-v4',
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
export const UNISWAPV3_CONFIG_BY_CHAIN_ID = valueByChainId(
 | 
			
		||||
    {
 | 
			
		||||
        [ChainId.Mainnet]: {
 | 
			
		||||
@@ -1672,6 +1784,7 @@ export const JETSWAP_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
 | 
			
		||||
    {
 | 
			
		||||
        [ChainId.BSC]: '0xbe65b8f75b9f20f4c522e0067a3887fada714800',
 | 
			
		||||
        [ChainId.Polygon]: '0x5c6ec38fb0e2609672bdf628b1fd605a523e5923',
 | 
			
		||||
        [ChainId.Fantom]: '0x845e76a8691423fbc4ecb8dd77556cb61c09ee25',
 | 
			
		||||
    },
 | 
			
		||||
    NULL_ADDRESS,
 | 
			
		||||
);
 | 
			
		||||
@@ -1690,6 +1803,20 @@ export const TRADER_JOE_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
 | 
			
		||||
    NULL_ADDRESS,
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
export const UBESWAP_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
 | 
			
		||||
    {
 | 
			
		||||
        [ChainId.Celo]: '0x7d28570135a2b1930f331c507f65039d4937f66c',
 | 
			
		||||
    },
 | 
			
		||||
    NULL_ADDRESS,
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
export const MORPHEUSSWAP_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
 | 
			
		||||
    {
 | 
			
		||||
        [ChainId.Fantom]: '0x8ac868293d97761a1fed6d4a01e9ff17c5594aa3',
 | 
			
		||||
    },
 | 
			
		||||
    NULL_ADDRESS,
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
export const SPIRITSWAP_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
 | 
			
		||||
    {
 | 
			
		||||
        [ChainId.Fantom]: '0x16327e3fbdaca3bcf7e38f5af2599d2ddc33ae52',
 | 
			
		||||
@@ -1855,11 +1982,18 @@ export const DEFAULT_GAS_SCHEDULE: Required<FeeSchedule> = {
 | 
			
		||||
    [ERC20BridgeSource.Pangolin]: uniswapV2CloneGasSchedule,
 | 
			
		||||
    [ERC20BridgeSource.TraderJoe]: uniswapV2CloneGasSchedule,
 | 
			
		||||
 | 
			
		||||
    //
 | 
			
		||||
    // Celo
 | 
			
		||||
    //
 | 
			
		||||
    [ERC20BridgeSource.UbeSwap]: uniswapV2CloneGasSchedule,
 | 
			
		||||
 | 
			
		||||
    //
 | 
			
		||||
    // Fantom
 | 
			
		||||
    //
 | 
			
		||||
    [ERC20BridgeSource.MorpheusSwap]: uniswapV2CloneGasSchedule,
 | 
			
		||||
    [ERC20BridgeSource.SpiritSwap]: uniswapV2CloneGasSchedule,
 | 
			
		||||
    [ERC20BridgeSource.SpookySwap]: uniswapV2CloneGasSchedule,
 | 
			
		||||
    [ERC20BridgeSource.Beethovenx]: () => 100e3,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const DEFAULT_FEE_SCHEDULE: Required<FeeSchedule> = { ...DEFAULT_GAS_SCHEDULE };
 | 
			
		||||
 
 | 
			
		||||
@@ -18,12 +18,15 @@ import {
 | 
			
		||||
 | 
			
		||||
import {
 | 
			
		||||
    dexSampleToReportSource,
 | 
			
		||||
    ExtendedQuoteReportSources,
 | 
			
		||||
    generateExtendedQuoteReportSources,
 | 
			
		||||
    generateQuoteReport,
 | 
			
		||||
    multiHopSampleToReportSource,
 | 
			
		||||
    nativeOrderToReportEntry,
 | 
			
		||||
    PriceComparisonsReport,
 | 
			
		||||
    QuoteReport,
 | 
			
		||||
} from './../quote_report_generator';
 | 
			
		||||
 | 
			
		||||
import { getComparisonPrices } from './comparison_price';
 | 
			
		||||
import {
 | 
			
		||||
    BUY_SOURCE_FILTER_BY_CHAIN_ID,
 | 
			
		||||
@@ -78,6 +81,25 @@ export class MarketOperationUtils {
 | 
			
		||||
        return generateQuoteReport(side, quotes.nativeOrders, liquidityDelivered, comparisonPrice, quoteRequestor);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static _computeExtendedQuoteReportSources(
 | 
			
		||||
        quoteRequestor: QuoteRequestor | undefined,
 | 
			
		||||
        marketSideLiquidity: MarketSideLiquidity,
 | 
			
		||||
        amount: BigNumber,
 | 
			
		||||
        optimizerResult: OptimizerResult,
 | 
			
		||||
        comparisonPrice?: BigNumber | undefined,
 | 
			
		||||
    ): ExtendedQuoteReportSources {
 | 
			
		||||
        const { side, quotes } = marketSideLiquidity;
 | 
			
		||||
        const { liquidityDelivered } = optimizerResult;
 | 
			
		||||
        return generateExtendedQuoteReportSources(
 | 
			
		||||
            side,
 | 
			
		||||
            quotes,
 | 
			
		||||
            liquidityDelivered,
 | 
			
		||||
            amount,
 | 
			
		||||
            comparisonPrice,
 | 
			
		||||
            quoteRequestor,
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static _computePriceComparisonsReport(
 | 
			
		||||
        quoteRequestor: QuoteRequestor | undefined,
 | 
			
		||||
        marketSideLiquidity: MarketSideLiquidity,
 | 
			
		||||
@@ -702,6 +724,16 @@ export class MarketOperationUtils {
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Always compute the Extended Quote Report
 | 
			
		||||
        let extendedQuoteReportSources: ExtendedQuoteReportSources | undefined;
 | 
			
		||||
        extendedQuoteReportSources = MarketOperationUtils._computeExtendedQuoteReportSources(
 | 
			
		||||
            _opts.rfqt ? _opts.rfqt.quoteRequestor : undefined,
 | 
			
		||||
            marketSideLiquidity,
 | 
			
		||||
            amount,
 | 
			
		||||
            optimizerResult,
 | 
			
		||||
            wholeOrderPrice,
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        let priceComparisonsReport: PriceComparisonsReport | undefined;
 | 
			
		||||
        if (_opts.shouldIncludePriceComparisonsReport) {
 | 
			
		||||
            priceComparisonsReport = MarketOperationUtils._computePriceComparisonsReport(
 | 
			
		||||
@@ -710,7 +742,7 @@ export class MarketOperationUtils {
 | 
			
		||||
                wholeOrderPrice,
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
        return { ...optimizerResult, quoteReport, priceComparisonsReport };
 | 
			
		||||
        return { ...optimizerResult, quoteReport, extendedQuoteReportSources, priceComparisonsReport };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private async _refreshPoolCacheIfRequiredAsync(takerToken: string, makerToken: string): Promise<void> {
 | 
			
		||||
 
 | 
			
		||||
@@ -184,10 +184,16 @@ export function getErc20BridgeSourceToBridgeSource(source: ERC20BridgeSource): s
 | 
			
		||||
            return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'Pangolin');
 | 
			
		||||
        case ERC20BridgeSource.TraderJoe:
 | 
			
		||||
            return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'TraderJoe');
 | 
			
		||||
        case ERC20BridgeSource.UbeSwap:
 | 
			
		||||
            return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'UbeSwap');
 | 
			
		||||
        case ERC20BridgeSource.Beethovenx:
 | 
			
		||||
            return encodeBridgeSourceId(BridgeProtocol.BalancerV2, 'Beethovenx');
 | 
			
		||||
        case ERC20BridgeSource.SpiritSwap:
 | 
			
		||||
            return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'SpiritSwap');
 | 
			
		||||
        case ERC20BridgeSource.SpookySwap:
 | 
			
		||||
            return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'SpookySwap');
 | 
			
		||||
        case ERC20BridgeSource.MorpheusSwap:
 | 
			
		||||
            return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'MorpheusSwap');
 | 
			
		||||
        default:
 | 
			
		||||
            throw new Error(AggregationError.NoBridgeForSource);
 | 
			
		||||
    }
 | 
			
		||||
@@ -236,6 +242,7 @@ export function createBridgeDataForBridgeOrder(order: OptimizedMarketBridgeOrder
 | 
			
		||||
            bridgeData = encoder.encode([balancerFillData.poolAddress]);
 | 
			
		||||
            break;
 | 
			
		||||
        case ERC20BridgeSource.BalancerV2:
 | 
			
		||||
        case ERC20BridgeSource.Beethovenx:
 | 
			
		||||
            const balancerV2FillData = (order as OptimizedMarketBridgeOrder<BalancerV2FillData>).fillData;
 | 
			
		||||
            const { vault, poolId } = balancerV2FillData;
 | 
			
		||||
            bridgeData = encoder.encode([vault, poolId]);
 | 
			
		||||
@@ -264,8 +271,10 @@ export function createBridgeDataForBridgeOrder(order: OptimizedMarketBridgeOrder
 | 
			
		||||
        case ERC20BridgeSource.JetSwap:
 | 
			
		||||
        case ERC20BridgeSource.Pangolin:
 | 
			
		||||
        case ERC20BridgeSource.TraderJoe:
 | 
			
		||||
        case ERC20BridgeSource.UbeSwap:
 | 
			
		||||
        case ERC20BridgeSource.SpiritSwap:
 | 
			
		||||
        case ERC20BridgeSource.SpookySwap:
 | 
			
		||||
        case ERC20BridgeSource.MorpheusSwap:
 | 
			
		||||
            const uniswapV2FillData = (order as OptimizedMarketBridgeOrder<UniswapV2FillData>).fillData;
 | 
			
		||||
            bridgeData = encoder.encode([uniswapV2FillData.router, uniswapV2FillData.tokenAddressPath]);
 | 
			
		||||
            break;
 | 
			
		||||
@@ -458,6 +467,9 @@ export const BRIDGE_ENCODERS: {
 | 
			
		||||
    [ERC20BridgeSource.TraderJoe]: routerAddressPathEncoder,
 | 
			
		||||
    [ERC20BridgeSource.SpiritSwap]: routerAddressPathEncoder,
 | 
			
		||||
    [ERC20BridgeSource.SpookySwap]: routerAddressPathEncoder,
 | 
			
		||||
    [ERC20BridgeSource.MorpheusSwap]: routerAddressPathEncoder,
 | 
			
		||||
    // Celo
 | 
			
		||||
    [ERC20BridgeSource.UbeSwap]: routerAddressPathEncoder,
 | 
			
		||||
    // BSC
 | 
			
		||||
    [ERC20BridgeSource.PancakeSwap]: routerAddressPathEncoder,
 | 
			
		||||
    [ERC20BridgeSource.PancakeSwapV2]: routerAddressPathEncoder,
 | 
			
		||||
@@ -485,6 +497,7 @@ export const BRIDGE_ENCODERS: {
 | 
			
		||||
    // Custom integrations
 | 
			
		||||
    [ERC20BridgeSource.MakerPsm]: makerPsmEncoder,
 | 
			
		||||
    [ERC20BridgeSource.BalancerV2]: balancerV2Encoder,
 | 
			
		||||
    [ERC20BridgeSource.Beethovenx]: balancerV2Encoder,
 | 
			
		||||
    [ERC20BridgeSource.UniswapV3]: AbiEncoder.create([
 | 
			
		||||
        { name: 'router', type: 'address' },
 | 
			
		||||
        { name: 'path', type: 'bytes' },
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,8 @@ import {
 | 
			
		||||
import {
 | 
			
		||||
    BALANCER_V2_VAULT_ADDRESS_BY_CHAIN,
 | 
			
		||||
    BANCOR_REGISTRY_BY_CHAIN_ID,
 | 
			
		||||
    BEETHOVEN_X_SUBGRAPH_URL_BY_CHAIN,
 | 
			
		||||
    BEETHOVEN_X_VAULT_ADDRESS_BY_CHAIN,
 | 
			
		||||
    DODOV1_CONFIG_BY_CHAIN_ID,
 | 
			
		||||
    DODOV2_FACTORIES_BY_CHAIN_ID,
 | 
			
		||||
    KYBER_CONFIG_BY_CHAIN_ID,
 | 
			
		||||
@@ -122,6 +124,10 @@ export class SamplerOperations {
 | 
			
		||||
            ? poolsCaches
 | 
			
		||||
            : {
 | 
			
		||||
                  [ERC20BridgeSource.BalancerV2]: new BalancerV2PoolsCache(chainId),
 | 
			
		||||
                  [ERC20BridgeSource.Beethovenx]: new BalancerV2PoolsCache(
 | 
			
		||||
                      chainId,
 | 
			
		||||
                      BEETHOVEN_X_SUBGRAPH_URL_BY_CHAIN[chainId],
 | 
			
		||||
                  ),
 | 
			
		||||
                  [ERC20BridgeSource.Balancer]: new BalancerPoolsCache(),
 | 
			
		||||
                  [ERC20BridgeSource.Cream]: new CreamPoolsCache(),
 | 
			
		||||
              };
 | 
			
		||||
@@ -1197,8 +1203,10 @@ export class SamplerOperations {
 | 
			
		||||
                    case ERC20BridgeSource.JetSwap:
 | 
			
		||||
                    case ERC20BridgeSource.Pangolin:
 | 
			
		||||
                    case ERC20BridgeSource.TraderJoe:
 | 
			
		||||
                    case ERC20BridgeSource.UbeSwap:
 | 
			
		||||
                    case ERC20BridgeSource.SpiritSwap:
 | 
			
		||||
                    case ERC20BridgeSource.SpookySwap:
 | 
			
		||||
                    case ERC20BridgeSource.MorpheusSwap:
 | 
			
		||||
                        const uniLikeRouter = uniswapV2LikeRouterAddress(this.chainId, source);
 | 
			
		||||
                        if (!isValidAddress(uniLikeRouter)) {
 | 
			
		||||
                            return [];
 | 
			
		||||
@@ -1300,13 +1308,14 @@ export class SamplerOperations {
 | 
			
		||||
                            ),
 | 
			
		||||
                        );
 | 
			
		||||
                    case ERC20BridgeSource.BalancerV2:
 | 
			
		||||
                    case ERC20BridgeSource.Beethovenx:
 | 
			
		||||
                        const poolIds =
 | 
			
		||||
                            this.poolsCaches[ERC20BridgeSource.BalancerV2].getCachedPoolAddressesForPair(
 | 
			
		||||
                                takerToken,
 | 
			
		||||
                                makerToken,
 | 
			
		||||
                            ) || [];
 | 
			
		||||
                            this.poolsCaches[source].getCachedPoolAddressesForPair(takerToken, makerToken) || [];
 | 
			
		||||
 | 
			
		||||
                        const vault = BALANCER_V2_VAULT_ADDRESS_BY_CHAIN[this.chainId];
 | 
			
		||||
                        const vault =
 | 
			
		||||
                            source === ERC20BridgeSource.BalancerV2
 | 
			
		||||
                                ? BALANCER_V2_VAULT_ADDRESS_BY_CHAIN[this.chainId]
 | 
			
		||||
                                : BEETHOVEN_X_VAULT_ADDRESS_BY_CHAIN[this.chainId];
 | 
			
		||||
                        if (vault === NULL_ADDRESS) {
 | 
			
		||||
                            return [];
 | 
			
		||||
                        }
 | 
			
		||||
@@ -1316,10 +1325,9 @@ export class SamplerOperations {
 | 
			
		||||
                                makerToken,
 | 
			
		||||
                                takerToken,
 | 
			
		||||
                                takerFillAmounts,
 | 
			
		||||
                                ERC20BridgeSource.BalancerV2,
 | 
			
		||||
                                source,
 | 
			
		||||
                            ),
 | 
			
		||||
                        );
 | 
			
		||||
 | 
			
		||||
                    case ERC20BridgeSource.Cream:
 | 
			
		||||
                        return (
 | 
			
		||||
                            this.poolsCaches[ERC20BridgeSource.Cream].getCachedPoolAddressesForPair(
 | 
			
		||||
@@ -1468,8 +1476,10 @@ export class SamplerOperations {
 | 
			
		||||
                    case ERC20BridgeSource.JetSwap:
 | 
			
		||||
                    case ERC20BridgeSource.Pangolin:
 | 
			
		||||
                    case ERC20BridgeSource.TraderJoe:
 | 
			
		||||
                    case ERC20BridgeSource.UbeSwap:
 | 
			
		||||
                    case ERC20BridgeSource.SpiritSwap:
 | 
			
		||||
                    case ERC20BridgeSource.SpookySwap:
 | 
			
		||||
                    case ERC20BridgeSource.MorpheusSwap:
 | 
			
		||||
                        const uniLikeRouter = uniswapV2LikeRouterAddress(this.chainId, source);
 | 
			
		||||
                        if (!isValidAddress(uniLikeRouter)) {
 | 
			
		||||
                            return [];
 | 
			
		||||
@@ -1571,13 +1581,14 @@ export class SamplerOperations {
 | 
			
		||||
                            ),
 | 
			
		||||
                        );
 | 
			
		||||
                    case ERC20BridgeSource.BalancerV2:
 | 
			
		||||
                    case ERC20BridgeSource.Beethovenx:
 | 
			
		||||
                        const poolIds =
 | 
			
		||||
                            this.poolsCaches[ERC20BridgeSource.BalancerV2].getCachedPoolAddressesForPair(
 | 
			
		||||
                                takerToken,
 | 
			
		||||
                                makerToken,
 | 
			
		||||
                            ) || [];
 | 
			
		||||
                            this.poolsCaches[source].getCachedPoolAddressesForPair(takerToken, makerToken) || [];
 | 
			
		||||
 | 
			
		||||
                        const vault = BALANCER_V2_VAULT_ADDRESS_BY_CHAIN[this.chainId];
 | 
			
		||||
                        const vault =
 | 
			
		||||
                            source === ERC20BridgeSource.BalancerV2
 | 
			
		||||
                                ? BALANCER_V2_VAULT_ADDRESS_BY_CHAIN[this.chainId]
 | 
			
		||||
                                : BEETHOVEN_X_VAULT_ADDRESS_BY_CHAIN[this.chainId];
 | 
			
		||||
                        if (vault === NULL_ADDRESS) {
 | 
			
		||||
                            return [];
 | 
			
		||||
                        }
 | 
			
		||||
@@ -1587,7 +1598,7 @@ export class SamplerOperations {
 | 
			
		||||
                                makerToken,
 | 
			
		||||
                                takerToken,
 | 
			
		||||
                                makerFillAmounts,
 | 
			
		||||
                                ERC20BridgeSource.BalancerV2,
 | 
			
		||||
                                source,
 | 
			
		||||
                            ),
 | 
			
		||||
                        );
 | 
			
		||||
                    case ERC20BridgeSource.Cream:
 | 
			
		||||
 
 | 
			
		||||
@@ -3,13 +3,12 @@ import {
 | 
			
		||||
    FillQuoteTransformerOrderType,
 | 
			
		||||
    FillQuoteTransformerRfqOrderInfo,
 | 
			
		||||
} from '@0x/protocol-utils';
 | 
			
		||||
import { V4RFQIndicativeQuote } from '@0x/quote-server';
 | 
			
		||||
import { MarketOperation } from '@0x/types';
 | 
			
		||||
import { BigNumber } from '@0x/utils';
 | 
			
		||||
 | 
			
		||||
import { NativeOrderWithFillableAmounts, RfqFirmQuoteValidator, RfqRequestOpts } from '../../types';
 | 
			
		||||
import { QuoteRequestor } from '../../utils/quote_requestor';
 | 
			
		||||
import { PriceComparisonsReport, QuoteReport } from '../quote_report_generator';
 | 
			
		||||
import { QuoteRequestor, V4RFQIndicativeQuoteMM } from '../../utils/quote_requestor';
 | 
			
		||||
import { ExtendedQuoteReportSources, PriceComparisonsReport, QuoteReport } from '../quote_report_generator';
 | 
			
		||||
 | 
			
		||||
import { CollapsedPath } from './path';
 | 
			
		||||
import { SourceFilters } from './source_filters';
 | 
			
		||||
@@ -93,11 +92,19 @@ export enum ERC20BridgeSource {
 | 
			
		||||
    // Avalanche
 | 
			
		||||
    Pangolin = 'Pangolin',
 | 
			
		||||
    TraderJoe = 'TraderJoe',
 | 
			
		||||
    // Celo only
 | 
			
		||||
    UbeSwap = 'UbeSwap',
 | 
			
		||||
    // Fantom
 | 
			
		||||
    SpiritSwap = 'SpiritSwap',
 | 
			
		||||
    SpookySwap = 'SpookySwap',
 | 
			
		||||
    Beethovenx = 'Beethovenx',
 | 
			
		||||
    MorpheusSwap = 'MorpheusSwap',
 | 
			
		||||
}
 | 
			
		||||
export type SourcesWithPoolsCache = ERC20BridgeSource.Balancer | ERC20BridgeSource.BalancerV2 | ERC20BridgeSource.Cream;
 | 
			
		||||
export type SourcesWithPoolsCache =
 | 
			
		||||
    | ERC20BridgeSource.Balancer
 | 
			
		||||
    | ERC20BridgeSource.BalancerV2
 | 
			
		||||
    | ERC20BridgeSource.Beethovenx
 | 
			
		||||
    | ERC20BridgeSource.Cream;
 | 
			
		||||
 | 
			
		||||
// tslint:disable: enum-naming
 | 
			
		||||
/**
 | 
			
		||||
@@ -491,6 +498,7 @@ export interface OptimizerResult {
 | 
			
		||||
 | 
			
		||||
export interface OptimizerResultWithReport extends OptimizerResult {
 | 
			
		||||
    quoteReport?: QuoteReport;
 | 
			
		||||
    extendedQuoteReportSources?: ExtendedQuoteReportSources;
 | 
			
		||||
    priceComparisonsReport?: PriceComparisonsReport;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -519,7 +527,7 @@ export interface MarketSideLiquidity {
 | 
			
		||||
 | 
			
		||||
export interface RawQuotes {
 | 
			
		||||
    nativeOrders: NativeOrderWithFillableAmounts[];
 | 
			
		||||
    rfqtIndicativeQuotes: V4RFQIndicativeQuote[];
 | 
			
		||||
    rfqtIndicativeQuotes: V4RFQIndicativeQuoteMM[];
 | 
			
		||||
    twoHopQuotes: Array<DexSample<MultiHopFillData>>;
 | 
			
		||||
    dexQuotes: Array<Array<DexSample<FillData>>>;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -14,8 +14,9 @@ import {
 | 
			
		||||
    NativeFillData,
 | 
			
		||||
    NativeLimitOrderFillData,
 | 
			
		||||
    NativeRfqOrderFillData,
 | 
			
		||||
    RawQuotes,
 | 
			
		||||
} from './market_operation_utils/types';
 | 
			
		||||
import { QuoteRequestor } from './quote_requestor';
 | 
			
		||||
import { QuoteRequestor, V4RFQIndicativeQuoteMM } from './quote_requestor';
 | 
			
		||||
 | 
			
		||||
export interface QuoteReportEntryBase {
 | 
			
		||||
    liquiditySource: ERC20BridgeSource;
 | 
			
		||||
@@ -36,30 +37,77 @@ export interface NativeLimitOrderQuoteReportEntry extends QuoteReportEntryBase {
 | 
			
		||||
    liquiditySource: ERC20BridgeSource.Native;
 | 
			
		||||
    fillData: NativeFillData;
 | 
			
		||||
    fillableTakerAmount: BigNumber;
 | 
			
		||||
    isRfqt: false;
 | 
			
		||||
    isRFQ: false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface NativeRfqOrderQuoteReportEntry extends QuoteReportEntryBase {
 | 
			
		||||
    liquiditySource: ERC20BridgeSource.Native;
 | 
			
		||||
    fillData: NativeFillData;
 | 
			
		||||
    fillableTakerAmount: BigNumber;
 | 
			
		||||
    isRfqt: true;
 | 
			
		||||
    isRFQ: true;
 | 
			
		||||
    nativeOrder: RfqOrderFields;
 | 
			
		||||
    makerUri: string;
 | 
			
		||||
    comparisonPrice?: number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface IndicativeRfqOrderQuoteReportEntry extends QuoteReportEntryBase {
 | 
			
		||||
    liquiditySource: ERC20BridgeSource.Native;
 | 
			
		||||
    fillableTakerAmount: BigNumber;
 | 
			
		||||
    isRFQ: true;
 | 
			
		||||
    makerUri?: string;
 | 
			
		||||
    comparisonPrice?: number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type QuoteReportEntry =
 | 
			
		||||
    | BridgeQuoteReportEntry
 | 
			
		||||
    | MultiHopQuoteReportEntry
 | 
			
		||||
    | NativeLimitOrderQuoteReportEntry
 | 
			
		||||
    | NativeRfqOrderQuoteReportEntry;
 | 
			
		||||
 | 
			
		||||
export type ExtendedQuoteReportEntry =
 | 
			
		||||
    | BridgeQuoteReportEntry
 | 
			
		||||
    | MultiHopQuoteReportEntry
 | 
			
		||||
    | NativeLimitOrderQuoteReportEntry
 | 
			
		||||
    | NativeRfqOrderQuoteReportEntry
 | 
			
		||||
    | IndicativeRfqOrderQuoteReportEntry;
 | 
			
		||||
 | 
			
		||||
export type ExtendedQuoteReportIndexedEntry = ExtendedQuoteReportEntry & {
 | 
			
		||||
    quoteEntryIndex: number;
 | 
			
		||||
    isDelivered: boolean;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export type ExtendedQuoteReportIndexedEntryOutbound = Omit<ExtendedQuoteReportIndexedEntry, 'fillData'> & {
 | 
			
		||||
    fillData?: string;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export interface QuoteReport {
 | 
			
		||||
    sourcesConsidered: QuoteReportEntry[];
 | 
			
		||||
    sourcesDelivered: QuoteReportEntry[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ExtendedQuoteReportSources {
 | 
			
		||||
    sourcesConsidered: ExtendedQuoteReportIndexedEntry[];
 | 
			
		||||
    sourcesDelivered: ExtendedQuoteReportIndexedEntry[] | undefined;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ExtendedQuoteReport {
 | 
			
		||||
    quoteId?: string;
 | 
			
		||||
    taker?: string;
 | 
			
		||||
    timestamp: number;
 | 
			
		||||
    firmQuoteReport: boolean;
 | 
			
		||||
    submissionBy: 'taker' | 'metaTxn' | 'rfqm';
 | 
			
		||||
    buyAmount?: string;
 | 
			
		||||
    sellAmount?: string;
 | 
			
		||||
    buyTokenAddress: string;
 | 
			
		||||
    sellTokenAddress: string;
 | 
			
		||||
    integratorId?: string;
 | 
			
		||||
    slippageBips?: number;
 | 
			
		||||
    zeroExTransactionHash?: string;
 | 
			
		||||
    decodedUniqueId?: string;
 | 
			
		||||
    sourcesConsidered: ExtendedQuoteReportIndexedEntryOutbound[];
 | 
			
		||||
    sourcesDelivered: ExtendedQuoteReportIndexedEntryOutbound[] | undefined;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface PriceComparisonsReport {
 | 
			
		||||
    dexSources: BridgeQuoteReportEntry[];
 | 
			
		||||
    multiHopSources: MultiHopQuoteReportEntry[];
 | 
			
		||||
@@ -80,7 +128,7 @@ export function generateQuoteReport(
 | 
			
		||||
    const nativeOrderSourcesConsidered = nativeOrders.map(order =>
 | 
			
		||||
        nativeOrderToReportEntry(order.type, order as any, order.fillableTakerAmount, comparisonPrice, quoteRequestor),
 | 
			
		||||
    );
 | 
			
		||||
    const sourcesConsidered = [...nativeOrderSourcesConsidered.filter(order => order.isRfqt)];
 | 
			
		||||
    const sourcesConsidered = [...nativeOrderSourcesConsidered.filter(order => order.isRFQ)];
 | 
			
		||||
 | 
			
		||||
    let sourcesDelivered;
 | 
			
		||||
    if (Array.isArray(liquidityDelivered)) {
 | 
			
		||||
@@ -116,6 +164,105 @@ export function generateQuoteReport(
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Generates a report of sources considered while computing the optimized
 | 
			
		||||
 * swap quote, the sources ultimately included in the computed quote. This
 | 
			
		||||
 * extende version incudes all considered quotes, not only native liquidity.
 | 
			
		||||
 */
 | 
			
		||||
export function generateExtendedQuoteReportSources(
 | 
			
		||||
    marketOperation: MarketOperation,
 | 
			
		||||
    quotes: RawQuotes,
 | 
			
		||||
    liquidityDelivered: ReadonlyArray<CollapsedFill> | DexSample<MultiHopFillData>,
 | 
			
		||||
    amount: BigNumber,
 | 
			
		||||
    comparisonPrice?: BigNumber | undefined,
 | 
			
		||||
    quoteRequestor?: QuoteRequestor,
 | 
			
		||||
): ExtendedQuoteReportSources {
 | 
			
		||||
    const sourcesConsidered: ExtendedQuoteReportEntry[] = [];
 | 
			
		||||
 | 
			
		||||
    // NativeOrders
 | 
			
		||||
    sourcesConsidered.push(
 | 
			
		||||
        ...quotes.nativeOrders.map(order =>
 | 
			
		||||
            nativeOrderToReportEntry(
 | 
			
		||||
                order.type,
 | 
			
		||||
                order as any,
 | 
			
		||||
                order.fillableTakerAmount,
 | 
			
		||||
                comparisonPrice,
 | 
			
		||||
                quoteRequestor,
 | 
			
		||||
            ),
 | 
			
		||||
        ),
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    // IndicativeQuotes
 | 
			
		||||
    sourcesConsidered.push(
 | 
			
		||||
        ...quotes.rfqtIndicativeQuotes.map(order => indicativeQuoteToReportEntry(order, comparisonPrice)),
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    // MultiHop
 | 
			
		||||
    sourcesConsidered.push(...quotes.twoHopQuotes.map(quote => multiHopSampleToReportSource(quote, marketOperation)));
 | 
			
		||||
 | 
			
		||||
    // Dex Quotes
 | 
			
		||||
    sourcesConsidered.push(
 | 
			
		||||
        ..._.flatten(
 | 
			
		||||
            quotes.dexQuotes.map(dex =>
 | 
			
		||||
                dex
 | 
			
		||||
                    .filter(quote => isDexSampleForTotalAmount(quote, marketOperation, amount))
 | 
			
		||||
                    .map(quote => dexSampleToReportSource(quote, marketOperation)),
 | 
			
		||||
            ),
 | 
			
		||||
        ),
 | 
			
		||||
    );
 | 
			
		||||
    const sourcesConsideredIndexed = sourcesConsidered.map(
 | 
			
		||||
        (quote, index): ExtendedQuoteReportIndexedEntry => {
 | 
			
		||||
            return {
 | 
			
		||||
                ...quote,
 | 
			
		||||
                quoteEntryIndex: index,
 | 
			
		||||
                isDelivered: false,
 | 
			
		||||
            };
 | 
			
		||||
        },
 | 
			
		||||
    );
 | 
			
		||||
    let sourcesDelivered;
 | 
			
		||||
    if (Array.isArray(liquidityDelivered)) {
 | 
			
		||||
        // create easy way to look up fillable amounts
 | 
			
		||||
        const nativeOrderSignaturesToFillableAmounts = _.fromPairs(
 | 
			
		||||
            quotes.nativeOrders.map(o => {
 | 
			
		||||
                return [_nativeDataToId(o), o.fillableTakerAmount];
 | 
			
		||||
            }),
 | 
			
		||||
        );
 | 
			
		||||
        // map sources delivered
 | 
			
		||||
        sourcesDelivered = liquidityDelivered.map(collapsedFill => {
 | 
			
		||||
            if (_isNativeOrderFromCollapsedFill(collapsedFill)) {
 | 
			
		||||
                return nativeOrderToReportEntry(
 | 
			
		||||
                    collapsedFill.type,
 | 
			
		||||
                    collapsedFill.fillData,
 | 
			
		||||
                    nativeOrderSignaturesToFillableAmounts[_nativeDataToId(collapsedFill.fillData)],
 | 
			
		||||
                    comparisonPrice,
 | 
			
		||||
                    quoteRequestor,
 | 
			
		||||
                );
 | 
			
		||||
            } else {
 | 
			
		||||
                return dexSampleToReportSource(collapsedFill, marketOperation);
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    } else {
 | 
			
		||||
        sourcesDelivered = [
 | 
			
		||||
            // tslint:disable-next-line: no-unnecessary-type-assertion
 | 
			
		||||
            multiHopSampleToReportSource(liquidityDelivered as DexSample<MultiHopFillData>, marketOperation),
 | 
			
		||||
        ];
 | 
			
		||||
    }
 | 
			
		||||
    const sourcesDeliveredIndexed = sourcesDelivered.map(
 | 
			
		||||
        (quote, index): ExtendedQuoteReportIndexedEntry => {
 | 
			
		||||
            return {
 | 
			
		||||
                ...quote,
 | 
			
		||||
                quoteEntryIndex: index,
 | 
			
		||||
                isDelivered: false,
 | 
			
		||||
            };
 | 
			
		||||
        },
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
        sourcesConsidered: sourcesConsideredIndexed,
 | 
			
		||||
        sourcesDelivered: sourcesDeliveredIndexed,
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function _nativeDataToId(data: { signature: Signature }): string {
 | 
			
		||||
    const { v, r, s } = data.signature;
 | 
			
		||||
    return `${v}${r}${s}`;
 | 
			
		||||
@@ -153,6 +300,22 @@ export function dexSampleToReportSource(ds: DexSample, marketOperation: MarketOp
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Checks if a DEX sample is the one that represents the whole amount requested by taker
 | 
			
		||||
 * NOTE: this is used for the QuoteReport to filter samples
 | 
			
		||||
 */
 | 
			
		||||
function isDexSampleForTotalAmount(ds: DexSample, marketOperation: MarketOperation, amount: BigNumber): boolean {
 | 
			
		||||
    // input and output map to different values
 | 
			
		||||
    // based on the market operation
 | 
			
		||||
    if (marketOperation === MarketOperation.Buy) {
 | 
			
		||||
        return ds.input === amount;
 | 
			
		||||
    } else if (marketOperation === MarketOperation.Sell) {
 | 
			
		||||
        return ds.output === amount;
 | 
			
		||||
    } else {
 | 
			
		||||
        throw new Error(`Unexpected marketOperation ${marketOperation}`);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Generates a report sample for a MultiHop source
 | 
			
		||||
 * NOTE: this is used for the QuoteReport and quote price comparison data
 | 
			
		||||
@@ -208,17 +371,17 @@ export function nativeOrderToReportEntry(
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // if we find this is an rfqt order, label it as such and associate makerUri
 | 
			
		||||
    const isRfqt = type === FillQuoteTransformerOrderType.Rfq;
 | 
			
		||||
    const isRFQ = type === FillQuoteTransformerOrderType.Rfq;
 | 
			
		||||
    const rfqtMakerUri =
 | 
			
		||||
        isRfqt && quoteRequestor ? quoteRequestor.getMakerUriForSignature(fillData.signature) : undefined;
 | 
			
		||||
        isRFQ && quoteRequestor ? quoteRequestor.getMakerUriForSignature(fillData.signature) : undefined;
 | 
			
		||||
 | 
			
		||||
    if (isRfqt) {
 | 
			
		||||
    if (isRFQ) {
 | 
			
		||||
        const nativeOrder = fillData.order as RfqOrderFields;
 | 
			
		||||
        // tslint:disable-next-line: no-object-literal-type-assertion
 | 
			
		||||
        return {
 | 
			
		||||
            liquiditySource: ERC20BridgeSource.Native,
 | 
			
		||||
            ...nativeOrderBase,
 | 
			
		||||
            isRfqt: true,
 | 
			
		||||
            isRFQ: true,
 | 
			
		||||
            makerUri: rfqtMakerUri || '',
 | 
			
		||||
            ...(comparisonPrice ? { comparisonPrice: comparisonPrice.toNumber() } : {}),
 | 
			
		||||
            nativeOrder,
 | 
			
		||||
@@ -229,8 +392,49 @@ export function nativeOrderToReportEntry(
 | 
			
		||||
        return {
 | 
			
		||||
            liquiditySource: ERC20BridgeSource.Native,
 | 
			
		||||
            ...nativeOrderBase,
 | 
			
		||||
            isRfqt: false,
 | 
			
		||||
            isRFQ: false,
 | 
			
		||||
            fillData,
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Generates a report entry for an indicative RFQ Quote
 | 
			
		||||
 * NOTE: this is used for the QuoteReport and quote price comparison data
 | 
			
		||||
 */
 | 
			
		||||
export function indicativeQuoteToReportEntry(
 | 
			
		||||
    order: V4RFQIndicativeQuoteMM,
 | 
			
		||||
    comparisonPrice?: BigNumber | undefined,
 | 
			
		||||
): IndicativeRfqOrderQuoteReportEntry {
 | 
			
		||||
    const nativeOrderBase = {
 | 
			
		||||
        makerAmount: order.makerAmount,
 | 
			
		||||
        takerAmount: order.takerAmount,
 | 
			
		||||
        fillableTakerAmount: order.takerAmount,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // tslint:disable-next-line: no-object-literal-type-assertion
 | 
			
		||||
    return {
 | 
			
		||||
        liquiditySource: ERC20BridgeSource.Native,
 | 
			
		||||
        ...nativeOrderBase,
 | 
			
		||||
        isRFQ: true,
 | 
			
		||||
        makerUri: order.makerUri,
 | 
			
		||||
        fillData: {},
 | 
			
		||||
        ...(comparisonPrice ? { comparisonPrice: comparisonPrice.toNumber() } : {}),
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * For the extended quote report, we output the filldata as JSON
 | 
			
		||||
 */
 | 
			
		||||
export function jsonifyFillData(source: ExtendedQuoteReportIndexedEntry): ExtendedQuoteReportIndexedEntryOutbound {
 | 
			
		||||
    return {
 | 
			
		||||
        ...source,
 | 
			
		||||
        fillData: JSON.stringify(source.fillData, (key: string, value: any) => {
 | 
			
		||||
            if (key === '_samplerContract') {
 | 
			
		||||
                return {};
 | 
			
		||||
            } else {
 | 
			
		||||
                return value;
 | 
			
		||||
            }
 | 
			
		||||
        }),
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -39,6 +39,10 @@ interface RfqQuote<T> {
 | 
			
		||||
    makerUri: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface V4RFQIndicativeQuoteMM extends V4RFQIndicativeQuote {
 | 
			
		||||
    makerUri: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface MetricsProxy {
 | 
			
		||||
    /**
 | 
			
		||||
     * Increments a counter that is tracking valid Firm Quotes that are dropped due to low expiration.
 | 
			
		||||
@@ -343,7 +347,7 @@ export class QuoteRequestor {
 | 
			
		||||
        marketOperation: MarketOperation,
 | 
			
		||||
        comparisonPrice: BigNumber | undefined,
 | 
			
		||||
        options: RfqmRequestOptions,
 | 
			
		||||
    ): Promise<V4RFQIndicativeQuote[]> {
 | 
			
		||||
    ): Promise<V4RFQIndicativeQuoteMM[]> {
 | 
			
		||||
        const _opts: RfqRequestOpts = {
 | 
			
		||||
            ...constants.DEFAULT_RFQT_REQUEST_OPTS,
 | 
			
		||||
            ...options,
 | 
			
		||||
@@ -367,7 +371,7 @@ export class QuoteRequestor {
 | 
			
		||||
        marketOperation: MarketOperation,
 | 
			
		||||
        comparisonPrice: BigNumber | undefined,
 | 
			
		||||
        options: RfqRequestOpts,
 | 
			
		||||
    ): Promise<V4RFQIndicativeQuote[]> {
 | 
			
		||||
    ): Promise<V4RFQIndicativeQuoteMM[]> {
 | 
			
		||||
        const _opts: RfqRequestOpts = { ...constants.DEFAULT_RFQT_REQUEST_OPTS, ...options };
 | 
			
		||||
        // Originally a takerAddress was required for indicative quotes, but
 | 
			
		||||
        // now we've eliminated that requirement.  @0x/quote-server, however,
 | 
			
		||||
@@ -398,8 +402,8 @@ export class QuoteRequestor {
 | 
			
		||||
        return this._orderSignatureToMakerUri[nativeDataToId({ signature })];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private _isValidRfqtIndicativeQuoteResponse(response: V4RFQIndicativeQuote): boolean {
 | 
			
		||||
        const requiredKeys: Array<keyof V4RFQIndicativeQuote> = [
 | 
			
		||||
    private _isValidRfqtIndicativeQuoteResponse(response: V4RFQIndicativeQuoteMM): boolean {
 | 
			
		||||
        const requiredKeys: Array<keyof V4RFQIndicativeQuoteMM> = [
 | 
			
		||||
            'makerAmount',
 | 
			
		||||
            'takerAmount',
 | 
			
		||||
            'makerToken',
 | 
			
		||||
@@ -545,7 +549,10 @@ export class QuoteRequestor {
 | 
			
		||||
                            },
 | 
			
		||||
                        });
 | 
			
		||||
                        rfqMakerBlacklist.logTimeoutOrLackThereof(typedMakerUrl.url, latencyMs >= timeoutMs);
 | 
			
		||||
                        return { response: response.data, makerUri: typedMakerUrl.url };
 | 
			
		||||
                        return {
 | 
			
		||||
                            response: { ...response.data, makerUri: typedMakerUrl.url },
 | 
			
		||||
                            makerUri: typedMakerUrl.url,
 | 
			
		||||
                        };
 | 
			
		||||
                    } else {
 | 
			
		||||
                        if (this._altRfqCreds === undefined) {
 | 
			
		||||
                            throw new Error(`don't have credentials for alt MM`);
 | 
			
		||||
@@ -694,7 +701,6 @@ export class QuoteRequestor {
 | 
			
		||||
            } else {
 | 
			
		||||
                const secondsRemaining = msRemainingUntilExpiration.div(ONE_SECOND_MS);
 | 
			
		||||
                this._metrics?.measureExpirationForValidOrder(isLastLook, order.maker, secondsRemaining);
 | 
			
		||||
 | 
			
		||||
                const takerAmount = new BigNumber(order.takerAmount);
 | 
			
		||||
                const fillRatio = takerAmount.div(assetFillAmount);
 | 
			
		||||
                if (fillRatio.lt(1) && fillRatio.gte(FILL_RATIO_WARNING_LEVEL)) {
 | 
			
		||||
@@ -744,9 +750,9 @@ export class QuoteRequestor {
 | 
			
		||||
        comparisonPrice: BigNumber | undefined,
 | 
			
		||||
        options: RfqRequestOpts,
 | 
			
		||||
        assetOfferings: RfqMakerAssetOfferings,
 | 
			
		||||
    ): Promise<V4RFQIndicativeQuote[]> {
 | 
			
		||||
    ): Promise<V4RFQIndicativeQuoteMM[]> {
 | 
			
		||||
        // fetch quotes
 | 
			
		||||
        const rawQuotes = await this._getQuotesAsync<V4RFQIndicativeQuote>(
 | 
			
		||||
        const rawQuotes = await this._getQuotesAsync<V4RFQIndicativeQuoteMM>(
 | 
			
		||||
            makerToken,
 | 
			
		||||
            takerToken,
 | 
			
		||||
            assetFillAmount,
 | 
			
		||||
@@ -758,7 +764,7 @@ export class QuoteRequestor {
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // validate
 | 
			
		||||
        const validationFunction = (o: V4RFQIndicativeQuote) => this._isValidRfqtIndicativeQuoteResponse(o);
 | 
			
		||||
        const validationFunction = (o: V4RFQIndicativeQuoteMM) => this._isValidRfqtIndicativeQuoteResponse(o);
 | 
			
		||||
        const validQuotes = rawQuotes.filter(result => {
 | 
			
		||||
            const order = result.response;
 | 
			
		||||
            if (!validationFunction(order)) {
 | 
			
		||||
 
 | 
			
		||||
@@ -159,7 +159,11 @@ describe('MarketOperationUtils tests', () => {
 | 
			
		||||
        } else {
 | 
			
		||||
            requestor
 | 
			
		||||
                .setup(r => r.requestRfqtIndicativeQuotesAsync(...args))
 | 
			
		||||
                .returns(async () => results.map(r => r.order))
 | 
			
		||||
                .returns(async () =>
 | 
			
		||||
                    results.map(r => {
 | 
			
		||||
                        return { ...r.order, makerUri: 'https://foo.bar/' };
 | 
			
		||||
                    }),
 | 
			
		||||
                )
 | 
			
		||||
                .verifiable(verifiable);
 | 
			
		||||
        }
 | 
			
		||||
        return requestor;
 | 
			
		||||
 
 | 
			
		||||
@@ -155,7 +155,7 @@ describe('generateQuoteReport', async () => {
 | 
			
		||||
            makerAmount: rfqtOrder1.order.makerAmount,
 | 
			
		||||
            takerAmount: rfqtOrder1.order.takerAmount,
 | 
			
		||||
            fillableTakerAmount: rfqtOrder1.fillableTakerAmount,
 | 
			
		||||
            isRfqt: true,
 | 
			
		||||
            isRFQ: true,
 | 
			
		||||
            makerUri: 'https://rfqt1.provider.club',
 | 
			
		||||
            nativeOrder: rfqtOrder1.order,
 | 
			
		||||
            fillData: {
 | 
			
		||||
@@ -167,7 +167,7 @@ describe('generateQuoteReport', async () => {
 | 
			
		||||
            makerAmount: rfqtOrder2.order.makerAmount,
 | 
			
		||||
            takerAmount: rfqtOrder2.order.takerAmount,
 | 
			
		||||
            fillableTakerAmount: rfqtOrder2.fillableTakerAmount,
 | 
			
		||||
            isRfqt: true,
 | 
			
		||||
            isRFQ: true,
 | 
			
		||||
            makerUri: 'https://rfqt2.provider.club',
 | 
			
		||||
            nativeOrder: rfqtOrder2.order,
 | 
			
		||||
            fillData: {
 | 
			
		||||
@@ -179,7 +179,7 @@ describe('generateQuoteReport', async () => {
 | 
			
		||||
            makerAmount: orderbookOrder2.order.makerAmount,
 | 
			
		||||
            takerAmount: orderbookOrder2.order.takerAmount,
 | 
			
		||||
            fillableTakerAmount: orderbookOrder2.fillableTakerAmount,
 | 
			
		||||
            isRfqt: false,
 | 
			
		||||
            isRFQ: false,
 | 
			
		||||
            fillData: {
 | 
			
		||||
                order: orderbookOrder2.order,
 | 
			
		||||
            } as NativeLimitOrderFillData,
 | 
			
		||||
@@ -263,7 +263,7 @@ describe('generateQuoteReport', async () => {
 | 
			
		||||
            makerAmount: orderbookOrder1.order.makerAmount,
 | 
			
		||||
            takerAmount: orderbookOrder1.order.takerAmount,
 | 
			
		||||
            fillableTakerAmount: orderbookOrder1.fillableTakerAmount,
 | 
			
		||||
            isRfqt: false,
 | 
			
		||||
            isRFQ: false,
 | 
			
		||||
            fillData: {
 | 
			
		||||
                order: orderbookOrder1.order,
 | 
			
		||||
            } as NativeLimitOrderFillData,
 | 
			
		||||
 
 | 
			
		||||
@@ -494,15 +494,18 @@ describe('QuoteRequestor', async () => {
 | 
			
		||||
                expiry: makeThreeMinuteExpiry(),
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            const goodMMUri1 = 'https://1337.0.0.1';
 | 
			
		||||
            const goodMMUri2 = 'https://37.0.0.1';
 | 
			
		||||
 | 
			
		||||
            mockedRequests.push({
 | 
			
		||||
                ...mockedDefaults,
 | 
			
		||||
                endpoint: 'https://1337.0.0.1',
 | 
			
		||||
                endpoint: goodMMUri1,
 | 
			
		||||
                responseData: successfulQuote1,
 | 
			
		||||
            });
 | 
			
		||||
            // [GOOD] Another Successful response
 | 
			
		||||
            mockedRequests.push({
 | 
			
		||||
                ...mockedDefaults,
 | 
			
		||||
                endpoint: 'https://37.0.0.1',
 | 
			
		||||
                endpoint: goodMMUri2,
 | 
			
		||||
                responseData: successfulQuote1,
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
@@ -532,6 +535,16 @@ describe('QuoteRequestor', async () => {
 | 
			
		||||
                responseData: { ...successfulQuote1, takerToken: otherToken1 },
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            const assetOfferings: { [k: string]: [[string, string]] } = {
 | 
			
		||||
                'https://420.0.0.1': [[makerToken, takerToken]],
 | 
			
		||||
                'https://421.0.0.1': [[makerToken, takerToken]],
 | 
			
		||||
                'https://422.0.0.1': [[makerToken, takerToken]],
 | 
			
		||||
                'https://423.0.0.1': [[makerToken, takerToken]],
 | 
			
		||||
                'https://424.0.0.1': [[makerToken, takerToken]],
 | 
			
		||||
            };
 | 
			
		||||
            assetOfferings[goodMMUri1] = [[makerToken, takerToken]];
 | 
			
		||||
            assetOfferings[goodMMUri2] = [[makerToken, takerToken]];
 | 
			
		||||
 | 
			
		||||
            return testHelpers.withMockedRfqQuotes(
 | 
			
		||||
                mockedRequests,
 | 
			
		||||
                [],
 | 
			
		||||
@@ -539,15 +552,7 @@ describe('QuoteRequestor', async () => {
 | 
			
		||||
                async () => {
 | 
			
		||||
                    const qr = new QuoteRequestor(
 | 
			
		||||
                        {}, // No RFQ-T asset offerings
 | 
			
		||||
                        {
 | 
			
		||||
                            'https://1337.0.0.1': [[makerToken, takerToken]],
 | 
			
		||||
                            'https://37.0.0.1': [[makerToken, takerToken]],
 | 
			
		||||
                            'https://420.0.0.1': [[makerToken, takerToken]],
 | 
			
		||||
                            'https://421.0.0.1': [[makerToken, takerToken]],
 | 
			
		||||
                            'https://422.0.0.1': [[makerToken, takerToken]],
 | 
			
		||||
                            'https://423.0.0.1': [[makerToken, takerToken]],
 | 
			
		||||
                            'https://424.0.0.1': [[makerToken, takerToken]],
 | 
			
		||||
                        },
 | 
			
		||||
                        assetOfferings,
 | 
			
		||||
                        quoteRequestorHttpClient,
 | 
			
		||||
                    );
 | 
			
		||||
                    const resp = await qr.requestRfqmIndicativeQuotesAsync(
 | 
			
		||||
@@ -572,7 +577,12 @@ describe('QuoteRequestor', async () => {
 | 
			
		||||
                            },
 | 
			
		||||
                        },
 | 
			
		||||
                    );
 | 
			
		||||
                    expect(resp.sort()).to.eql([successfulQuote1, successfulQuote1].sort());
 | 
			
		||||
                    expect(resp.sort()).to.eql(
 | 
			
		||||
                        [
 | 
			
		||||
                            { ...successfulQuote1, makerUri: goodMMUri1 },
 | 
			
		||||
                            { ...successfulQuote1, makerUri: goodMMUri2 },
 | 
			
		||||
                        ].sort(),
 | 
			
		||||
                    );
 | 
			
		||||
                },
 | 
			
		||||
                quoteRequestorHttpClient,
 | 
			
		||||
            );
 | 
			
		||||
@@ -622,9 +632,12 @@ describe('QuoteRequestor', async () => {
 | 
			
		||||
                expiry: makeThreeMinuteExpiry(),
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            const goodMMUri1 = 'https://1337.0.0.1';
 | 
			
		||||
            const goodMMUri2 = 'https://37.0.0.1';
 | 
			
		||||
 | 
			
		||||
            mockedRequests.push({
 | 
			
		||||
                ...mockedDefaults,
 | 
			
		||||
                endpoint: 'https://1337.0.0.1',
 | 
			
		||||
                endpoint: goodMMUri1,
 | 
			
		||||
                responseData: successfulQuote1,
 | 
			
		||||
            });
 | 
			
		||||
            // Test out a bad response code, ensure it doesnt cause throw
 | 
			
		||||
@@ -655,28 +668,26 @@ describe('QuoteRequestor', async () => {
 | 
			
		||||
            // Another Successful response
 | 
			
		||||
            mockedRequests.push({
 | 
			
		||||
                ...mockedDefaults,
 | 
			
		||||
                endpoint: 'https://37.0.0.1',
 | 
			
		||||
                endpoint: goodMMUri2,
 | 
			
		||||
                responseData: successfulQuote1,
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            const assetOfferings: { [k: string]: [[string, string]] } = {
 | 
			
		||||
                'https://420.0.0.1': [[makerToken, takerToken]],
 | 
			
		||||
                'https://421.0.0.1': [[makerToken, takerToken]],
 | 
			
		||||
                'https://422.0.0.1': [[makerToken, takerToken]],
 | 
			
		||||
                'https://423.0.0.1': [[makerToken, takerToken]],
 | 
			
		||||
                'https://424.0.0.1': [[makerToken, takerToken]],
 | 
			
		||||
            };
 | 
			
		||||
            assetOfferings[goodMMUri1] = [[makerToken, takerToken]];
 | 
			
		||||
            assetOfferings[goodMMUri2] = [[makerToken, takerToken]];
 | 
			
		||||
 | 
			
		||||
            return testHelpers.withMockedRfqQuotes(
 | 
			
		||||
                mockedRequests,
 | 
			
		||||
                [],
 | 
			
		||||
                RfqQuoteEndpoint.Indicative,
 | 
			
		||||
                async () => {
 | 
			
		||||
                    const qr = new QuoteRequestor(
 | 
			
		||||
                        {
 | 
			
		||||
                            'https://1337.0.0.1': [[makerToken, takerToken]],
 | 
			
		||||
                            'https://420.0.0.1': [[makerToken, takerToken]],
 | 
			
		||||
                            'https://421.0.0.1': [[makerToken, takerToken]],
 | 
			
		||||
                            'https://422.0.0.1': [[makerToken, takerToken]],
 | 
			
		||||
                            'https://423.0.0.1': [[makerToken, takerToken]],
 | 
			
		||||
                            'https://424.0.0.1': [[makerToken, takerToken]],
 | 
			
		||||
                            'https://37.0.0.1': [[makerToken, takerToken]],
 | 
			
		||||
                        },
 | 
			
		||||
                        {},
 | 
			
		||||
                        quoteRequestorHttpClient,
 | 
			
		||||
                    );
 | 
			
		||||
                    const qr = new QuoteRequestor(assetOfferings, {}, quoteRequestorHttpClient);
 | 
			
		||||
                    const resp = await qr.requestRfqtIndicativeQuotesAsync(
 | 
			
		||||
                        makerToken,
 | 
			
		||||
                        takerToken,
 | 
			
		||||
@@ -693,7 +704,12 @@ describe('QuoteRequestor', async () => {
 | 
			
		||||
                            intentOnFilling: true,
 | 
			
		||||
                        },
 | 
			
		||||
                    );
 | 
			
		||||
                    expect(resp.sort()).to.eql([successfulQuote1, successfulQuote1].sort());
 | 
			
		||||
                    expect(resp.sort()).to.eql(
 | 
			
		||||
                        [
 | 
			
		||||
                            { ...successfulQuote1, makerUri: goodMMUri1 },
 | 
			
		||||
                            { ...successfulQuote1, makerUri: goodMMUri2 },
 | 
			
		||||
                        ].sort(),
 | 
			
		||||
                    );
 | 
			
		||||
                },
 | 
			
		||||
                quoteRequestorHttpClient,
 | 
			
		||||
            );
 | 
			
		||||
@@ -784,7 +800,7 @@ describe('QuoteRequestor', async () => {
 | 
			
		||||
                            makerEndpointMaxResponseTimeMs: maxTimeoutMs,
 | 
			
		||||
                        },
 | 
			
		||||
                    );
 | 
			
		||||
                    expect(resp.sort()).to.eql([successfulQuote1].sort()); // notice only one result, despite two requests made
 | 
			
		||||
                    expect(resp.sort()).to.eql([{ ...successfulQuote1, makerUri: 'https://1337.0.0.1' }].sort()); // notice only one result, despite two requests made
 | 
			
		||||
                },
 | 
			
		||||
                quoteRequestorHttpClient,
 | 
			
		||||
            );
 | 
			
		||||
@@ -847,7 +863,7 @@ describe('QuoteRequestor', async () => {
 | 
			
		||||
                            intentOnFilling: true,
 | 
			
		||||
                        },
 | 
			
		||||
                    );
 | 
			
		||||
                    expect(resp.sort()).to.eql([successfulQuote1].sort());
 | 
			
		||||
                    expect(resp.sort()).to.eql([{ ...successfulQuote1, makerUri: 'https://1337.0.0.1' }].sort());
 | 
			
		||||
                },
 | 
			
		||||
                quoteRequestorHttpClient,
 | 
			
		||||
            );
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,14 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "version": "6.9.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Add Celo addresses",
 | 
			
		||||
                "pr": 368
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1637102971
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1635903615,
 | 
			
		||||
        "version": "6.8.1",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v6.9.0 - _November 16, 2021_
 | 
			
		||||
 | 
			
		||||
    * Add Celo addresses (#368)
 | 
			
		||||
 | 
			
		||||
## v6.8.1 - _November 3, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 
 | 
			
		||||
@@ -418,5 +418,47 @@
 | 
			
		||||
            "fillQuoteTransformer": "0x71de60a1b160094a3f6c7e1b883ff9337d639131",
 | 
			
		||||
            "positiveSlippageFeeTransformer": "0xe87d69b285005cc82b53b844322652c49ed64600"
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    "42220": {
 | 
			
		||||
        "erc20Proxy": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "erc721Proxy": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "zrxToken": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "etherToken": "0x471ece3750da237f93b8e339c536989b8978a438",
 | 
			
		||||
        "exchangeV2": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "exchange": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "assetProxyOwner": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "zeroExGovernor": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "forwarder": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "coordinatorRegistry": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "coordinator": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "multiAssetProxy": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "staticCallProxy": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "erc1155Proxy": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "devUtils": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "zrxVault": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "staking": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "stakingProxy": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "erc20BridgeProxy": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "erc20BridgeSampler": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "chaiBridge": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "dydxBridge": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "godsUnchainedValidator": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "broker": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "chainlinkStopLimit": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "maximumGasPrice": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "dexForwarderBridge": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "exchangeProxyGovernor": "0x92115010fd9b170d4918b102efc86b1b7bebdc7f",
 | 
			
		||||
        "exchangeProxy": "0xdef1c0ded9bec7f1a1670819833240f027b25eff",
 | 
			
		||||
        "exchangeProxyTransformerDeployer": "0x1fe80d5ad9464dba2d60b88e449305f184823f8a",
 | 
			
		||||
        "exchangeProxyFlashWallet": "0xdb6f1920a889355780af7570773609bd8cb1f498",
 | 
			
		||||
        "exchangeProxyLiquidityProviderSandbox": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "zrxTreasury": "0x0000000000000000000000000000000000000000",
 | 
			
		||||
        "transformers": {
 | 
			
		||||
            "wethTransformer": "0x948e03e708b4c62c63f89157a3aa76b986c110ed",
 | 
			
		||||
            "payTakerTransformer": "0x90fb6c638ece8f3e4bfda1c6d6425626b53148b0",
 | 
			
		||||
            "affiliateFeeTransformer": "0xc93913692ed073cb0cb37d4a760afd7916e9cb01",
 | 
			
		||||
            "fillQuoteTransformer": "0xa825d4d3c4d2820c52da69fcccf269b4081871f2",
 | 
			
		||||
            "positiveSlippageFeeTransformer": "0x9ffc7a79133ed5242777e40764777a6d5aab282c"
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contract-addresses",
 | 
			
		||||
    "version": "6.8.1",
 | 
			
		||||
    "version": "6.9.0",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
 
 | 
			
		||||
@@ -54,6 +54,7 @@ export enum ChainId {
 | 
			
		||||
    PolygonMumbai = 80001,
 | 
			
		||||
    Avalanche = 43114,
 | 
			
		||||
    Fantom = 250,
 | 
			
		||||
    Celo = 42220,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,13 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1637102971,
 | 
			
		||||
        "version": "13.18.3",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1635903615,
 | 
			
		||||
        "version": "13.18.2",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v13.18.3 - _November 16, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v13.18.2 - _November 3, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contract-wrappers",
 | 
			
		||||
    "version": "13.18.2",
 | 
			
		||||
    "version": "13.18.3",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -57,7 +57,7 @@
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0x/assert": "^3.0.29",
 | 
			
		||||
        "@0x/base-contract": "^6.4.2",
 | 
			
		||||
        "@0x/contract-addresses": "^6.8.1",
 | 
			
		||||
        "@0x/contract-addresses": "^6.9.0",
 | 
			
		||||
        "@0x/json-schemas": "^6.3.0",
 | 
			
		||||
        "@0x/types": "^3.3.4",
 | 
			
		||||
        "@0x/utils": "^6.4.4",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,22 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1637102971,
 | 
			
		||||
        "version": "8.1.12",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1637065617,
 | 
			
		||||
        "version": "8.1.11",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "8.1.10",
 | 
			
		||||
        "changes": [
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,14 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v8.1.12 - _November 16, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v8.1.11 - _November 16, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v8.1.10 - _November 3, 2021_
 | 
			
		||||
 | 
			
		||||
    * Add OtcOrders to fullMigrateAsync (#350)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/migrations",
 | 
			
		||||
    "version": "8.1.10",
 | 
			
		||||
    "version": "8.1.12",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -68,20 +68,20 @@
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0x/base-contract": "^6.4.2",
 | 
			
		||||
        "@0x/contract-addresses": "^6.8.1",
 | 
			
		||||
        "@0x/contract-addresses": "^6.9.0",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^3.7.19",
 | 
			
		||||
        "@0x/contracts-coordinator": "^3.1.38",
 | 
			
		||||
        "@0x/contracts-dev-utils": "^1.3.36",
 | 
			
		||||
        "@0x/contracts-erc1155": "^2.1.37",
 | 
			
		||||
        "@0x/contracts-erc20": "^3.3.22",
 | 
			
		||||
        "@0x/contracts-erc20": "^3.3.23",
 | 
			
		||||
        "@0x/contracts-erc721": "^3.1.37",
 | 
			
		||||
        "@0x/contracts-exchange": "^3.2.38",
 | 
			
		||||
        "@0x/contracts-exchange-forwarder": "^4.2.38",
 | 
			
		||||
        "@0x/contracts-extensions": "^6.2.32",
 | 
			
		||||
        "@0x/contracts-multisig": "^4.1.38",
 | 
			
		||||
        "@0x/contracts-staking": "^2.0.45",
 | 
			
		||||
        "@0x/contracts-utils": "^4.8.3",
 | 
			
		||||
        "@0x/contracts-zero-ex": "^0.29.3",
 | 
			
		||||
        "@0x/contracts-utils": "^4.8.4",
 | 
			
		||||
        "@0x/contracts-zero-ex": "^0.29.5",
 | 
			
		||||
        "@0x/sol-compiler": "^4.7.5",
 | 
			
		||||
        "@0x/subproviders": "^6.6.0",
 | 
			
		||||
        "@0x/typescript-typings": "^5.2.1",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,13 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1637102971,
 | 
			
		||||
        "version": "1.9.5",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1635903615,
 | 
			
		||||
        "version": "1.9.4",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v1.9.5 - _November 16, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.9.4 - _November 3, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/protocol-utils",
 | 
			
		||||
    "version": "1.9.4",
 | 
			
		||||
    "version": "1.9.5",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -63,8 +63,8 @@
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0x/assert": "^3.0.29",
 | 
			
		||||
        "@0x/contract-addresses": "^6.8.1",
 | 
			
		||||
        "@0x/contract-wrappers": "^13.18.2",
 | 
			
		||||
        "@0x/contract-addresses": "^6.9.0",
 | 
			
		||||
        "@0x/contract-wrappers": "^13.18.3",
 | 
			
		||||
        "@0x/json-schemas": "^6.3.0",
 | 
			
		||||
        "@0x/subproviders": "^6.6.0",
 | 
			
		||||
        "@0x/utils": "^6.4.4",
 | 
			
		||||
 
 | 
			
		||||
@@ -6402,6 +6402,7 @@ fake-merkle-patricia-tree@^1.0.1:
 | 
			
		||||
fast-abi@^0.0.2:
 | 
			
		||||
  version "0.0.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/fast-abi/-/fast-abi-0.0.2.tgz#da5f796fd7c7b0c966d916ee21daae3eca61c07c"
 | 
			
		||||
  integrity sha512-k/2s63SkFf6jU2LyF6oQC5/N+L90q6VD1wkp2NXo+DSHoTeOJD2Q6Egpcs+bTPODik0CHxjb7lORgsG+QCRq/Q==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@mapbox/node-pre-gyp" "^1.0.4"
 | 
			
		||||
    neon-cli "^0.8.0"
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user