Merge branch 'main' into integrator_service

This commit is contained in:
Dmitry Leleko
2023-10-04 09:08:46 +02:00
40 changed files with 464 additions and 626 deletions

View File

@@ -71,7 +71,7 @@ npm i @orionprotocol/sdk
## Initialization
> :warning: **Ethers ^5.6.0 required**
> :warning: **Ethers ^6.7.0 required**
```js
// Node.js

View File

@@ -28,7 +28,7 @@ import { BaseProvider } from "@metamask/providers";
import { ethers } from "ethers";
const startApp = async (provider: BaseProvider) => {
const web3Provider = new ethers.providers.Web3Provider(provider);
const web3Provider = new ethers.Web3Provider(provider);
await web3Provider.ready;
const signer = web3Provider.getSigner(); // ready to go
};

350
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "@orionprotocol/sdk",
"version": "0.19.89-rc22",
"version": "0.20.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@orionprotocol/sdk",
"version": "0.19.89-rc22",
"version": "0.20.1",
"hasInstallScript": true,
"license": "ISC",
"dependencies": {
@@ -17,7 +17,7 @@
"bignumber.js": "^9.1.1",
"bson-objectid": "^2.0.4",
"buffer": "^6.0.3",
"ethers": "^5.6.2",
"ethers": "^6.7.1",
"express": "^4.18.2",
"isomorphic-ws": "^5.0.0",
"just-clone": "^6.2.0",
@@ -76,6 +76,11 @@
"node": ">=0.10.0"
}
},
"node_modules/@adraffy/ens-normalize": {
"version": "1.9.2",
"resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.9.2.tgz",
"integrity": "sha512-0h+FrQDqe2Wn+IIGFkTCd4aAwTJ+7834Ek1COohCyV26AXhwQ7WQaz+4F/nLOeVl/3BtWHOHLPsq46V8YB46Eg=="
},
"node_modules/@ampproject/remapping": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz",
@@ -716,32 +721,6 @@
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
"node_modules/@ethersproject/abi": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.7.0.tgz",
"integrity": "sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==",
"funding": [
{
"type": "individual",
"url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
},
{
"type": "individual",
"url": "https://www.buymeacoffee.com/ricmoo"
}
],
"dependencies": {
"@ethersproject/address": "^5.7.0",
"@ethersproject/bignumber": "^5.7.0",
"@ethersproject/bytes": "^5.7.0",
"@ethersproject/constants": "^5.7.0",
"@ethersproject/hash": "^5.7.0",
"@ethersproject/keccak256": "^5.7.0",
"@ethersproject/logger": "^5.7.0",
"@ethersproject/properties": "^5.7.0",
"@ethersproject/strings": "^5.7.0"
}
},
"node_modules/@ethersproject/abstract-provider": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz",
@@ -903,33 +882,6 @@
"@ethersproject/bignumber": "^5.7.0"
}
},
"node_modules/@ethersproject/contracts": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.7.0.tgz",
"integrity": "sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg==",
"funding": [
{
"type": "individual",
"url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
},
{
"type": "individual",
"url": "https://www.buymeacoffee.com/ricmoo"
}
],
"dependencies": {
"@ethersproject/abi": "^5.7.0",
"@ethersproject/abstract-provider": "^5.7.0",
"@ethersproject/abstract-signer": "^5.7.0",
"@ethersproject/address": "^5.7.0",
"@ethersproject/bignumber": "^5.7.0",
"@ethersproject/bytes": "^5.7.0",
"@ethersproject/constants": "^5.7.0",
"@ethersproject/logger": "^5.7.0",
"@ethersproject/properties": "^5.7.0",
"@ethersproject/transactions": "^5.7.0"
}
},
"node_modules/@ethersproject/hash": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.7.0.tgz",
@@ -956,65 +908,6 @@
"@ethersproject/strings": "^5.7.0"
}
},
"node_modules/@ethersproject/hdnode": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.7.0.tgz",
"integrity": "sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg==",
"funding": [
{
"type": "individual",
"url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
},
{
"type": "individual",
"url": "https://www.buymeacoffee.com/ricmoo"
}
],
"dependencies": {
"@ethersproject/abstract-signer": "^5.7.0",
"@ethersproject/basex": "^5.7.0",
"@ethersproject/bignumber": "^5.7.0",
"@ethersproject/bytes": "^5.7.0",
"@ethersproject/logger": "^5.7.0",
"@ethersproject/pbkdf2": "^5.7.0",
"@ethersproject/properties": "^5.7.0",
"@ethersproject/sha2": "^5.7.0",
"@ethersproject/signing-key": "^5.7.0",
"@ethersproject/strings": "^5.7.0",
"@ethersproject/transactions": "^5.7.0",
"@ethersproject/wordlists": "^5.7.0"
}
},
"node_modules/@ethersproject/json-wallets": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz",
"integrity": "sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g==",
"funding": [
{
"type": "individual",
"url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
},
{
"type": "individual",
"url": "https://www.buymeacoffee.com/ricmoo"
}
],
"dependencies": {
"@ethersproject/abstract-signer": "^5.7.0",
"@ethersproject/address": "^5.7.0",
"@ethersproject/bytes": "^5.7.0",
"@ethersproject/hdnode": "^5.7.0",
"@ethersproject/keccak256": "^5.7.0",
"@ethersproject/logger": "^5.7.0",
"@ethersproject/pbkdf2": "^5.7.0",
"@ethersproject/properties": "^5.7.0",
"@ethersproject/random": "^5.7.0",
"@ethersproject/strings": "^5.7.0",
"@ethersproject/transactions": "^5.7.0",
"aes-js": "3.0.0",
"scrypt-js": "3.0.1"
}
},
"node_modules/@ethersproject/keccak256": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz",
@@ -1067,25 +960,6 @@
"@ethersproject/logger": "^5.7.0"
}
},
"node_modules/@ethersproject/pbkdf2": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz",
"integrity": "sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw==",
"funding": [
{
"type": "individual",
"url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
},
{
"type": "individual",
"url": "https://www.buymeacoffee.com/ricmoo"
}
],
"dependencies": {
"@ethersproject/bytes": "^5.7.0",
"@ethersproject/sha2": "^5.7.0"
}
},
"node_modules/@ethersproject/properties": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.7.0.tgz",
@@ -1242,29 +1116,6 @@
"hash.js": "1.1.7"
}
},
"node_modules/@ethersproject/solidity": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.7.0.tgz",
"integrity": "sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA==",
"funding": [
{
"type": "individual",
"url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
},
{
"type": "individual",
"url": "https://www.buymeacoffee.com/ricmoo"
}
],
"dependencies": {
"@ethersproject/bignumber": "^5.7.0",
"@ethersproject/bytes": "^5.7.0",
"@ethersproject/keccak256": "^5.7.0",
"@ethersproject/logger": "^5.7.0",
"@ethersproject/sha2": "^5.7.0",
"@ethersproject/strings": "^5.7.0"
}
},
"node_modules/@ethersproject/strings": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.7.0.tgz",
@@ -1311,58 +1162,6 @@
"@ethersproject/signing-key": "^5.7.0"
}
},
"node_modules/@ethersproject/units": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.7.0.tgz",
"integrity": "sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg==",
"funding": [
{
"type": "individual",
"url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
},
{
"type": "individual",
"url": "https://www.buymeacoffee.com/ricmoo"
}
],
"dependencies": {
"@ethersproject/bignumber": "^5.7.0",
"@ethersproject/constants": "^5.7.0",
"@ethersproject/logger": "^5.7.0"
}
},
"node_modules/@ethersproject/wallet": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.7.0.tgz",
"integrity": "sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA==",
"funding": [
{
"type": "individual",
"url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
},
{
"type": "individual",
"url": "https://www.buymeacoffee.com/ricmoo"
}
],
"dependencies": {
"@ethersproject/abstract-provider": "^5.7.0",
"@ethersproject/abstract-signer": "^5.7.0",
"@ethersproject/address": "^5.7.0",
"@ethersproject/bignumber": "^5.7.0",
"@ethersproject/bytes": "^5.7.0",
"@ethersproject/hash": "^5.7.0",
"@ethersproject/hdnode": "^5.7.0",
"@ethersproject/json-wallets": "^5.7.0",
"@ethersproject/keccak256": "^5.7.0",
"@ethersproject/logger": "^5.7.0",
"@ethersproject/properties": "^5.7.0",
"@ethersproject/random": "^5.7.0",
"@ethersproject/signing-key": "^5.7.0",
"@ethersproject/transactions": "^5.7.0",
"@ethersproject/wordlists": "^5.7.0"
}
},
"node_modules/@ethersproject/web": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.1.tgz",
@@ -1385,28 +1184,6 @@
"@ethersproject/strings": "^5.7.0"
}
},
"node_modules/@ethersproject/wordlists": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.7.0.tgz",
"integrity": "sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA==",
"funding": [
{
"type": "individual",
"url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
},
{
"type": "individual",
"url": "https://www.buymeacoffee.com/ricmoo"
}
],
"dependencies": {
"@ethersproject/bytes": "^5.7.0",
"@ethersproject/hash": "^5.7.0",
"@ethersproject/logger": "^5.7.0",
"@ethersproject/properties": "^5.7.0",
"@ethersproject/strings": "^5.7.0"
}
},
"node_modules/@fastify/deepmerge": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/@fastify/deepmerge/-/deepmerge-1.3.0.tgz",
@@ -2247,6 +2024,28 @@
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
"node_modules/@noble/hashes": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.1.2.tgz",
"integrity": "sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA==",
"funding": [
{
"type": "individual",
"url": "https://paulmillr.com/funding/"
}
]
},
"node_modules/@noble/secp256k1": {
"version": "1.7.1",
"resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz",
"integrity": "sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==",
"funding": [
{
"type": "individual",
"url": "https://paulmillr.com/funding/"
}
]
},
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -3123,9 +2922,9 @@
}
},
"node_modules/aes-js": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz",
"integrity": "sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw=="
"version": "4.0.0-beta.5",
"resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz",
"integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q=="
},
"node_modules/ajv": {
"version": "6.12.6",
@@ -5190,13 +4989,13 @@
}
},
"node_modules/ethers": {
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz",
"integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==",
"version": "6.7.1",
"resolved": "https://registry.npmjs.org/ethers/-/ethers-6.7.1.tgz",
"integrity": "sha512-qX5kxIFMfg1i+epfgb0xF4WM7IqapIIu50pOJ17aebkxxa4BacW5jFrQRmCJpDEg2ZK2oNtR5QjrQ1WDBF29dA==",
"funding": [
{
"type": "individual",
"url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
"url": "https://github.com/sponsors/ethers-io/"
},
{
"type": "individual",
@@ -5204,36 +5003,46 @@
}
],
"dependencies": {
"@ethersproject/abi": "5.7.0",
"@ethersproject/abstract-provider": "5.7.0",
"@ethersproject/abstract-signer": "5.7.0",
"@ethersproject/address": "5.7.0",
"@ethersproject/base64": "5.7.0",
"@ethersproject/basex": "5.7.0",
"@ethersproject/bignumber": "5.7.0",
"@ethersproject/bytes": "5.7.0",
"@ethersproject/constants": "5.7.0",
"@ethersproject/contracts": "5.7.0",
"@ethersproject/hash": "5.7.0",
"@ethersproject/hdnode": "5.7.0",
"@ethersproject/json-wallets": "5.7.0",
"@ethersproject/keccak256": "5.7.0",
"@ethersproject/logger": "5.7.0",
"@ethersproject/networks": "5.7.1",
"@ethersproject/pbkdf2": "5.7.0",
"@ethersproject/properties": "5.7.0",
"@ethersproject/providers": "5.7.2",
"@ethersproject/random": "5.7.0",
"@ethersproject/rlp": "5.7.0",
"@ethersproject/sha2": "5.7.0",
"@ethersproject/signing-key": "5.7.0",
"@ethersproject/solidity": "5.7.0",
"@ethersproject/strings": "5.7.0",
"@ethersproject/transactions": "5.7.0",
"@ethersproject/units": "5.7.0",
"@ethersproject/wallet": "5.7.0",
"@ethersproject/web": "5.7.1",
"@ethersproject/wordlists": "5.7.0"
"@adraffy/ens-normalize": "1.9.2",
"@noble/hashes": "1.1.2",
"@noble/secp256k1": "1.7.1",
"@types/node": "18.15.13",
"aes-js": "4.0.0-beta.5",
"tslib": "2.4.0",
"ws": "8.5.0"
},
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/ethers/node_modules/@types/node": {
"version": "18.15.13",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz",
"integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q=="
},
"node_modules/ethers/node_modules/tslib": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
"integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="
},
"node_modules/ethers/node_modules/ws": {
"version": "8.5.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz",
"integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": "^5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
},
"node_modules/events": {
@@ -9924,11 +9733,6 @@
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
"dev": true
},
"node_modules/scrypt-js": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz",
"integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA=="
},
"node_modules/semver": {
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",

View File

@@ -1,6 +1,6 @@
{
"name": "@orionprotocol/sdk",
"version": "0.19.89-rc22",
"version": "0.20.1",
"description": "Orion Protocol SDK",
"main": "./lib/index.cjs",
"module": "./lib/index.js",
@@ -91,7 +91,7 @@
"bignumber.js": "^9.1.1",
"bson-objectid": "^2.0.4",
"buffer": "^6.0.3",
"ethers": "^5.6.2",
"ethers": "^6.7.1",
"express": "^4.18.2",
"isomorphic-ws": "^5.0.0",
"just-clone": "^6.2.0",

View File

@@ -1,7 +1,7 @@
import { BigNumber } from 'bignumber.js';
import { ethers } from 'ethers';
import clone from 'just-clone';
import { ERC20__factory } from '@orionprotocol/contracts/lib/ethers-v5/index.js';
import { ERC20__factory } from '@orionprotocol/contracts/lib/ethers-v6/index.js';
import { APPROVE_ERC20_GAS_LIMIT, NATIVE_CURRENCY_PRECISION } from './constants/index.js';
import type {
AggregatedBalanceRequirement, ApproveFix, Asset, BalanceIssue, BalanceRequirement, Source,
@@ -24,7 +24,7 @@ export default class BalanceGuard {
private readonly nativeCryptocurrency: Asset;
private readonly provider: ethers.providers.Provider;
private readonly provider: ethers.Provider;
private readonly signer: ethers.Signer;
@@ -33,7 +33,7 @@ export default class BalanceGuard {
constructor(
balances: Partial<Record<string, Record<'exchange' | 'wallet', BigNumber>>>,
nativeCryptocurrency: Asset,
provider: ethers.providers.Provider,
provider: ethers.Provider,
signer: ethers.Signer,
logger?: (message: string) => void,
) {
@@ -62,10 +62,10 @@ export default class BalanceGuard {
const walletAddress = await this.signer.getAddress();
const tokenContract = ERC20__factory
.connect(assetAddress, this.provider);
const unsignedTx = await tokenContract.populateTransaction
.approve(
const unsignedTx = await tokenContract.approve
.populateTransaction(
spenderAddress,
ethers.constants.MaxUint256,
ethers.MaxUint256,
);
unsignedTx.from = walletAddress;
let resetRequired = false;
@@ -117,21 +117,23 @@ export default class BalanceGuard {
const approve = async ({ spenderAddress, targetAmount }: ApproveFix) => {
const bnTargetAmount = new BigNumber(targetAmount);
const unsignedApproveTx = await tokenContract
.populateTransaction
.approve(
.approve.populateTransaction(
spenderAddress,
bnTargetAmount.isZero()
? '0' // Reset
: ethers.constants.MaxUint256, // Infinite approve
: ethers.MaxUint256, // Infinite approve
);
const walletAddress = await this.signer.getAddress();
const nonce = await this.provider.getTransactionCount(walletAddress, 'pending');
const gasPrice = await this.provider.getGasPrice();
const { gasPrice, maxFeePerGas } = await this.provider.getFeeData();
const network = await this.provider.getNetwork();
if (gasPrice !== null && maxFeePerGas !== null) {
unsignedApproveTx.gasPrice = gasPrice;
unsignedApproveTx.maxFeePerGas = maxFeePerGas;
}
unsignedApproveTx.chainId = network.chainId;
unsignedApproveTx.gasPrice = gasPrice;
unsignedApproveTx.nonce = nonce;
unsignedApproveTx.from = walletAddress;
const gasLimit = await this.provider.estimateGas(unsignedApproveTx);
@@ -139,7 +141,7 @@ export default class BalanceGuard {
this.logger?.('Approve transaction signing...');
const signedTx = await this.signer.signTransaction(unsignedApproveTx);
const txResponse = await this.provider.sendTransaction(signedTx);
const txResponse = await this.provider.broadcastTransaction(signedTx);
this.logger?.(`${issue.asset.name} approve transaction sent ${txResponse.hash}. Waiting for confirmation...`);
await txResponse.wait();
this.logger?.(`${issue.asset.name} approve transaction confirmed.`);
@@ -230,7 +232,7 @@ export default class BalanceGuard {
const lackAmount = remainingBalance.exchange.abs(); // e.g. -435.234234 to 434.234234
let denormalizedAllowance: BigNumber;
if (asset.address === ethers.constants.AddressZero) {
if (asset.address === ethers.ZeroAddress) {
denormalizedAllowance = remainingBalance.wallet;
} else {
if (spenderAddress === undefined) throw new Error(`Spender address is required for ${asset.name}`);
@@ -272,13 +274,11 @@ export default class BalanceGuard {
asset.address,
spenderAddress,
);
const gasPriceWei = await this.provider.getGasPrice();
const approveTransactionCost = ethers.BigNumber
.from(APPROVE_ERC20_GAS_LIMIT)
.mul(gasPriceWei);
const { gasPrice: gasPriceWei } = await this.provider.getFeeData();
const approveTransactionCost = BigInt(APPROVE_ERC20_GAS_LIMIT) * (gasPriceWei ?? 0n);
const denormalizedApproveTransactionCost = denormalizeNumber(
approveTransactionCost,
NATIVE_CURRENCY_PRECISION
BigInt(NATIVE_CURRENCY_PRECISION)
);
requiredApproves.items = {
@@ -329,7 +329,7 @@ export default class BalanceGuard {
.reduce<BigNumber>((p, c) => (c !== undefined ? p.plus(c) : p), new BigNumber(0));
let denormalizedAllowance: BigNumber;
if (asset.address === ethers.constants.AddressZero) {
if (asset.address === ethers.ZeroAddress) {
denormalizedAllowance = remainingBalance.wallet;
} else {
if (spenderAddress === undefined) throw new Error(`Spender address is required for ${asset.name}`);
@@ -365,13 +365,11 @@ export default class BalanceGuard {
asset.address,
spenderAddress,
);
const gasPriceWei = await this.provider.getGasPrice();
const approveTransactionCost = ethers.BigNumber
.from(APPROVE_ERC20_GAS_LIMIT)
.mul(gasPriceWei);
const { gasPrice: gasPriceWei } = await this.provider.getFeeData();
const approveTransactionCost = BigInt(APPROVE_ERC20_GAS_LIMIT) * (gasPriceWei ?? 0n);
const denormalizedApproveTransactionCost = denormalizeNumber(
approveTransactionCost,
NATIVE_CURRENCY_PRECISION
BigInt(NATIVE_CURRENCY_PRECISION)
);
requiredApproves.items = {

View File

@@ -5,10 +5,10 @@ import { isValidChainId } from '../../utils/index.js';
import { simpleFetch } from 'simple-typed-fetch';
import bsonObjectId from 'bson-objectid';
const ObjectID = bsonObjectId.default
const ObjectID = bsonObjectId;
const getHistory = async (units: Unit[], address: string, limit = 1000) => {
if (!ethers.utils.isAddress(address)) throw new Error(`Invalid address: ${address}`);
if (!ethers.isAddress(address)) throw new Error(`Invalid address: ${address}`);
const data = await Promise.all(units.map(async ({ blockchainService, aggregator, chainId }) => {
const sourceNetworkHistory = await simpleFetch(blockchainService.getSourceAtomicSwapHistory)({
limit,

View File

@@ -229,7 +229,7 @@ export default class Bridge {
env?: string | undefined,
) {
const secret = generateSecret();
const secretHash = ethers.utils.keccak256(secret);
const secretHash = ethers.keccak256(secret);
const lockExpiration = Date.now() + SECONDS_IN_DAY * EXPIRATION_DAYS * 1000;
return {

View File

@@ -1,6 +1,6 @@
import { BigNumber } from 'bignumber.js';
import { ethers } from 'ethers';
import { Exchange__factory } from '@orionprotocol/contracts/lib/ethers-v5/index.js';
import { Exchange__factory } from '@orionprotocol/contracts/lib/ethers-v6/index.js';
import getBalances from '../../utils/getBalances.js';
import BalanceGuard from '../../BalanceGuard.js';
import getAvailableSources from '../../utils/getAvailableFundsSources.js';
@@ -123,7 +123,7 @@ export default async function swap({
const sourceChainBalances = await getBalances(
{
[assetName]: sourceChainAssetAddress,
[sourceChainNativeCryptocurrency]: ethers.constants.AddressZero,
[sourceChainNativeCryptocurrency]: ethers.ZeroAddress,
},
sourceAggregator,
walletAddress,
@@ -134,7 +134,7 @@ export default async function swap({
const targetChainBalances = await getBalances(
{
[assetName]: targetChainAssetAddress,
[targetChainNativeCryptocurrency]: ethers.constants.AddressZero,
[targetChainNativeCryptocurrency]: ethers.ZeroAddress,
},
targetAggregator,
walletAddress,
@@ -146,7 +146,7 @@ export default async function swap({
sourceChainBalances,
{
name: sourceChainNativeCryptocurrency,
address: ethers.constants.AddressZero,
address: ethers.ZeroAddress,
},
sourceProvider,
signer,
@@ -157,7 +157,7 @@ export default async function swap({
targetChainBalances,
{
name: targetChainNativeCryptocurrency,
address: ethers.constants.AddressZero,
address: ethers.ZeroAddress,
},
targetProvider,
signer,
@@ -181,33 +181,33 @@ export default async function swap({
BigNumber.ROUND_FLOOR,
);
const secret = generateSecret();
const secretHash = ethers.utils.keccak256(secret);
const secretHash = ethers.keccak256(secret);
options?.logger?.(`Secret is ${secret}`);
options?.logger?.(`Secret hash is ${secretHash}`);
const secondsInDay = 60 * 60 * 24;
const expirationDays = 4;
const expirationEtherBN = ethers.BigNumber.from(
const expirationEtherBN = BigInt(
Date.now() + (secondsInDay * expirationDays * 1000),
);
const unsignedLockAtomicTx = await sourceExchangeContract.populateTransaction.lockAtomic({
const unsignedLockAtomicTx = await sourceExchangeContract.lockAtomic.populateTransaction({
amount: amountBlockchainParam,
asset: sourceChainAssetAddress,
expiration: expirationEtherBN,
secretHash,
sender: walletAddress,
targetChainId: ethers.BigNumber.from(targetChain),
targetChainId: BigInt(targetChain),
});
let sourceChainGasPrice: ethers.BigNumber;
let sourceChainGasPrice: bigint;
const sourceChainFeeData = await sourceChainUnit.provider.getFeeData();
if (ethers.BigNumber.isBigNumber(sourceChainFeeData.gasPrice)) { //
if (sourceChainFeeData.gasPrice !== null) { //
unsignedLockAtomicTx.gasPrice = sourceChainFeeData.gasPrice;
sourceChainGasPrice = sourceChainFeeData.gasPrice;
} else if (
ethers.BigNumber.isBigNumber(sourceChainFeeData.maxFeePerGas) &&
ethers.BigNumber.isBigNumber(sourceChainFeeData.maxPriorityFeePerGas)
sourceChainFeeData.maxFeePerGas !== null &&
sourceChainFeeData.maxPriorityFeePerGas !== null
) { // EIP-1559
unsignedLockAtomicTx.maxFeePerGas = sourceChainFeeData.maxFeePerGas;
unsignedLockAtomicTx.maxPriorityFeePerGas = sourceChainFeeData.maxPriorityFeePerGas;
@@ -216,7 +216,7 @@ export default async function swap({
throw new Error('Can\'t get gas price');
}
unsignedLockAtomicTx.chainId = parseInt(chainId, 10);
unsignedLockAtomicTx.chainId = BigInt(chainId);
unsignedLockAtomicTx.from = walletAddress;
let value = new BigNumber(0);
@@ -230,16 +230,16 @@ export default async function swap({
NATIVE_CURRENCY_PRECISION,
BigNumber.ROUND_CEIL,
);
unsignedLockAtomicTx.gasLimit = ethers.BigNumber.from(LOCKATOMIC_GAS_LIMIT);
unsignedLockAtomicTx.gasLimit = BigInt(LOCKATOMIC_GAS_LIMIT);
const transactionCost = ethers.BigNumber.from(LOCKATOMIC_GAS_LIMIT).mul(sourceChainGasPrice);
const denormalizedTransactionCost = denormalizeNumber(transactionCost, NATIVE_CURRENCY_PRECISION);
const transactionCost = BigInt(LOCKATOMIC_GAS_LIMIT) * sourceChainGasPrice;
const denormalizedTransactionCost = denormalizeNumber(transactionCost, BigInt(NATIVE_CURRENCY_PRECISION));
sourceChainBalanceGuard.registerRequirement({
reason: 'Network fee',
asset: {
name: sourceChainNativeCryptocurrency,
address: ethers.constants.AddressZero,
address: ethers.ZeroAddress,
},
amount: denormalizedTransactionCost.toString(),
sources: ['wallet']
@@ -252,7 +252,7 @@ export default async function swap({
options?.logger?.('Signing lock tx transaction...');
const signedTransaction = await signer.signTransaction(unsignedLockAtomicTx);
const lockAtomicTxResponse = await sourceChainUnit.provider.sendTransaction(signedTransaction);
const lockAtomicTxResponse = await sourceChainUnit.provider.broadcastTransaction(signedTransaction);
options?.logger?.(`Lock tx sent. Tx hash: ${lockAtomicTxResponse.hash}. Waiting for tx to be mined...`);
await lockAtomicTxResponse.wait();
options?.logger?.('Lock tx mined.');
@@ -280,7 +280,7 @@ export default async function swap({
options?.logger?.('Atomic swap placed.');
// const targetChainGasPriceWei = await simpleFetch(targetBlockchainService.getGasPriceWei)();
const unsignedRedeemAtomicTx = await targetExchangeContract.populateTransaction.redeemAtomic(
const unsignedRedeemAtomicTx = await targetExchangeContract.redeemAtomic.populateTransaction(
{
amount: amountBlockchainParam,
asset: targetChainAssetAddress,
@@ -294,14 +294,14 @@ export default async function swap({
secret
)
let targetChainGasPrice: ethers.BigNumber;
let targetChainGasPrice: bigint;
const targetChainFeeData = await targetChainUnit.provider.getFeeData();
if (ethers.BigNumber.isBigNumber(targetChainFeeData.gasPrice)) { //
if (targetChainFeeData.gasPrice !== null) { //
unsignedRedeemAtomicTx.gasPrice = targetChainFeeData.gasPrice;
targetChainGasPrice = targetChainFeeData.gasPrice;
} else if (
ethers.BigNumber.isBigNumber(targetChainFeeData.maxFeePerGas) &&
ethers.BigNumber.isBigNumber(targetChainFeeData.maxPriorityFeePerGas)
targetChainFeeData.maxFeePerGas !== null &&
targetChainFeeData.maxPriorityFeePerGas !== null
) { // EIP-1559
unsignedRedeemAtomicTx.maxFeePerGas = targetChainFeeData.maxFeePerGas;
unsignedRedeemAtomicTx.maxPriorityFeePerGas = targetChainFeeData.maxPriorityFeePerGas;
@@ -310,18 +310,18 @@ export default async function swap({
throw new Error('Can\'t get gas price');
}
unsignedRedeemAtomicTx.chainId = parseInt(targetChain, 10);
unsignedRedeemAtomicTx.chainId = BigInt(parseInt(targetChain, 10));
unsignedRedeemAtomicTx.from = walletAddress;
unsignedRedeemAtomicTx.gasLimit = ethers.BigNumber.from(REDEEMATOMIC_GAS_LIMIT);
unsignedRedeemAtomicTx.gasLimit = BigInt(REDEEMATOMIC_GAS_LIMIT);
const redeemAtomicTransactionCost = ethers.BigNumber.from(REDEEMATOMIC_GAS_LIMIT).mul(targetChainGasPrice);
const targetDenormalizedTransactionCost = denormalizeNumber(redeemAtomicTransactionCost, NATIVE_CURRENCY_PRECISION);
const redeemAtomicTransactionCost = BigInt(REDEEMATOMIC_GAS_LIMIT) * targetChainGasPrice;
const targetDenormalizedTransactionCost = denormalizeNumber(redeemAtomicTransactionCost, BigInt(NATIVE_CURRENCY_PRECISION));
targetChainBalanceGuard.registerRequirement({
reason: 'Network fee',
asset: {
name: targetChainNativeCryptocurrency,
address: ethers.constants.AddressZero,
address: ethers.ZeroAddress,
},
amount: targetDenormalizedTransactionCost.toString(),
sources: ['wallet']
@@ -334,7 +334,7 @@ export default async function swap({
options?.logger?.('Signing redeem tx transaction...');
const targetSignedTransaction = await signer.signTransaction(unsignedRedeemAtomicTx);
const targetLockAtomicTxResponse = await targetChainUnit.provider.sendTransaction(targetSignedTransaction);
const targetLockAtomicTxResponse = await targetChainUnit.provider.broadcastTransaction(targetSignedTransaction);
options?.logger?.(`Redeem tx sent. Tx hash: ${targetLockAtomicTxResponse.hash}. Waiting for tx to be mined...`);
await targetLockAtomicTxResponse.wait();
@@ -343,16 +343,16 @@ export default async function swap({
if (options?.withdrawToWallet !== undefined && options.withdrawToWallet) {
options.logger?.('Withdrawing to wallet...');
const unsignedWithdrawTx = await targetExchangeContract.populateTransaction.withdraw(
const unsignedWithdrawTx = await targetExchangeContract.withdraw.populateTransaction(
targetChainAssetAddress,
amountBlockchainParam,
);
if (ethers.BigNumber.isBigNumber(targetChainFeeData.gasPrice)) { //
if (targetChainFeeData.gasPrice !== null) { //
unsignedWithdrawTx.gasPrice = targetChainFeeData.gasPrice;
targetChainGasPrice = targetChainFeeData.gasPrice;
} else if (
ethers.BigNumber.isBigNumber(targetChainFeeData.maxFeePerGas) &&
ethers.BigNumber.isBigNumber(targetChainFeeData.maxPriorityFeePerGas)
targetChainFeeData.maxFeePerGas !== null &&
targetChainFeeData.maxPriorityFeePerGas !== null
) { // EIP-1559
unsignedWithdrawTx.maxFeePerGas = targetChainFeeData.maxFeePerGas;
unsignedWithdrawTx.maxPriorityFeePerGas = targetChainFeeData.maxPriorityFeePerGas;
@@ -360,12 +360,12 @@ export default async function swap({
} else {
throw new Error('Can\'t get gas price');
}
unsignedWithdrawTx.chainId = parseInt(targetChain, 10);
unsignedWithdrawTx.gasLimit = ethers.BigNumber.from(WITHDRAW_GAS_LIMIT);
unsignedWithdrawTx.chainId = BigInt(parseInt(targetChain, 10));
unsignedWithdrawTx.gasLimit = BigInt(WITHDRAW_GAS_LIMIT);
unsignedWithdrawTx.from = walletAddress;
unsignedWithdrawTx.nonce = await targetProvider.getTransactionCount(walletAddress, 'pending');
const signedTx = await signer.signTransaction(unsignedWithdrawTx);
const withdrawTx = await targetProvider.sendTransaction(signedTx);
const withdrawTx = await targetProvider.broadcastTransaction(signedTx);
options.logger?.(`Withdraw tx sent. Tx hash: ${withdrawTx.hash}. Waiting for tx to be mined...`);
await withdrawTx.wait();
options.logger?.('Withdraw tx mined.');

View File

@@ -1,6 +1,6 @@
import { BigNumber } from 'bignumber.js';
import { ethers } from 'ethers';
import { Exchange__factory } from '@orionprotocol/contracts/lib/ethers-v5/index.js';
import { Exchange__factory } from '@orionprotocol/contracts/lib/ethers-v6/index.js';
import getBalances from '../../utils/getBalances.js';
import BalanceGuard from '../../BalanceGuard.js';
import type Unit from '../index.js';
@@ -51,7 +51,7 @@ export default async function deposit({
const balances = await getBalances(
{
[asset]: assetAddress,
[nativeCryptocurrency]: ethers.constants.AddressZero,
[nativeCryptocurrency]: ethers.ZeroAddress,
},
aggregator,
walletAddress,
@@ -63,7 +63,7 @@ export default async function deposit({
balances,
{
name: nativeCryptocurrency,
address: ethers.constants.AddressZero,
address: ethers.ZeroAddress,
},
provider,
signer,
@@ -80,34 +80,34 @@ export default async function deposit({
sources: ['wallet'],
});
let unsignedTx: ethers.PopulatedTransaction;
let unsignedTx: ethers.TransactionLike;
if (asset === nativeCryptocurrency) {
unsignedTx = await exchangeContract.populateTransaction.deposit();
unsignedTx = await exchangeContract.deposit.populateTransaction();
unsignedTx.value = normalizeNumber(amount, NATIVE_CURRENCY_PRECISION, BigNumber.ROUND_CEIL);
unsignedTx.gasLimit = ethers.BigNumber.from(DEPOSIT_ETH_GAS_LIMIT);
unsignedTx.gasLimit = BigInt(DEPOSIT_ETH_GAS_LIMIT);
} else {
unsignedTx = await exchangeContract.populateTransaction.depositAsset(
unsignedTx = await exchangeContract.depositAsset.populateTransaction(
assetAddress,
normalizeNumber(amount, INTERNAL_PROTOCOL_PRECISION, BigNumber.ROUND_CEIL),
);
unsignedTx.gasLimit = ethers.BigNumber.from(DEPOSIT_ERC20_GAS_LIMIT);
unsignedTx.gasLimit = BigInt(DEPOSIT_ERC20_GAS_LIMIT);
}
const transactionCost = ethers.BigNumber.from(unsignedTx.gasLimit).mul(gasPriceWei);
const denormalizedTransactionCost = denormalizeNumber(transactionCost, NATIVE_CURRENCY_PRECISION);
const transactionCost = BigInt(unsignedTx.gasLimit) * BigInt(gasPriceWei);
const denormalizedTransactionCost = denormalizeNumber(transactionCost, BigInt(NATIVE_CURRENCY_PRECISION));
balanceGuard.registerRequirement({
reason: 'Network fee',
asset: {
name: nativeCryptocurrency,
address: ethers.constants.AddressZero,
address: ethers.ZeroAddress,
},
amount: denormalizedTransactionCost.toString(),
sources: ['wallet'],
});
unsignedTx.chainId = parseInt(chainId, 10);
unsignedTx.gasPrice = ethers.BigNumber.from(gasPriceWei);
unsignedTx.gasPrice = BigInt(gasPriceWei);
unsignedTx.from = walletAddress;
await balanceGuard.check(true);
@@ -117,10 +117,10 @@ export default async function deposit({
const signedTx = await signer.signTransaction(unsignedTx);
try {
const txResponse = await provider.sendTransaction(signedTx);
const txResponse = await provider.broadcastTransaction(signedTx);
console.log(`Deposit tx sent: ${txResponse.hash}. Waiting for confirmation...`);
const txReceipt = await txResponse.wait();
if (txReceipt.status !== undefined) {
if (txReceipt?.status !== undefined) {
console.log('Deposit tx confirmed');
} else {
console.log('Deposit tx failed');

View File

@@ -1,11 +1,13 @@
import type { ExchangeWithGenericSwap } from '@orionprotocol/contracts/lib/ethers-v5/Exchange.js';
import { UniswapV3Pool__factory, ERC20__factory, SwapExecutor__factory, CurveRegistry__factory } from '@orionprotocol/contracts/lib/ethers-v5/index.js';
import { BigNumber, ethers, type BigNumberish } from 'ethers';
import { concat, defaultAbiCoder, type BytesLike } from 'ethers/lib/utils.js';
import type { ExchangeWithGenericSwap } from '@orionprotocol/contracts/lib/ethers-v6/Exchange.js';
import {
UniswapV3Pool__factory, ERC20__factory,
SwapExecutor__factory, CurveRegistry__factory
} from '@orionprotocol/contracts/lib/ethers-v6/index.js';
import { ethers, type BigNumberish, type AddressLike, concat, type BytesLike } from 'ethers';
import { safeGet, SafeArray } from '../../utils/safeGetters.js';
import type Unit from '../index.js';
import { simpleFetch } from 'simple-typed-fetch';
import type { PromiseOrValue } from '@orionprotocol/contracts/lib/ethers-v5/common.js';
import { BigNumber } from 'bignumber.js';
const EXECUTOR_SWAP_FUNCTION = 'func_70LYiww'
@@ -46,8 +48,8 @@ export default async function generateSwapCalldata({
const curveRegistryAddress = safeGet(unit.contracts, 'curveRegistry')
const { assetToAddress, swapExecutorContractAddress, exchangeContractAddress } = await simpleFetch(unit.blockchainService.getInfo)();
let path = SafeArray.from(path_).map((swapInfo) => {
swapInfo.assetIn = safeGet(assetToAddress, swapInfo.assetIn);
swapInfo.assetOut = safeGet(assetToAddress, swapInfo.assetOut);
swapInfo.assetIn = assetToAddress[swapInfo.assetIn] ?? swapInfo.assetIn.toLowerCase();
swapInfo.assetOut = assetToAddress[swapInfo.assetOut] ?? swapInfo.assetOut.toLowerCase();
return swapInfo;
})
const factory = path.first().factory
@@ -64,20 +66,24 @@ export default async function generateSwapCalldata({
flags: 0
}
const exchangeToNativeDecimals = async (token: PromiseOrValue<string>) => {
token = await token
let decimals = 18
if (token !== ethers.constants.AddressZero) {
const exchangeToNativeDecimals = async (token: AddressLike) => {
if (typeof token !== 'string' && 'getAddress' in token) {
token = await token.getAddress();
} else {
token = await token
}
let decimals = 18n
if (token !== ethers.ZeroAddress) {
const contract = ERC20__factory.connect(token, unit.provider)
decimals = await contract.decimals()
}
return BigNumber.from(amount).mul(BigNumber.from(10).pow(decimals)).div(BigNumber.from(10).pow(8))
return BigNumber(amount.toString()).multipliedBy(BigNumber(10).pow(decimals.toString())).div(BigNumber(10).pow(8))
}
const amountNativeDecimals = await exchangeToNativeDecimals(swapDescription.srcToken);
path = SafeArray.from(path_).map((swapInfo) => {
if (swapInfo.assetIn == ethers.constants.AddressZero) swapInfo.assetIn = wethAddress
if (swapInfo.assetOut == ethers.constants.AddressZero) swapInfo.assetOut = wethAddress
if (swapInfo.assetIn == ethers.ZeroAddress) swapInfo.assetIn = wethAddress
if (swapInfo.assetOut == ethers.ZeroAddress) swapInfo.assetOut = wethAddress
return swapInfo;
});
@@ -94,16 +100,16 @@ export default async function generateSwapCalldata({
break;
}
case 'UniswapV3': {
calldata = await generateUni3Calls(amountNativeDecimals, exchangeContractAddress, path, unit.provider)
calldata = await generateUni3Calls(amountNativeDecimals.toString(), exchangeContractAddress, path, unit.provider)
break;
}
case 'OrionV3': {
calldata = await generateOrion3Calls(amountNativeDecimals, exchangeContractAddress, path, unit.provider)
calldata = await generateOrion3Calls(amountNativeDecimals.toString(), exchangeContractAddress, path, unit.provider)
break;
}
case 'Curve': {
calldata = await generateCurveStableSwapCalls(
amountNativeDecimals,
amountNativeDecimals.toString(),
exchangeContractAddress,
swapExecutorContractAddress ?? '',
path,
@@ -134,7 +140,7 @@ export async function generateUni2Calls(
currentSwap.pool,
currentSwap.assetIn,
currentSwap.assetOut,
defaultAbiCoder.encode(['uint256'], [concat(['0x03', nextSwap.pool])]),
ethers.AbiCoder.defaultAbiCoder().encode(['uint256'], [concat(['0x03', nextSwap.pool])]),
]
)
calls.push(addCallParams(calldata))
@@ -145,7 +151,7 @@ export async function generateUni2Calls(
lastSwap.pool,
lastSwap.assetIn,
lastSwap.assetOut,
defaultAbiCoder.encode(['uint256'], [concat(['0x03', exchangeAddress])]),
ethers.AbiCoder.defaultAbiCoder().encode(['uint256'], [concat(['0x03', exchangeAddress])]),
])
calls.push(addCallParams(calldata))
@@ -156,22 +162,22 @@ async function generateUni3Calls(
amount: BigNumberish,
exchangeContractAddress: string,
path: SafeArray<SwapInfo>,
provider: ethers.providers.JsonRpcProvider
provider: ethers.JsonRpcApiProvider
) {
const encodedPools: BytesLike[] = []
const encodedPools: string[] = []
for (const swap of path) {
const pool = UniswapV3Pool__factory.connect(swap.pool, provider)
const token0 = await pool.token0()
const zeroForOne = token0.toLowerCase() === swap.assetIn.toLowerCase()
const unwrapWETH = swap.assetOut === ethers.constants.AddressZero
const unwrapWETH = swap.assetOut === ethers.ZeroAddress
let encodedPool = ethers.utils.solidityPack(['uint256'], [pool.address])
encodedPool = ethers.utils.hexDataSlice(encodedPool, 1)
let encodedPool = ethers.solidityPacked(['uint256'], [await pool.getAddress()])
encodedPool = ethers.dataSlice(encodedPool, 1)
let firstByte = 0
if (unwrapWETH) firstByte += 32
if (!zeroForOne) firstByte += 128
const encodedFirstByte = ethers.utils.solidityPack(['uint8'], [firstByte])
encodedPool = ethers.utils.hexlify(ethers.utils.concat([encodedFirstByte, encodedPool]))
const encodedFirstByte = ethers.solidityPacked(['uint8'], [firstByte])
encodedPool = ethers.hexlify(ethers.concat([encodedFirstByte, encodedPool]))
encodedPools.push(encodedPool)
}
const executorInterface = SwapExecutor__factory.createInterface()
@@ -185,22 +191,22 @@ async function generateOrion3Calls(
amount: BigNumberish,
exchangeContractAddress: string,
path: SafeArray<SwapInfo>,
provider: ethers.providers.JsonRpcProvider
provider: ethers.JsonRpcApiProvider
) {
const encodedPools: BytesLike[] = []
const encodedPools: string[] = []
for (const swap of path) {
const pool = UniswapV3Pool__factory.connect(swap.pool, provider)
const token0 = await pool.token0()
const zeroForOne = token0.toLowerCase() === swap.assetIn.toLowerCase()
const unwrapWETH = swap.assetOut === ethers.constants.AddressZero
const unwrapWETH = swap.assetOut === ethers.ZeroAddress
let encodedPool = ethers.utils.solidityPack(['uint256'], [pool.address])
encodedPool = ethers.utils.hexDataSlice(encodedPool, 1)
let encodedPool = ethers.solidityPacked(['uint256'], [await pool.getAddress()])
encodedPool = ethers.dataSlice(encodedPool, 1)
let firstByte = 0
if (unwrapWETH) firstByte += 32
if (!zeroForOne) firstByte += 128
const encodedFirstByte = ethers.utils.solidityPack(['uint8'], [firstByte])
encodedPool = ethers.utils.hexlify(ethers.utils.concat([encodedFirstByte, encodedPool]))
const encodedFirstByte = ethers.solidityPacked(['uint8'], [firstByte])
encodedPool = ethers.hexlify(ethers.concat([encodedFirstByte, encodedPool]))
encodedPools.push(encodedPool)
}
const executorInterface = SwapExecutor__factory.createInterface()
@@ -215,7 +221,7 @@ async function generateCurveStableSwapCalls(
exchangeContractAddress: string,
executorAddress: string,
path: SafeArray<SwapInfo>,
provider: ethers.providers.JsonRpcProvider,
provider: ethers.JsonRpcProvider,
curveRegistry: string
) {
if (path.length > 1) {
@@ -231,12 +237,12 @@ async function generateCurveStableSwapCalls(
const executorAllowance = await firstToken.allowance(executorAddress, swap.pool)
const calls: BytesLike[] = []
if (executorAllowance.lt(amount)) {
if (executorAllowance < BigInt(amount)) {
const calldata = addCallParams(
executorInterface.encodeFunctionData('safeApprove', [
swap.assetIn,
swap.pool,
ethers.constants.MaxUint256
ethers.MaxUint256
])
)
calls.push(calldata)
@@ -265,28 +271,28 @@ function addCallParams(
if (callParams) {
if (callParams.value !== undefined) {
firstByte += 16 // 00010000
const encodedValue = ethers.utils.solidityPack(['uint128'], [callParams.value])
calldata = ethers.utils.hexlify(ethers.utils.concat([encodedValue, calldata]))
const encodedValue = ethers.solidityPacked(['uint128'], [callParams.value])
calldata = ethers.hexlify(ethers.concat([encodedValue, calldata]))
}
if (callParams.target !== undefined) {
firstByte += 32 // 00100000
const encodedAddress = ethers.utils.solidityPack(['address'], [callParams.target])
calldata = ethers.utils.hexlify(ethers.utils.concat([encodedAddress, calldata]))
const encodedAddress = ethers.solidityPacked(['address'], [callParams.target])
calldata = ethers.hexlify(ethers.concat([encodedAddress, calldata]))
}
if (callParams.gaslimit !== undefined) {
firstByte += 64 // 01000000
const encodedGaslimit = ethers.utils.solidityPack(['uint32'], [callParams.gaslimit])
calldata = ethers.utils.hexlify(ethers.utils.concat([encodedGaslimit, calldata]))
const encodedGaslimit = ethers.solidityPacked(['uint32'], [callParams.gaslimit])
calldata = ethers.hexlify(ethers.concat([encodedGaslimit, calldata]))
}
if (callParams.isMandatory !== undefined) firstByte += 128 // 10000000
}
const encodedFirstByte = ethers.utils.solidityPack(['uint8'], [firstByte])
calldata = ethers.utils.hexlify(ethers.utils.concat([encodedFirstByte, calldata]))
const encodedFirstByte = ethers.solidityPacked(['uint8'], [firstByte])
calldata = ethers.hexlify(ethers.concat([encodedFirstByte, calldata]))
return calldata
}
async function generateCalls(calls: BytesLike[]) {
function generateCalls(calls: BytesLike[]) {
const executorInterface = SwapExecutor__factory.createInterface()
return '0x' + executorInterface.encodeFunctionData(EXECUTOR_SWAP_FUNCTION, [ethers.constants.AddressZero, calls]).slice(74)
return '0x' + executorInterface.encodeFunctionData(EXECUTOR_SWAP_FUNCTION, [ethers.ZeroAddress, calls]).slice(74)
}

View File

@@ -51,7 +51,7 @@ export default async function getSwapInfo({
const allPrices = await simpleFetch(blockchainService.getPricesWithQuoteAsset)();
const gasPriceWei = await simpleFetch(blockchainService.getGasPriceWei)();
const gasPriceGwei = ethers.utils.formatUnits(gasPriceWei, 'gwei').toString();
const gasPriceGwei = ethers.formatUnits(gasPriceWei, 'gwei').toString();
const assetInAddress = assetToAddress[assetIn];
if (assetInAddress === undefined) throw new Error(`Asset '${assetIn}' not found`);
@@ -101,15 +101,15 @@ export default async function getSwapInfo({
}
if (route === 'pool') {
const transactionCost = ethers.BigNumber.from(SWAP_THROUGH_ORION_POOL_GAS_LIMIT).mul(gasPriceWei);
const denormalizedTransactionCost = denormalizeNumber(transactionCost, NATIVE_CURRENCY_PRECISION);
const transactionCost = BigInt(SWAP_THROUGH_ORION_POOL_GAS_LIMIT) * BigInt(gasPriceWei);
const denormalizedTransactionCost = denormalizeNumber(transactionCost, BigInt(NATIVE_CURRENCY_PRECISION));
return {
route,
swapInfo,
fee: {
assetName: nativeCryptocurrencyName,
assetAddress: ethers.constants.AddressZero,
assetAddress: ethers.ZeroAddress,
networkFeeInFeeAsset: denormalizedTransactionCost.toString(),
protocolFeeInFeeAsset: undefined,
},
@@ -134,7 +134,7 @@ export default async function getSwapInfo({
gasPriceGwei,
feePercent,
baseAssetAddress,
ethers.constants.AddressZero,
ethers.ZeroAddress,
feeAssetAddress,
allPrices.prices
);

View File

@@ -1,6 +1,6 @@
import { BigNumber } from 'bignumber.js';
import { ethers } from 'ethers';
import { Exchange__factory } from '@orionprotocol/contracts/lib/ethers-v5/index.js';
import { Exchange__factory } from '@orionprotocol/contracts/lib/ethers-v6/index.js';
import getBalances from '../../utils/getBalances.js';
import BalanceGuard from '../../BalanceGuard.js';
import getAvailableSources from '../../utils/getAvailableFundsSources.js';
@@ -44,7 +44,7 @@ type PoolSwap = {
amountOut: number
through: 'pool'
txHash: string
wait: (confirmations?: number | undefined) => Promise<ethers.providers.TransactionReceipt>
wait: (confirmations?: number | undefined) => Promise<ethers.TransactionReceipt | null>
}
export type Swap = AggregatorOrder | PoolSwap;
@@ -95,7 +95,7 @@ export default async function swapLimit({
const { factories } = await simpleFetch(blockchainService.getPoolsConfig)();
const poolExchangesList = factories !== undefined ? Object.keys(factories) : [];
const gasPriceGwei = ethers.utils.formatUnits(gasPriceWei, 'gwei').toString();
const gasPriceGwei = ethers.formatUnits(gasPriceWei, 'gwei').toString();
const assetInAddress = assetToAddress[assetIn];
if (assetInAddress === undefined) throw new Error(`Asset '${assetIn}' not found`);
@@ -108,7 +108,7 @@ export default async function swapLimit({
{
[assetIn]: assetInAddress,
[feeAsset]: feeAssetAddress,
[nativeCryptocurrency]: ethers.constants.AddressZero,
[nativeCryptocurrency]: ethers.ZeroAddress,
},
aggregator,
walletAddress,
@@ -120,7 +120,7 @@ export default async function swapLimit({
balances,
{
name: nativeCryptocurrency,
address: ethers.constants.AddressZero,
address: ethers.ZeroAddress,
},
provider,
signer,
@@ -271,7 +271,7 @@ export default async function swapLimit({
BigNumber.ROUND_FLOOR,
);
const unsignedSwapThroughOrionPoolTx = await exchangeContract.populateTransaction.swapThroughOrionPool(
const unsignedSwapThroughOrionPoolTx = await exchangeContract.swapThroughOrionPool.populateTransaction(
amountSpendBlockchainParam,
amountReceiveBlockchainParam,
factoryAddress !== undefined
@@ -280,8 +280,8 @@ export default async function swapLimit({
type === 'exactSpend',
);
unsignedSwapThroughOrionPoolTx.chainId = parseInt(chainId, 10);
unsignedSwapThroughOrionPoolTx.gasPrice = ethers.BigNumber.from(gasPriceWei);
unsignedSwapThroughOrionPoolTx.chainId = BigInt(parseInt(chainId, 10));
unsignedSwapThroughOrionPoolTx.gasPrice = BigInt(gasPriceWei);
unsignedSwapThroughOrionPoolTx.from = walletAddress;
const amountSpendBN = new BigNumber(amountSpend);
@@ -297,19 +297,19 @@ export default async function swapLimit({
NATIVE_CURRENCY_PRECISION,
BigNumber.ROUND_CEIL,
);
unsignedSwapThroughOrionPoolTx.gasLimit = ethers.BigNumber.from(SWAP_THROUGH_ORION_POOL_GAS_LIMIT);
unsignedSwapThroughOrionPoolTx.gasLimit = BigInt(SWAP_THROUGH_ORION_POOL_GAS_LIMIT);
const transactionCost = ethers.BigNumber.from(SWAP_THROUGH_ORION_POOL_GAS_LIMIT).mul(gasPriceWei);
const denormalizedTransactionCost = denormalizeNumber(transactionCost, NATIVE_CURRENCY_PRECISION);
const transactionCost = BigInt(SWAP_THROUGH_ORION_POOL_GAS_LIMIT) * BigInt(gasPriceWei);
const denormalizedTransactionCost = denormalizeNumber(transactionCost, BigInt(NATIVE_CURRENCY_PRECISION));
balanceGuard.registerRequirement({
reason: 'Network fee',
asset: {
name: nativeCryptocurrency,
address: ethers.constants.AddressZero,
address: ethers.ZeroAddress,
},
amount: denormalizedTransactionCost.toString(),
sources: getAvailableSources('network_fee', ethers.constants.AddressZero, 'pool'),
sources: getAvailableSources('network_fee', ethers.ZeroAddress, 'pool'),
});
// if (value.gt(0)) {
@@ -317,10 +317,10 @@ export default async function swapLimit({
// reason: 'Transaction value (extra amount)',
// asset: {
// name: nativeCryptocurrency,
// address: ethers.constants.AddressZero,
// address: ethers.ZeroAddress,
// },
// amount: value.toString(),
// sources: getAvailableSources('amount', ethers.constants.AddressZero, 'pool'),
// sources: getAvailableSources('amount', ethers.ZeroAddress, 'pool'),
// });
// }
@@ -380,7 +380,7 @@ export default async function swapLimit({
gasPriceGwei,
feePercent,
baseAssetAddress,
ethers.constants.AddressZero,
ethers.ZeroAddress,
feeAssetAddress,
allPrices.prices,
);

View File

@@ -1,6 +1,6 @@
import { BigNumber } from 'bignumber.js';
import { ethers } from 'ethers';
import { Exchange__factory } from '@orionprotocol/contracts/lib/ethers-v5/index.js';
import { Exchange__factory } from '@orionprotocol/contracts/lib/ethers-v6/index.js';
import getBalances from '../../utils/getBalances.js';
import BalanceGuard from '../../BalanceGuard.js';
import getAvailableSources from '../../utils/getAvailableFundsSources.js';
@@ -28,7 +28,7 @@ type PoolSwap = {
amountOut: number
through: 'pool'
txHash: string
wait: (confirmations?: number | undefined) => Promise<ethers.providers.TransactionReceipt>
wait: (confirmations?: number | undefined) => Promise<ethers.TransactionReceipt | null>
}
export type Swap = AggregatorOrder | PoolSwap;
@@ -80,7 +80,7 @@ export default async function swapMarket({
const { factories } = await simpleFetch(blockchainService.getPoolsConfig)();
const poolExchangesList = factories !== undefined ? Object.keys(factories) : [];
const gasPriceGwei = ethers.utils.formatUnits(gasPriceWei, 'gwei').toString();
const gasPriceGwei = ethers.formatUnits(gasPriceWei, 'gwei').toString();
const assetInAddress = assetToAddress[assetIn];
if (assetInAddress === undefined) throw new Error(`Asset '${assetIn}' not found`);
@@ -93,7 +93,7 @@ export default async function swapMarket({
{
[assetIn]: assetInAddress,
[feeAsset]: feeAssetAddress,
[nativeCryptocurrency]: ethers.constants.AddressZero,
[nativeCryptocurrency]: ethers.ZeroAddress,
},
aggregator,
walletAddress,
@@ -105,7 +105,7 @@ export default async function swapMarket({
balances,
{
name: nativeCryptocurrency,
address: ethers.constants.AddressZero,
address: ethers.ZeroAddress,
},
provider,
signer,
@@ -221,17 +221,17 @@ export default async function swapMarket({
INTERNAL_PROTOCOL_PRECISION,
BigNumber.ROUND_FLOOR,
);
const unsignedSwapThroughOrionPoolTx = await exchangeContract.populateTransaction.swapThroughOrionPool(
amountSpendBlockchainParam,
amountReceiveBlockchainParam,
const unsignedSwapThroughOrionPoolTx = await exchangeContract.swapThroughOrionPool.populateTransaction(
amountSpendBlockchainParam.toString(),
amountReceiveBlockchainParam.toString(),
factoryAddress !== undefined
? [factoryAddress, ...pathAddresses]
: pathAddresses,
type === 'exactSpend',
);
unsignedSwapThroughOrionPoolTx.chainId = parseInt(chainId, 10);
unsignedSwapThroughOrionPoolTx.gasPrice = ethers.BigNumber.from(gasPriceWei);
unsignedSwapThroughOrionPoolTx.chainId = BigInt(chainId);
unsignedSwapThroughOrionPoolTx.gasPrice = BigInt(gasPriceWei);
unsignedSwapThroughOrionPoolTx.from = walletAddress;
const amountSpendBN = new BigNumber(amountSpend);
@@ -247,19 +247,19 @@ export default async function swapMarket({
NATIVE_CURRENCY_PRECISION,
BigNumber.ROUND_CEIL,
);
unsignedSwapThroughOrionPoolTx.gasLimit = ethers.BigNumber.from(SWAP_THROUGH_ORION_POOL_GAS_LIMIT);
unsignedSwapThroughOrionPoolTx.gasLimit = BigInt(SWAP_THROUGH_ORION_POOL_GAS_LIMIT);
const transactionCost = ethers.BigNumber.from(SWAP_THROUGH_ORION_POOL_GAS_LIMIT).mul(gasPriceWei);
const denormalizedTransactionCost = denormalizeNumber(transactionCost, NATIVE_CURRENCY_PRECISION);
const transactionCost = BigInt(SWAP_THROUGH_ORION_POOL_GAS_LIMIT) * BigInt(gasPriceWei);
const denormalizedTransactionCost = denormalizeNumber(transactionCost, BigInt(NATIVE_CURRENCY_PRECISION));
balanceGuard.registerRequirement({
reason: 'Network fee',
asset: {
name: nativeCryptocurrency,
address: ethers.constants.AddressZero,
address: ethers.ZeroAddress,
},
amount: denormalizedTransactionCost.toString(),
sources: getAvailableSources('network_fee', ethers.constants.AddressZero, 'pool'),
sources: getAvailableSources('network_fee', ethers.ZeroAddress, 'pool'),
});
// if (value.gt(0)) {
@@ -267,10 +267,10 @@ export default async function swapMarket({
// reason: 'Transaction value (extra amount)',
// asset: {
// name: nativeCryptocurrency,
// address: ethers.constants.AddressZero,
// address: ethers.ZeroAddress,
// },
// amount: value.toString(),
// sources: getAvailableSources('amount', ethers.constants.AddressZero, 'pool'),
// sources: getAvailableSources('amount', ethers.ZeroAddress, 'pool'),
// });
// }
@@ -338,7 +338,7 @@ export default async function swapMarket({
gasPriceGwei,
feePercent,
baseAssetAddress,
ethers.constants.AddressZero,
ethers.ZeroAddress,
feeAssetAddress,
allPrices.prices,
);

View File

@@ -1,6 +1,6 @@
import { BigNumber } from 'bignumber.js';
import { ethers } from 'ethers';
import { Exchange__factory } from '@orionprotocol/contracts/lib/ethers-v5/index.js';
import { Exchange__factory } from '@orionprotocol/contracts/lib/ethers-v6/index.js';
import getBalances from '../../utils/getBalances.js';
import BalanceGuard from '../../BalanceGuard.js';
import type Unit from '../index.js';
@@ -50,7 +50,7 @@ export default async function withdraw({
const balances = await getBalances(
{
[asset]: assetAddress,
[nativeCryptocurrency]: ethers.constants.AddressZero,
[nativeCryptocurrency]: ethers.ZeroAddress,
},
aggregator,
walletAddress,
@@ -62,7 +62,7 @@ export default async function withdraw({
balances,
{
name: nativeCryptocurrency,
address: ethers.constants.AddressZero,
address: ethers.ZeroAddress,
},
provider,
signer,
@@ -78,27 +78,27 @@ export default async function withdraw({
sources: ['exchange'],
});
const unsignedTx = await exchangeContract.populateTransaction.withdraw(
const unsignedTx = await exchangeContract.withdraw.populateTransaction(
assetAddress,
normalizeNumber(amount, INTERNAL_PROTOCOL_PRECISION, BigNumber.ROUND_FLOOR),
normalizeNumber(amount, INTERNAL_PROTOCOL_PRECISION, BigNumber.ROUND_FLOOR).toString(),
);
unsignedTx.gasLimit = ethers.BigNumber.from(WITHDRAW_GAS_LIMIT);
unsignedTx.gasLimit = BigInt(WITHDRAW_GAS_LIMIT);
const transactionCost = ethers.BigNumber.from(unsignedTx.gasLimit).mul(gasPriceWei);
const denormalizedTransactionCost = denormalizeNumber(transactionCost, NATIVE_CURRENCY_PRECISION);
const transactionCost = BigInt(unsignedTx.gasLimit) * BigInt(gasPriceWei);
const denormalizedTransactionCost = denormalizeNumber(transactionCost, BigInt(NATIVE_CURRENCY_PRECISION));
balanceGuard.registerRequirement({
reason: 'Network fee',
asset: {
name: nativeCryptocurrency,
address: ethers.constants.AddressZero,
address: ethers.ZeroAddress,
},
amount: denormalizedTransactionCost.toString(),
sources: ['wallet'],
});
unsignedTx.chainId = parseInt(chainId, 10);
unsignedTx.gasPrice = ethers.BigNumber.from(gasPriceWei);
unsignedTx.chainId = BigInt(chainId);
unsignedTx.gasPrice = BigInt(gasPriceWei);
unsignedTx.from = walletAddress;
await balanceGuard.check(true);
@@ -107,11 +107,11 @@ export default async function withdraw({
unsignedTx.nonce = nonce;
const signedTx = await signer.signTransaction(unsignedTx);
const txResponse = await provider.sendTransaction(signedTx);
const txResponse = await provider.broadcastTransaction(signedTx);
console.log(`Withdraw tx sent: ${txResponse.hash}. Waiting for confirmation...`);
try {
const txReceipt = await txResponse.wait();
if (txReceipt.status !== undefined) {
if (txReceipt?.status !== undefined) {
console.log('Withdraw tx confirmed');
} else {
console.log('Withdraw tx failed');

View File

@@ -1,4 +1,4 @@
import { Exchange__factory, IUniswapV2Pair__factory, IUniswapV2Router__factory } from '@orionprotocol/contracts/lib/ethers-v5/index.js';
import { Exchange__factory, IUniswapV2Pair__factory, IUniswapV2Router__factory } from '@orionprotocol/contracts/lib/ethers-v6/index.js';
import { BigNumber } from 'bignumber.js';
import { ethers } from 'ethers';
import { simpleFetch } from 'simple-typed-fetch';
@@ -71,7 +71,7 @@ export default class FarmingManager {
{
[assetA]: assetAAddress,
[assetB]: assetBAddress,
[nativeCryptocurrency]: ethers.constants.AddressZero,
[nativeCryptocurrency]: ethers.ZeroAddress,
},
this.unit.aggregator,
walletAddress,
@@ -81,7 +81,7 @@ export default class FarmingManager {
const balanceGuard = new BalanceGuard(
balances,
{
address: ethers.constants.AddressZero,
address: ethers.ZeroAddress,
name: nativeCryptocurrency,
},
this.unit.provider,
@@ -109,13 +109,13 @@ export default class FarmingManager {
const assetAReserve = pairTokensIsInversed ? _reserve1 : _reserve0;
const assetBReserve = pairTokensIsInversed ? _reserve0 : _reserve1;
const denormalizedAssetAReserve = denormalizeNumber(assetAReserve, assetADecimals);
const denormalizedAssetBReserve = denormalizeNumber(assetBReserve, assetBDecimals);
const denormalizedAssetAReserve = denormalizeNumber(assetAReserve, BigInt(assetADecimals));
const denormalizedAssetBReserve = denormalizeNumber(assetBReserve, BigInt(assetBDecimals));
const price = denormalizedAssetBReserve.div(denormalizedAssetAReserve);
const assetAIsNativeCurrency = assetAAddress === ethers.constants.AddressZero;
const assetBIsNativeCurrency = assetBAddress === ethers.constants.AddressZero;
const assetAIsNativeCurrency = assetAAddress === ethers.ZeroAddress;
const assetBIsNativeCurrency = assetBAddress === ethers.ZeroAddress;
const assetAAmount = assetA === amountAsset ? amountBN : amountBN.div(price);
const assetBAmount = assetA === amountAsset ? amountBN.multipliedBy(price) : amountBN;
@@ -145,33 +145,33 @@ export default class FarmingManager {
sources: ['exchange', 'wallet'],
});
const unsignedTx = await exchangeContract.populateTransaction.withdrawToPool(
const unsignedTx = await exchangeContract.withdrawToPool.populateTransaction(
assetBIsNativeCurrency ? assetBAddress : assetAAddress,
assetBIsNativeCurrency ? assetAAddress : assetBAddress,
assetBIsNativeCurrency
? normalizeNumber(assetBAmount, INTERNAL_PROTOCOL_PRECISION, BigNumber.ROUND_FLOOR)
: normalizeNumber(assetAAmount, INTERNAL_PROTOCOL_PRECISION, BigNumber.ROUND_FLOOR),
? normalizeNumber(assetBAmount, INTERNAL_PROTOCOL_PRECISION, BigNumber.ROUND_FLOOR).toString()
: normalizeNumber(assetAAmount, INTERNAL_PROTOCOL_PRECISION, BigNumber.ROUND_FLOOR).toString(),
assetBIsNativeCurrency
? normalizeNumber(assetAAmount, INTERNAL_PROTOCOL_PRECISION, BigNumber.ROUND_FLOOR)
: normalizeNumber(assetBAmount, INTERNAL_PROTOCOL_PRECISION, BigNumber.ROUND_FLOOR),
? normalizeNumber(assetAAmount, INTERNAL_PROTOCOL_PRECISION, BigNumber.ROUND_FLOOR).toString()
: normalizeNumber(assetBAmount, INTERNAL_PROTOCOL_PRECISION, BigNumber.ROUND_FLOOR).toString(),
assetBIsNativeCurrency
? normalizeNumber(assetBAmountWithSlippage, INTERNAL_PROTOCOL_PRECISION, BigNumber.ROUND_FLOOR)
: normalizeNumber(assetAAmountWithSlippage, INTERNAL_PROTOCOL_PRECISION, BigNumber.ROUND_FLOOR),
? normalizeNumber(assetBAmountWithSlippage, INTERNAL_PROTOCOL_PRECISION, BigNumber.ROUND_FLOOR).toString()
: normalizeNumber(assetAAmountWithSlippage, INTERNAL_PROTOCOL_PRECISION, BigNumber.ROUND_FLOOR).toString(),
assetBIsNativeCurrency
? normalizeNumber(assetAAmountWithSlippage, INTERNAL_PROTOCOL_PRECISION, BigNumber.ROUND_FLOOR)
: normalizeNumber(assetBAmountWithSlippage, INTERNAL_PROTOCOL_PRECISION, BigNumber.ROUND_FLOOR),
? normalizeNumber(assetAAmountWithSlippage, INTERNAL_PROTOCOL_PRECISION, BigNumber.ROUND_FLOOR).toString()
: normalizeNumber(assetBAmountWithSlippage, INTERNAL_PROTOCOL_PRECISION, BigNumber.ROUND_FLOOR).toString(),
);
const gasPrice = await this.unit.provider.getGasPrice();
const { gasPrice, maxFeePerGas } = await this.unit.provider.getFeeData();
const transactionCost = ethers.BigNumber.from(ADD_LIQUIDITY_GAS_LIMIT).mul(gasPrice);
const denormalizedTransactionCost = denormalizeNumber(transactionCost, NATIVE_CURRENCY_PRECISION);
const transactionCost = BigInt(ADD_LIQUIDITY_GAS_LIMIT) * (gasPrice ?? 0n);
const denormalizedTransactionCost = denormalizeNumber(transactionCost, BigInt(NATIVE_CURRENCY_PRECISION));
balanceGuard.registerRequirement({
reason: 'Network fee',
asset: {
name: nativeCryptocurrency,
address: ethers.constants.AddressZero,
address: ethers.ZeroAddress,
},
amount: denormalizedTransactionCost.toString(),
sources: ['wallet'],
@@ -195,8 +195,11 @@ export default class FarmingManager {
}
}
if (gasPrice !== null && maxFeePerGas !== null) {
unsignedTx.gasPrice = gasPrice;
unsignedTx.maxFeePerGas = maxFeePerGas;
}
unsignedTx.chainId = network.chainId;
unsignedTx.gasPrice = gasPrice;
unsignedTx.nonce = nonce;
unsignedTx.from = walletAddress;
const gasLimit = await this.unit.provider.estimateGas(unsignedTx);
@@ -205,13 +208,13 @@ export default class FarmingManager {
await balanceGuard.check(true);
const signedTx = await signer.signTransaction(unsignedTx);
const txResponse = await this.unit.provider.sendTransaction(signedTx);
const txResponse = await this.unit.provider.broadcastTransaction(signedTx);
console.log(`Add liquidity tx sent: ${txResponse.hash}. Waiting for confirmation...`);
const txReceipt = await txResponse.wait();
if (txReceipt.status === 1) {
console.log(`Add liquidity tx confirmed: ${txReceipt.transactionHash}`);
if (txReceipt?.status === 1) {
console.log(`Add liquidity tx confirmed: ${txReceipt.hash}`);
} else {
console.log(`Add liquidity tx failed: ${txReceipt.transactionHash}`);
console.log(`Add liquidity tx failed: ${txReceipt?.hash}`);
}
}
@@ -254,7 +257,7 @@ export default class FarmingManager {
[assetA]: assetAAddress,
[assetB]: assetBAddress,
[`${poolName} LP Token`]: pool.lpTokenAddress,
[nativeCryptocurrency]: ethers.constants.AddressZero,
[nativeCryptocurrency]: ethers.ZeroAddress,
},
this.unit.aggregator,
walletAddress,
@@ -265,7 +268,7 @@ export default class FarmingManager {
const balanceGuard = new BalanceGuard(
balances,
{
address: ethers.constants.AddressZero,
address: ethers.ZeroAddress,
name: nativeCryptocurrency,
},
this.unit.provider,
@@ -298,8 +301,8 @@ export default class FarmingManager {
const assetAReserve = pairTokensIsInversed ? _reserve1 : _reserve0;
const assetBReserve = pairTokensIsInversed ? _reserve0 : _reserve1;
const denormalizedAssetAReserve = denormalizeNumber(assetAReserve, assetADecimals);
const denormalizedAssetBReserve = denormalizeNumber(assetBReserve, assetBDecimals);
const denormalizedAssetAReserve = denormalizeNumber(assetAReserve, BigInt(assetADecimals));
const denormalizedAssetBReserve = denormalizeNumber(assetBReserve, BigInt(assetBDecimals));
const denormalizedUserPooledAssetA = denormalizedAssetAReserve.multipliedBy(userShare);
const denormalizedUserPooledAssetB = denormalizedAssetBReserve.multipliedBy(userShare);
@@ -307,8 +310,8 @@ export default class FarmingManager {
const denormalizedUserPooledAssetAWithSlippage = denormalizedUserPooledAssetA.multipliedBy(1 - ADD_LIQUIDITY_SLIPPAGE);
const denormalizedUserPooledAssetBWithSlippage = denormalizedUserPooledAssetB.multipliedBy(1 - ADD_LIQUIDITY_SLIPPAGE);
const assetAIsNativeCurrency = assetAAddress === ethers.constants.AddressZero;
const assetBIsNativeCurrency = assetBAddress === ethers.constants.AddressZero;
const assetAIsNativeCurrency = assetAAddress === ethers.ZeroAddress;
const assetBIsNativeCurrency = assetBAddress === ethers.ZeroAddress;
balanceGuard.registerRequirement({
reason: `${poolName} liquidity`,
@@ -321,9 +324,9 @@ export default class FarmingManager {
sources: ['wallet'],
});
let unsignedTx: ethers.PopulatedTransaction;
let unsignedTx: ethers.TransactionLike;
if (assetAIsNativeCurrency || assetBIsNativeCurrency) {
unsignedTx = await routerContract.populateTransaction.removeLiquidityETH(
unsignedTx = await routerContract.removeLiquidityETH.populateTransaction(
assetBIsNativeCurrency ? assetAAddress : assetBAddress, // token
lpTokenUserBalance,
assetBIsNativeCurrency
@@ -331,28 +334,28 @@ export default class FarmingManager {
denormalizedUserPooledAssetAWithSlippage,
assetADecimals,
BigNumber.ROUND_FLOOR,
)
).toString()
: normalizeNumber(
denormalizedUserPooledAssetBWithSlippage,
assetBDecimals,
BigNumber.ROUND_FLOOR,
), // token min
).toString(), // token min
assetBIsNativeCurrency
? normalizeNumber(
denormalizedUserPooledAssetBWithSlippage,
assetBDecimals,
BigNumber.ROUND_FLOOR,
)
).toString()
: normalizeNumber(
denormalizedUserPooledAssetAWithSlippage,
assetADecimals,
BigNumber.ROUND_FLOOR,
), // eth min
).toString(), // eth min
walletAddress,
Math.floor(Date.now() / 1000) + 60 * 20,
);
} else {
unsignedTx = await routerContract.populateTransaction.removeLiquidity(
unsignedTx = await routerContract.removeLiquidity.populateTransaction(
assetAAddress,
assetBAddress,
lpTokenUserBalance,
@@ -360,27 +363,27 @@ export default class FarmingManager {
denormalizedUserPooledAssetAWithSlippage,
assetADecimals,
BigNumber.ROUND_FLOOR,
),
).toString(),
normalizeNumber(
denormalizedUserPooledAssetBWithSlippage,
assetBDecimals,
BigNumber.ROUND_FLOOR,
),
).toString(),
walletAddress,
Math.floor(Date.now() / 1000) + 60 * 20,
);
}
const gasPrice = await this.unit.provider.getGasPrice();
const { gasPrice } = await this.unit.provider.getFeeData()
const transactionCost = ethers.BigNumber.from(ADD_LIQUIDITY_GAS_LIMIT).mul(gasPrice);
const denormalizedTransactionCost = denormalizeNumber(transactionCost, NATIVE_CURRENCY_PRECISION);
const transactionCost = BigInt(ADD_LIQUIDITY_GAS_LIMIT) * (gasPrice ?? 0n);
const denormalizedTransactionCost = denormalizeNumber(transactionCost, BigInt(NATIVE_CURRENCY_PRECISION));
balanceGuard.registerRequirement({
reason: 'Network fee',
asset: {
name: nativeCryptocurrency,
address: ethers.constants.AddressZero,
address: ethers.ZeroAddress,
},
amount: denormalizedTransactionCost.toString(),
sources: ['wallet'],
@@ -398,13 +401,13 @@ export default class FarmingManager {
unsignedTx.gasLimit = gasLimit;
const signedTx = await signer.signTransaction(unsignedTx);
const txResponse = await this.unit.provider.sendTransaction(signedTx);
const txResponse = await this.unit.provider.broadcastTransaction(signedTx);
console.log(`Remove all liquidity tx sent: ${txResponse.hash}. Waiting for confirmation...`);
const txReceipt = await txResponse.wait();
if (txReceipt.status === 1) {
console.log(`Remove all liquidity tx confirmed: ${txReceipt.transactionHash}`);
if (txReceipt?.status === 1) {
console.log(`Remove all liquidity tx confirmed: ${txReceipt.hash}`);
} else {
console.log(`Remove all liquidity tx failed: ${txReceipt.transactionHash}`);
console.log(`Remove all liquidity tx failed: ${txReceipt?.hash}`);
}
}
}

View File

@@ -1,8 +1,12 @@
import { ethers } from 'ethers';
import { JsonRpcProvider } from 'ethers';
import { Aggregator } from '../services/Aggregator/index.js';
import { BlockchainService } from '../services/BlockchainService/index.js';
import { PriceFeed } from '../services/PriceFeed/index.js';
import type { KnownEnv, SupportedChainId, VerboseUnitConfig } from '../types.js';
import type {
KnownEnv,
SupportedChainId,
VerboseUnitConfig,
} from '../types.js';
import Exchange from './Exchange/index.js';
import FarmingManager from './FarmingManager/index.js';
import { chains, envs } from '../config/index.js';
@@ -12,14 +16,14 @@ import { IntegratorService } from '../services/Integrator/index.js';
type KnownConfig = {
env: KnownEnv
chainId: SupportedChainId
}
};
export default class Unit {
public readonly networkCode: typeof networkCodes[number];
public readonly networkCode: (typeof networkCodes)[number];
public readonly chainId: SupportedChainId;
public readonly provider: ethers.providers.StaticJsonRpcProvider;
public readonly provider: JsonRpcProvider;
public readonly blockchainService: BlockchainService;
@@ -40,13 +44,33 @@ export default class Unit {
constructor(config: KnownConfig | VerboseUnitConfig) {
if ('env' in config) {
const staticConfig = envs[config.env];
if (!staticConfig) throw new Error(`Invalid environment: ${config.env}. Available environments: ${Object.keys(envs).join(', ')}`);
if (!staticConfig) {
throw new Error(
`Invalid environment: ${
config.env
}. Available environments: ${Object.keys(envs).join(', ')}`
);
}
const chainConfig = chains[config.chainId];
if (!chainConfig) throw new Error(`Invalid chainId: ${config.chainId}. Available chainIds: ${Object.keys(chains).join(', ')}`);
if (!chainConfig) {
throw new Error(
`Invalid chainId: ${
config.chainId
}. Available chainIds: ${Object.keys(chains).join(', ')}`
);
}
const networkConfig = staticConfig.networks[config.chainId];
if (!networkConfig) throw new Error(`Invalid chainId: ${config.chainId}. Available chainIds: ${Object.keys(staticConfig.networks).join(', ')}`);
if (!networkConfig) {
throw new Error(
`Invalid chainId: ${
config.chainId
}. Available chainIds: ${Object.keys(staticConfig.networks).join(
', '
)}`
);
}
this.config = {
chainId: config.chainId,
nodeJsonRpc: networkConfig.rpc ?? chainConfig.rpc,
@@ -63,31 +87,41 @@ export default class Unit {
},
integrator: {
api: networkConfig.api + networkConfig.services.integrator.http,
}
},
},
}
};
} else {
this.config = config;
}
const chainInfo = chains[config.chainId];
if (!chainInfo) throw new Error('Chain info is required');
this.chainId = config.chainId;
this.networkCode = chainInfo.code;
this.contracts = chainInfo.contracts
this.contracts = chainInfo.contracts;
const intNetwork = parseInt(this.chainId, 10);
if (Number.isNaN(intNetwork)) throw new Error('Invalid chainId (not a number)' + this.chainId);
this.provider = new ethers.providers.StaticJsonRpcProvider(this.config.nodeJsonRpc, intNetwork);
if (Number.isNaN(intNetwork)) {
throw new Error('Invalid chainId (not a number)' + this.chainId);
}
this.provider = new JsonRpcProvider(this.config.nodeJsonRpc, intNetwork);
this.provider.pollingInterval = 1000;
this.blockchainService = new BlockchainService(this.config.services.blockchainService.http, this.config.basicAuth);
this.integrator = new IntegratorService(this.config.services.integrator.api, intNetwork);
this.blockchainService = new BlockchainService(
this.config.services.blockchainService.http,
this.config.basicAuth
);
this.integrator = new IntegratorService(
this.config.services.integrator.api,
intNetwork
);
this.aggregator = new Aggregator(
this.config.services.aggregator.http,
this.config.services.aggregator.ws,
this.config.basicAuth,
this.config.basicAuth
);
this.priceFeed = new PriceFeed(
this.config.services.priceFeed.api,
this.config.basicAuth
);
this.priceFeed = new PriceFeed(this.config.services.priceFeed.api, this.config.basicAuth);
this.exchange = new Exchange(this);
this.farmingManager = new FarmingManager(this);
}

View File

@@ -198,7 +198,7 @@ describe('Orion', () => {
expect(unit.aggregator.ws.api).toBe(`ws://localhost:${server1.port}/v1`);
expect(unit.blockchainService.api).toBe(blockchainServiceAPI);
expect(unit.priceFeed.api).toBe(orionPriceFeedAPI + '/price-feed');
expect(unit.provider.connection.url).toBe('https://cloudflare-eth.com/');
expect(unit.provider._getConnection().url).toBe('https://cloudflare-eth.com/');
const info = await simpleFetch(unit.blockchainService.getInfo)();
expect(info).toBeDefined();
@@ -249,7 +249,7 @@ describe('Orion', () => {
});
const bscUnit = orion.units[SupportedChainId.BSC_TESTNET]
expect(bscUnit?.provider.connection.url).toBe('https://data-seed-prebsc-1-s1.binance.org:8545/');
expect(bscUnit?.provider._getConnection().url).toBe('https://data-seed-prebsc-1-s1.binance.org:8545/');
expect(orion.referralSystem.api).toBe('https://zxczxc.orionprotocol.io');
});
@@ -315,7 +315,7 @@ describe('Orion', () => {
const network = await unitBSC.provider.getNetwork();
expect(network.chainId).toBe(97);
const zeroAddressWithout0x = ethers.constants.AddressZero.slice(2);
const zeroAddressWithout0x = ethers.ZeroAddress.slice(2);
expect(simpleFetch(orion.referralSystem.getMiniStats)(zeroAddressWithout0x))
.rejects
.toThrow('empty reward history');

View File

@@ -83,7 +83,7 @@ describe('Fee calculation', () => {
const gasPriceGwei = 3;
const feePercent = 0.2;
const baseAssetAddress = '0xcb2951e90d8dcf16e1fa84ac0c83f48906d6a744';
const baseCurrencyAddress = ethers.constants.AddressZero;
const baseCurrencyAddress = ethers.ZeroAddress;
const feeAssetAddress = '0xf223eca06261145b3287a0fefd8cfad371c7eb34';
const { totalFeeInFeeAsset: ornTotalFee } = calculateFeeInFeeAsset(
amount,

View File

@@ -1,7 +1,7 @@
import { ethers } from 'ethers';
import { z } from 'zod';
const addressSchema = z.string().refine(ethers.utils.isAddress, (value) => ({
const addressSchema = z.string().refine(ethers.isAddress, (value) => ({
message: `Should be an address, got ${value}`,
}));

View File

@@ -1,7 +1,7 @@
import { ethers } from 'ethers';
import type { Order } from '../types.js';
const hashOrder = (order: Order) => ethers.utils.solidityKeccak256(
const hashOrder = (order: Order) => ethers.solidityPackedKeccak256(
[
'uint8',
'address',

View File

@@ -1,6 +1,5 @@
import type { TypedDataSigner } from '@ethersproject/abstract-signer';
import type { ethers } from 'ethers';
import { joinSignature, splitSignature } from 'ethers/lib/utils.js';
import { ethers } from 'ethers';
import CANCEL_ORDER_TYPES from '../constants/cancelOrderTypes.js';
import type { CancelOrderRequest, SignedCancelOrderRequest, SupportedChainId } from '../types.js';
import getDomainData from './getDomainData.js';
@@ -26,7 +25,7 @@ const signCancelOrder = async (
const signature = usePersonalSign
? await signCancelOrderPersonal(cancelOrderRequest, signer)
// https://docs.ethers.io/v5/api/signer/#Signer-signTypedData
: await typedDataSigner._signTypedData(
: await typedDataSigner.signTypedData(
getDomainData(chainId),
CANCEL_ORDER_TYPES,
cancelOrderRequest,
@@ -34,7 +33,7 @@ const signCancelOrder = async (
// https://github.com/poap-xyz/poap-fun/pull/62#issue-928290265
// "Signature's v was always send as 27 or 28, but from Ledger was 0 or 1"
const fixedSignature = joinSignature(splitSignature(signature));
const fixedSignature = ethers.Signature.from(signature).serialized;
// if (!fixedSignature) throw new Error("Can't sign order cancel");

View File

@@ -1,5 +1,4 @@
import { ethers } from 'ethers';
import { arrayify, joinSignature, splitSignature } from 'ethers/lib/utils.js';
import type { CancelOrderRequest } from '../types.js';
const signCancelOrderPersonal = async (
@@ -7,14 +6,14 @@ const signCancelOrderPersonal = async (
signer: ethers.Signer,
) => {
const types = ['string', 'string', 'address'];
const message = ethers.utils.solidityKeccak256(
const message = ethers.solidityPackedKeccak256(
types,
['cancelOrder', cancelOrderRequest.id, cancelOrderRequest.senderAddress],
);
const signature = await signer.signMessage(arrayify(message));
const signature = await signer.signMessage(ethers.getBytes(message));
// NOTE: metamask broke sig.v value and we fix it in next line
return joinSignature(splitSignature(signature));
return ethers.Signature.from(signature).serialized;
};
export default signCancelOrderPersonal;

View File

@@ -1,7 +1,6 @@
import type { TypedDataSigner } from '@ethersproject/abstract-signer';
import { BigNumber } from 'bignumber.js';
import type { ethers } from 'ethers';
import { joinSignature, splitSignature } from 'ethers/lib/utils.js';
import { ethers } from 'ethers';
import { INTERNAL_PROTOCOL_PRECISION } from '../constants/index.js';
import ORDER_TYPES from '../constants/orderTypes.js';
import type { Order, SignedOrder, SupportedChainId } from '../types.js';
@@ -37,21 +36,21 @@ export const signOrder = async (
baseAsset: baseAssetAddr,
quoteAsset: quoteAssetAddr,
matcherFeeAsset: serviceFeeAssetAddr,
amount: normalizeNumber(
amount: Number(normalizeNumber(
amount,
INTERNAL_PROTOCOL_PRECISION,
BigNumber.ROUND_FLOOR,
).toNumber(),
price: normalizeNumber(
)),
price: Number(normalizeNumber(
price,
INTERNAL_PROTOCOL_PRECISION,
BigNumber.ROUND_FLOOR,
).toNumber(),
matcherFee: normalizeNumber(
)),
matcherFee: Number(normalizeNumber(
matcherFee,
INTERNAL_PROTOCOL_PRECISION,
BigNumber.ROUND_CEIL, // ROUND_CEIL because we don't want get "not enough fee" error
).toNumber(),
)),
nonce,
expiration,
buySide: side === 'BUY' ? 1 : 0,
@@ -63,7 +62,7 @@ export const signOrder = async (
const signature = usePersonalSign
? await signOrderPersonal(order, signer)
: await typedDataSigner._signTypedData(
: await typedDataSigner.signTypedData(
getDomainData(chainId),
ORDER_TYPES,
order,
@@ -71,7 +70,7 @@ export const signOrder = async (
// https://github.com/poap-xyz/poap-fun/pull/62#issue-928290265
// "Signature's v was always send as 27 or 28, but from Ledger was 0 or 1"
const fixedSignature = joinSignature(splitSignature(signature));
const fixedSignature = ethers.Signature.from(signature).serialized;
// if (!fixedSignature) throw new Error("Can't sign order");

View File

@@ -1,10 +1,8 @@
import { ethers } from 'ethers';
import type { Order } from '../types.js';
const { arrayify, joinSignature, splitSignature } = ethers.utils;
const signOrderPersonal = async (order: Order, signer: ethers.Signer) => {
const message = ethers.utils.solidityKeccak256(
const message = ethers.solidityPackedKeccak256(
[
'string', 'address', 'address', 'address', 'address',
'address', 'uint64', 'uint64', 'uint64', 'uint64', 'uint64', 'uint8',
@@ -24,10 +22,10 @@ const signOrderPersonal = async (order: Order, signer: ethers.Signer) => {
order.buySide,
],
);
const signature = await signer.signMessage(arrayify(message));
const signature = await signer.signMessage(ethers.getBytes(message));
// NOTE: metamask broke sig.v value and we fix it in next line
return joinSignature(splitSignature(signature));
return ethers.Signature.from(signature).serialized;
};
export default signOrderPersonal;

View File

@@ -74,13 +74,13 @@ class Aggregator {
}
getOrder = (orderId: string, owner?: string) => {
if (!ethers.utils.isHexString(orderId)) {
if (!ethers.isHexString(orderId)) {
throw new Error(`Invalid order id: ${orderId}. Must be a hex string`);
}
const url = new URL(`${this.apiUrl}/api/v1/order`);
url.searchParams.append('orderId', orderId);
if (owner !== undefined) {
if (!ethers.utils.isAddress(owner)) {
if (!ethers.isAddress(owner)) {
throw new Error(`Invalid owner address: ${owner}`);
}
url.searchParams.append('owner', owner);

View File

@@ -3,22 +3,22 @@ import { z } from 'zod';
import { exchanges, orderStatuses, subOrderStatuses } from '../../../constants/index.js';
const blockchainOrderSchema = z.object({
id: z.string().refine(ethers.utils.isHexString, (value) => ({
id: z.string().refine(ethers.isHexString, (value) => ({
message: `blockchainOrder.id must be a hex string, got ${value}`,
})),
senderAddress: z.string().refine(ethers.utils.isAddress, (value) => ({
senderAddress: z.string().refine(ethers.isAddress, (value) => ({
message: `blockchainOrder.senderAddress must be an address, got ${value}`,
})),
matcherAddress: z.string().refine(ethers.utils.isAddress, (value) => ({
matcherAddress: z.string().refine(ethers.isAddress, (value) => ({
message: `blockchainOrder.matcherAddress must be an address, got ${value}`,
})),
baseAsset: z.string().refine(ethers.utils.isAddress, (value) => ({
baseAsset: z.string().refine(ethers.isAddress, (value) => ({
message: `blockchainOrder.baseAsset must be an address, got ${value}`,
})),
quoteAsset: z.string().refine(ethers.utils.isAddress, (value) => ({
quoteAsset: z.string().refine(ethers.isAddress, (value) => ({
message: `blockchainOrder.quoteAsset must be an address, got ${value}`,
})),
matcherFeeAsset: z.string().refine(ethers.utils.isAddress, (value) => ({
matcherFeeAsset: z.string().refine(ethers.isAddress, (value) => ({
message: `blockchainOrder.matcherFeeAsset must be an address, got ${value}`,
})),
amount: z.number().int().nonnegative(),
@@ -27,7 +27,7 @@ const blockchainOrderSchema = z.object({
nonce: z.number(),
expiration: z.number(),
buySide: z.union([z.literal(1), z.literal(0)]),
signature: z.string().refine(ethers.utils.isHexString, (value) => ({
signature: z.string().refine(ethers.isHexString, (value) => ({
message: `blockchainOrder.signature must be a hex string, got ${value}`,
})).nullable(),
isPersonalSign: z.boolean(),
@@ -53,7 +53,7 @@ const baseOrderSchema = z.object({
amount: z.number().nonnegative(),
remainingAmount: z.number().nonnegative(),
price: z.number().nonnegative(),
sender: z.string().refine(ethers.utils.isAddress, (value) => ({
sender: z.string().refine(ethers.isAddress, (value) => ({
message: `order.sender must be an address, got ${value}`,
})),
filledAmount: z.number().nonnegative(),
@@ -77,13 +77,13 @@ const brokerAddressSchema = z.enum([
'SELF_BROKER'
])
.or(selfBrokerSchema)
.or(z.string().refine(ethers.utils.isAddress, (value) => ({
.or(z.string().refine(ethers.isAddress, (value) => ({
message: `subOrder.subOrders.[n].brokerAddress must be an address, got ${value}`,
})));
const subOrderSchema = baseOrderSchema.extend({
price: z.number(),
id: z.number(),
parentOrderId: z.string().refine(ethers.utils.isHexString, (value) => ({
parentOrderId: z.string().refine(ethers.isHexString, (value) => ({
message: `subOrder.parentOrderId must be a hex string, got ${value}`,
})),
exchange: z.string(),
@@ -98,11 +98,11 @@ const subOrderSchema = baseOrderSchema.extend({
});
const orderSchema = z.object({
orderId: z.string().refine(ethers.utils.isHexString, (value) => ({
orderId: z.string().refine(ethers.isHexString, (value) => ({
message: `orderId must be a hex string, got ${value}`,
})),
order: baseOrderSchema.extend({
id: z.string().refine(ethers.utils.isHexString, (value) => ({
id: z.string().refine(ethers.isHexString, (value) => ({
message: `order.id must be a hex string, got ${value}`,
})),
fee: z.number().nonnegative(),

View File

@@ -16,9 +16,9 @@ const baseAtomicHistoryItem = z.object({
_id: z.string(),
__v: z.number(),
asset: z.string(),
sender: z.string().refine(ethers.utils.isAddress),
secretHash: z.string().refine(ethers.utils.isHexString),
receiver: z.string().refine(ethers.utils.isAddress).optional(),
sender: z.string().refine(ethers.isAddress),
secretHash: z.string().refine(ethers.isHexString),
receiver: z.string().refine(ethers.isAddress).optional(),
secret: z.string().optional(),
});

View File

@@ -1,10 +1,10 @@
import { z } from 'zod';
import { SupportedChainId } from '../../../types.js';
import { isAddress } from 'ethers/lib/utils.js';
import { ethers } from 'ethers';
const contractsAddressesSchema = z.record(
z.nativeEnum(SupportedChainId),
z.string().refine(isAddress)
z.string().refine(ethers.isAddress)
);
export default contractsAddressesSchema;

View File

@@ -6,6 +6,7 @@ const ratingSchema = z.object({
weekly_boost_budget_fmt: z.number(),
monthly_boost_budget: z.string(),
monthly_boost_budget_fmt: z.number(),
displayed_boost_budget_fmt: z.number(),
time_left_for_the_reward: z.number(),
time_left_for_the_reward_local: z.string(),
time_left_for_the_reward_utc: z.string(),

View File

@@ -8,6 +8,6 @@ export default function calculateNetworkFee(
) {
const networkFeeGwei = new BigNumber(gasPriceGwei).multipliedBy(gasLimit);
const bn = new BigNumber(ethers.utils.parseUnits(networkFeeGwei.toString(), 'gwei').toString());
const bn = new BigNumber(ethers.parseUnits(networkFeeGwei.toString(), 'gwei').toString());
return bn.div(new BigNumber(10).pow(NATIVE_CURRENCY_PRECISION)).toString();
}

View File

@@ -1,8 +1,8 @@
import { ERC20__factory } from '@orionprotocol/contracts/lib/ethers-v5/index.js';
import { ERC20__factory } from '@orionprotocol/contracts/lib/ethers-v6/index.js';
import { ethers } from 'ethers';
import invariant from 'tiny-invariant';
const checkIsToken = async (address: string, provider?: ethers.providers.Provider) => {
const checkIsToken = async (address: string, provider?: ethers.Provider) => {
invariant(provider, 'No provider for token checking');
const tokenContract = ERC20__factory.connect(address, provider);
try {
@@ -12,7 +12,7 @@ const checkIsToken = async (address: string, provider?: ethers.providers.Provide
tokenContract.symbol(),
tokenContract.decimals(),
tokenContract.totalSupply(),
tokenContract.balanceOf(ethers.constants.AddressZero),
tokenContract.balanceOf(ethers.ZeroAddress),
],
);

View File

@@ -1,5 +1,4 @@
import { BigNumber } from 'bignumber.js';
import type { ethers } from 'ethers';
/**
* Converts normalized blockchain ("machine-readable") number to denormalized ("human-readable") number.
@@ -7,8 +6,8 @@ import type { ethers } from 'ethers';
* @param decimals Blockchain asset precision
* @returns BigNumber
*/
export default function denormalizeNumber(input: ethers.BigNumber, decimals: BigNumber.Value) {
const decimalsBN = new BigNumber(decimals);
export default function denormalizeNumber(input: bigint, decimals: bigint) {
const decimalsBN = new BigNumber(decimals.toString());
if (!decimalsBN.isInteger()) throw new Error(`Decimals '${decimalsBN.toString()}' is not an integer`);
return new BigNumber(input.toString()).div(new BigNumber(10).pow(decimalsBN));
}

View File

@@ -45,7 +45,7 @@ function isomorphicCryptoRandomBytes(size: number): Uint8Array {
const generateSecret = () => {
const RANDOM_BITS = 256;
const rand = isomorphicCryptoRandomBytes(RANDOM_BITS);
const secret = ethers.utils.keccak256(rand);
const secret = ethers.keccak256(rand);
return secret;
};

View File

@@ -8,7 +8,7 @@ export default function getAvailableFundsSources(
): Source[] {
switch (route) {
case 'aggregator':
if (assetAddress === ethers.constants.AddressZero) return ['exchange']; // We can't take native crypto from wallet
if (assetAddress === ethers.ZeroAddress) return ['exchange']; // We can't take native crypto from wallet
return ['exchange', 'wallet']; // We can take any token amount from exchange + wallet. Order is important!
case 'pool':
if (expenseType === 'network_fee') return ['wallet']; // Network fee is always taken from wallet

View File

@@ -1,5 +1,4 @@
import type { Exchange } from '@orionprotocol/contracts/lib/ethers-v5/index.js';
import { ERC20__factory } from '@orionprotocol/contracts/lib/ethers-v5/index.js';
import { ERC20__factory, type Exchange } from '@orionprotocol/contracts/lib/ethers-v6/index.js';
import type { BigNumber } from 'bignumber.js';
import { ethers } from 'ethers';
import { INTERNAL_PROTOCOL_PRECISION, NATIVE_CURRENCY_PRECISION } from '../constants/index.js';
@@ -12,11 +11,11 @@ export default async function getBalance(
assetAddress: string,
walletAddress: string,
exchangeContract: Exchange,
provider: ethers.providers.Provider,
provider: ethers.Provider,
) {
const assetIsNativeCryptocurrency = assetAddress === ethers.constants.AddressZero;
const assetIsNativeCryptocurrency = assetAddress === ethers.ZeroAddress;
let assetWalletBalance: ethers.BigNumber | undefined;
let assetWalletBalance: bigint | undefined;
let denormalizedAssetInWalletBalance: BigNumber | undefined;
@@ -28,10 +27,10 @@ export default async function getBalance(
denormalizedAssetInWalletBalance = denormalizeNumber(assetWalletBalance, assetDecimals);
} else {
assetWalletBalance = await provider.getBalance(walletAddress);
denormalizedAssetInWalletBalance = denormalizeNumber(assetWalletBalance, NATIVE_CURRENCY_PRECISION);
denormalizedAssetInWalletBalance = denormalizeNumber(assetWalletBalance, BigInt(NATIVE_CURRENCY_PRECISION));
}
const assetContractBalance = await exchangeContract.getBalance(assetAddress, walletAddress);
const denormalizedAssetInContractBalance = denormalizeNumber(assetContractBalance, INTERNAL_PROTOCOL_PRECISION);
const denormalizedAssetInContractBalance = denormalizeNumber(assetContractBalance, BigInt(INTERNAL_PROTOCOL_PRECISION));
const denormalizedAssetLockedBalanceResult = await aggregator.getLockedBalance(walletAddress, assetName);
if (denormalizedAssetLockedBalanceResult.isErr()) {
throw new Error(denormalizedAssetLockedBalanceResult.error.message);

View File

@@ -1,4 +1,4 @@
import type { Exchange } from '@orionprotocol/contracts/lib/ethers-v5/index.js';
import type { Exchange } from '@orionprotocol/contracts/lib/ethers-v6/index.js';
import type { BigNumber } from 'bignumber.js';
import type { ethers } from 'ethers';
import type { Aggregator } from '../services/Aggregator/index.js';
@@ -9,7 +9,7 @@ export default async (
aggregator: Aggregator,
walletAddress: string,
exchangeContract: Exchange,
provider: ethers.providers.Provider,
provider: ethers.Provider,
) => {
const balances = await Promise.all(
Object.entries(balancesRequired)

View File

@@ -11,7 +11,7 @@ const getNativeCryptocurrencyName = (assetToAddress: Partial<Record<string, stri
};
}, {});
const nativeCryptocurrencyName = addressToAssetName[ethers.constants.AddressZero];
const nativeCryptocurrencyName = addressToAssetName[ethers.ZeroAddress];
if (nativeCryptocurrencyName === undefined) {
throw new Error('Native cryptocurrency asset name is not found');
}

View File

@@ -1,25 +1,25 @@
import { BigNumber } from 'bignumber.js';
import { ethers } from 'ethers';
import { BigNumber } from "bignumber.js";
/**
* Converts denormalized ("human-readable") number to normalized ("machine-readable") number.
* @param input Any numeric value
* @param decimals Blockchain asset precision
* @param roundingMode Rounding mode
* @returns ethers.BigNumber
* @returns bigint
*/
export default function normalizeNumber(
input: BigNumber.Value,
decimals: BigNumber.Value,
roundingMode: BigNumber.RoundingMode,
roundingMode: BigNumber.RoundingMode
) {
const decimalsBN = new BigNumber(decimals);
if (!decimalsBN.isInteger()) throw new Error(`Decimals '${decimalsBN.toString()}' is not an integer`);
if (!decimalsBN.isInteger())
throw new Error(`Decimals '${decimalsBN.toString()}' is not an integer`);
const inputBN = new BigNumber(input);
return ethers.BigNumber.from(
return BigInt(
inputBN
.multipliedBy(new BigNumber(10).pow(decimals))
.integerValue(roundingMode)
.toString(),
.toString()
);
}

View File

@@ -1,13 +1,13 @@
import { Exchange__factory } from '@orionprotocol/contracts/lib/ethers-v5/index.js';
import { Exchange__factory } from '@orionprotocol/contracts/lib/ethers-v6/index.js';
import { ethers } from 'ethers';
import { z } from 'zod';
const swapThroughOrionPoolSchema = z.object({
name: z.literal('swapThroughOrionPool'),
args: z.tuple([
z.instanceof(ethers.BigNumber), // amount_spend
z.instanceof(ethers.BigNumber), // amount_receive
z.string().refine(ethers.utils.isAddress).array().nonempty(), // path
z.bigint(), // amount_spend
z.bigint(), // amount_receive
z.string().refine(ethers.isAddress).array().nonempty(), // path
z.boolean(), // is_exact_spend
]),
}).transform((data) => ({
@@ -21,34 +21,34 @@ const swapThroughOrionPoolSchema = z.object({
}));
const buyOrderSchema = z.tuple([ // buy order
z.string().refine(ethers.utils.isAddress), // senderAddress
z.string().refine(ethers.utils.isAddress), // matcherAddress
z.string().refine(ethers.utils.isAddress), // baseAsset
z.string().refine(ethers.utils.isAddress), // quoteAsset
z.string().refine(ethers.utils.isAddress), // matcherFeeAsset
z.instanceof(ethers.BigNumber), // amount
z.instanceof(ethers.BigNumber), // price
z.instanceof(ethers.BigNumber), // matcherFee
z.instanceof(ethers.BigNumber), // nonce
z.instanceof(ethers.BigNumber), // expiration
z.string().refine(ethers.isAddress), // senderAddress
z.string().refine(ethers.isAddress), // matcherAddress
z.string().refine(ethers.isAddress), // baseAsset
z.string().refine(ethers.isAddress), // quoteAsset
z.string().refine(ethers.isAddress), // matcherFeeAsset
z.bigint(), // amount
z.bigint(), // price
z.bigint(), // matcherFee
z.bigint(), // nonce
z.bigint(), // expiration
z.literal(1), // buySide
z.boolean(), // isPersonalSign
z.string().refine(ethers.utils.isHexString), // signature
z.string().refine(ethers.isHexString), // signature
]);
const sellOrderSchema = z.tuple([ // sell orer
z.string().refine(ethers.utils.isAddress), // senderAddress
z.string().refine(ethers.utils.isAddress), // matcherAddress
z.string().refine(ethers.utils.isAddress), // baseAsset
z.string().refine(ethers.utils.isAddress), // quoteAsset
z.string().refine(ethers.utils.isAddress), // matcherFeeAsset
z.instanceof(ethers.BigNumber), // amount
z.instanceof(ethers.BigNumber), // price
z.instanceof(ethers.BigNumber), // matcherFee
z.instanceof(ethers.BigNumber), // nonce
z.instanceof(ethers.BigNumber), // expiration
z.string().refine(ethers.isAddress), // senderAddress
z.string().refine(ethers.isAddress), // matcherAddress
z.string().refine(ethers.isAddress), // baseAsset
z.string().refine(ethers.isAddress), // quoteAsset
z.string().refine(ethers.isAddress), // matcherFeeAsset
z.bigint(), // amount
z.bigint(), // price
z.bigint(), // matcherFee
z.bigint(), // nonce
z.bigint(), // expiration
z.literal(0), // buySide
z.boolean(), // isPersonalSign
z.string().refine(ethers.utils.isHexString), // signature
z.string().refine(ethers.isHexString), // signature
]);
const toOrder = <T extends z.infer<typeof buyOrderSchema> | z.infer<typeof sellOrderSchema>>(data: T) => ({
@@ -71,9 +71,9 @@ const fillThroughOrionPoolSchema = z.object({
name: z.literal('fillThroughOrionPool'),
args: z.tuple([
sellOrderSchema,
z.instanceof(ethers.BigNumber), // filled amount
z.instanceof(ethers.BigNumber), // blockchainFee
z.string().refine(ethers.utils.isAddress).array().nonempty(), // path
z.bigint(), // filled amount
z.bigint(), // blockchainFee
z.string().refine(ethers.isAddress).array().nonempty(), // path
]),
}).transform((data) => ({
name: data.name,
@@ -90,8 +90,8 @@ const fillOrdersSchema = z.object({
args: z.tuple([
buyOrderSchema,
sellOrderSchema,
z.instanceof(ethers.BigNumber), // filledPrice
z.instanceof(ethers.BigNumber), // filledAmount
z.bigint(), // filledPrice
z.bigint(), // filledAmount
]),
}).transform((data) => ({
name: data.name,

View File

@@ -12,8 +12,7 @@
],
"compilerOptions": {
"target": "esnext",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"module": "ESNext",
"esModuleInterop": true,
"resolveJsonModule": true /* Enable importing .json files */,
"declaration": true /* Generate .d.ts files from TypeScript and JavaScript files in your project. */,