Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/deps update/tests migration #180

Merged
merged 24 commits into from
Nov 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Refer to the documentation of the ParaSwap API: https://developers.paraswap.netw

**Canonical**: bring only the functions you actually need

**Lightweight**: 400B Gzipped for the minimal variant
**Lightweight**: 10KB Gzipped for the minimal variant

## Installing ParaSwap SDK

Expand All @@ -29,7 +29,7 @@ You can see some examples in [/src/examples](src/examples) directory.

### Simple SDK

Can be created by providing `chainId` and either `axios` or `window.fetch` (or alternative `fetch` implementation), and an optional `version` (`'5'` or `'6.1'`) parameter that corresponds to the API version SDK will be making requests to. The resulting SDK will be able to use all methods that query the API.
Can be created by providing `chainId` and either `axios` or `window.fetch` (or alternative `fetch` implementation), and an optional `version` (`'5'` or `'6.2'`) parameter that corresponds to the API version SDK will be making requests to. The resulting SDK will be able to use all methods that query the API.

```ts
import { constructSimpleSDK } from '@paraswap/sdk';
Expand Down
25 changes: 23 additions & 2 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,38 @@
import * as dotenv from 'dotenv';
import type { HardhatUserConfig } from 'hardhat/config';
import 'hardhat-switch-network';

dotenv.config();

const TEST_MNEMONIC =
'radar blur cabbage chef fix engine embark joy scheme fiction master release';

const config: HardhatUserConfig = {
solidity: '0.8.24',
networks: {
hardhat: {
forking: {
url: process.env.PROVIDER_URL!, // Replace with your actual Alchemy/Infura URL
// Optional forking configurations (e.g., block number):
// blockNumber: 12345678,
},
// Optional forking configurations (e.g., block number):
// blockNumber: 12345678,
chainId: 1,
// have to config hardhat with fixed accounts unlocked, otherwise signTx and signTyped data fail when used in RPC calls to Node
// which breaks web3.js
// ethers signs data and txs locally off-chain as long as it has provate key
// web3 is a bit harder to init wallets for locally.
// impersonateAccounts doesn't work, even though it should logically fully unlock accounts,
// but only remore accounts are unlocked, fixed are not,
// so we always need to only use accounts generated from this mnemonic

// refs:
// https://github.com/NomicFoundation/hardhat/issues/3059
// https://github.com/NomicFoundation/hardhat/issues/1226
accounts: { mnemonic: TEST_MNEMONIC }, // and with fixed
// dynamically switch between networks configured here
// by calling `hre.switchNetwork(networkName)` thanks to hardhat-switch-network plugin
gasPrice: 8e9,
initialBaseFeePerGas: 1e8, // will break if used with a chain without eip1559
},
},
};
Expand Down
41 changes: 23 additions & 18 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"testEnvironment": "node"
},
"engines": {
"node": ">=12"
"node": ">=18"
},
"size-limit": [
{
Expand All @@ -49,31 +49,33 @@
],
"devDependencies": {
"@size-limit/preset-small-lib": "^11.1.6",
"@tsconfig/recommended": "^1.0.7",
"axios": "^1.1.3",
"bignumber.js": "^9.0.2",
"dotenv": "^16.0.0",
"@tsconfig/recommended": "^1.0.8",
"axios": "^1.7.7",
"bignumber.js": "^9.1.2",
"dotenv": "^16.4.5",
"dts-cli": "^2.0.5",
"ethers": "^5.6.5",
"ganache": "^7.9.2",
"hardhat": "^2.22.14",
"ethers": "^6.13.4",
"ethersV5": "npm:ethers@5",
"hardhat": "^2.22.15",
"hardhat-switch-network": "^1.1.1",
"husky": "^9.1.6",
"isomorphic-unfetch": "^3.1.0",
"isomorphic-unfetch": "^4.0.2",
"size-limit": "^11.1.6",
"tslib": "^2.8.0",
"typedoc": "^0.26.10",
"typedoc-plugin-markdown": "^4.2.9",
"tslib": "^2.8.1",
"typedoc": "^0.26.11",
"typedoc-plugin-markdown": "^4.2.10",
"typedoc-plugin-missing-exports": "^3.0.0",
"typedoc-plugin-replace-text": "^4.0.0",
"typescript": "^5.6.3",
"viem": "^2.21.32",
"wagmi": "^2.12.22",
"web3": "^1.7.3"
"viem": "^2.21.39",
"wagmi": "^2.12.25",
"web3": "^4.14.0"
},
"peerDependencies": {
"axios": ">=0.25.0 <2.0.0",
"ethers": "^5.5.0",
"web3": "^1.7.1"
"ethers": "^5.5.0 || ^6.0.0",
"viem": "^2.21.0",
"web3": "^4.14.0"
},
"peerDependenciesMeta": {
"axios": {
Expand All @@ -84,11 +86,14 @@
},
"web3": {
"optional": true
},
"viem": {
"optional": true
}
},
"dependencies": {
"@paraswap/core": "2.4.0",
"ts-essentials": "^10.0.2"
"ts-essentials": "^10.0.3"
},
"author": "ParaSwap",
"description": "ParaSwap SDK",
Expand Down
38 changes: 38 additions & 0 deletions src/examples/ethersV6.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import axios from 'axios';
import { ethers } from 'ethers';
import {
constructPartialSDK,
constructFullSDK,
constructGetAdapters,
constructEthersV6ContractCaller,
constructAxiosFetcher,
} from '..';

const fetcher = constructAxiosFetcher(axios);

const provider = ethers.getDefaultProvider(1);
const contractCaller = constructEthersV6ContractCaller({
ethersV6ProviderOrSigner: provider,
EthersV6Contract: ethers.Contract,
});

const paraswap = constructFullSDK({
chainId: 1,
fetcher,
contractCaller,
});

const res = paraswap.swap.getAdapters();

// type Promise<ContractTransaction>
const txResponse = paraswap.swap.approveToken('1', '0x...');
// type Promise<ContractTransaction[]>
const txResponses = paraswap.swap.approveTokenBulk('1', ['0x...']);

const partial = constructPartialSDK(
{ apiURL: '', chainId: 1, fetcher },
constructGetAdapters
);

const res1 = partial.getAdapters();
2 changes: 1 addition & 1 deletion src/examples/limitOrders_all.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import axios from 'axios';
import BigNumber from 'bignumber.js';
import { ethers } from 'ethers';
import { ethers } from 'ethersV5';
import { assert } from 'ts-essentials';
import {
// swap methods
Expand Down
2 changes: 1 addition & 1 deletion src/examples/limitOrders_partial.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import axios from 'axios';
import BigNumber from 'bignumber.js';
import { ethers } from 'ethers';
import { ethers } from 'ethersV5';
import { assert } from 'ts-essentials';
import {
// swap methods
Expand Down
2 changes: 1 addition & 1 deletion src/examples/limitOrders_postOrder.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import axios from 'axios';
import { ethers } from 'ethers';
import { ethers } from 'ethersV5';

import {
// swap methods
Expand Down
2 changes: 1 addition & 1 deletion src/examples/partial.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import axios from 'axios';
import { ethers } from 'ethers';
import { ethers } from 'ethersV5';
import {
constructPartialSDK,
constructGetAdapters,
Expand Down
6 changes: 3 additions & 3 deletions src/examples/sdk.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import axios from 'axios';
import { ethers } from 'ethers';
import { ethers } from 'ethersV5';
import {
constructPartialSDK,
constructFullSDK,
constructGetAdapters,
constructEthersContractCaller,
constructEthersV5ContractCaller,
constructAxiosFetcher,
} from '..';

const fetcher = constructAxiosFetcher(axios);

const provider = ethers.getDefaultProvider(1);
const contractCaller = constructEthersContractCaller({
const contractCaller = constructEthersV5ContractCaller({
ethersProviderOrSigner: provider,
EthersContract: ethers.Contract,
});
Expand Down
2 changes: 1 addition & 1 deletion src/examples/simple.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import axios from 'axios';
import { ethers, Wallet } from 'ethers';
import { ethers, Wallet } from 'ethersV5';
import {
constructSimpleSDK,
ContractMethod,
Expand Down
13 changes: 11 additions & 2 deletions src/helpers/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
import { EthersV5ProviderDeps } from './providers/ethers';
import { EthersV6ProviderDeps } from './providers/ethersV6';
export { constructFetcher as constructAxiosFetcher } from './fetchers/axios';
export { constructFetcher as constructFetchFetcher } from './fetchers/fetch';
export {
constructContractCaller as constructEthersContractCaller,
EthersProviderDeps,
constructEthersV5ContractCaller as constructEthersContractCaller,
constructEthersV5ContractCaller,
EthersV5ProviderDeps,
} from './providers/ethers';
export {
constructContractCaller as constructEthersV6ContractCaller,
EthersV6ProviderDeps,
} from './providers/ethersV6';
export type EthersProviderDeps = EthersV5ProviderDeps | EthersV6ProviderDeps;

export {
constructContractCaller as constructWeb3ContractCaller,
Web3UnpromiEvent,
Expand Down
95 changes: 18 additions & 77 deletions src/helpers/misc.ts
Original file line number Diff line number Diff line change
@@ -1,70 +1,4 @@
import type {
Contract as EthersContract,
ContractFunction as EthersContractFunction,
PopulatedTransaction as EthersPopulatedTransaction,
BigNumber as EthersBigNumber,
} from 'ethers';
import type {
ContractSendMethod as Web3ContractSendMethod,
Contract as Web3Contract,
} from 'web3-eth-contract';
import { assert, Primitive } from 'ts-essentials';

import type { AxiosError, AxiosResponse } from 'axios';

export type EthersContractWithMethod<T extends string> = EthersContract & {
readonly [method in T]: EthersContractFunction;
} & {
readonly functions: { [method in T]: EthersContractFunction };

readonly callStatic: { [method in T]: EthersContractFunction };
readonly estimateGas: {
[method in T]: EthersContractFunction<EthersBigNumber>;
};
readonly populateTransaction: {
[method in T]: EthersContractFunction<EthersPopulatedTransaction>;
};
};

export function ethersContractHasMethods<T extends string>(
contract: EthersContract,
...methods: T[]
): contract is EthersContractWithMethod<T> {
return methods.every((method) => typeof contract[method] === 'function');
}

export function assertEthersContractHasMethods<T extends string>(
contract: EthersContract,
...methods: T[]
): asserts contract is EthersContractWithMethod<T> {
assert(
ethersContractHasMethods(contract, ...methods),
`Contract must have methods: ${methods.join(', ')}`
);
}

export type Web3ContractWithMethod<T extends string> = Web3Contract & {
methods: { [method in T]: Web3ContractSendMethod };
};

export function web3ContractHasMethods<T extends string>(
contract: Web3Contract,
...methods: T[]
): contract is Web3ContractWithMethod<T> {
return methods.every(
(method) => typeof contract.methods[method] === 'function'
);
}

export function assertWeb3ContractHasMethods<T extends string>(
contract: Web3Contract,
...methods: T[]
): asserts contract is Web3ContractWithMethod<T> {
assert(
web3ContractHasMethods(contract, ...methods),
`Contract must have methods: ${methods.join(', ')}`
);
}
import type { Primitive } from 'ts-essentials';

export const objectToFilledEntries = <T extends Record<string, unknown>>(
object: T
Expand All @@ -91,16 +25,23 @@ export const constructSearchString = <
return queryString && `?${queryString}`;
};

type FetcherErrorConstructorInput = Pick<
AxiosError,
'code' | 'request' | 'isAxiosError' | 'message'
> & {
response?: Pick<
AxiosResponse,
'data' | 'status' | 'statusText' | 'headers'
> & {
config: { url?: string; method?: string };
};
type MinAxiosError = {
code?: string;
request?: any;
isAxiosError: boolean;
message: string;
};

type MinAxiosResponse = {
data: any;
status: number;
statusText: string;
headers: Record<string, any>;
config: { url?: string; method?: string };
};

type FetcherErrorConstructorInput = MinAxiosError & {
response?: MinAxiosResponse;
};

export interface FetcherErrorInterface extends FetcherErrorConstructorInput {
Expand Down
Loading
Loading