mirror of
https://github.com/orionprotocol/sdk.git
synced 2026-03-14 06:02:36 +03:00
Initial commit
This commit is contained in:
67
.eslintrc.js
Normal file
67
.eslintrc.js
Normal file
@@ -0,0 +1,67 @@
|
||||
module.exports = {
|
||||
ignorePatterns: ['.eslintrc.js'],
|
||||
env: {
|
||||
browser: true,
|
||||
es2021: true,
|
||||
node: true,
|
||||
},
|
||||
extends: [
|
||||
'airbnb-base',
|
||||
'plugin:@typescript-eslint/eslint-recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:@typescript-eslint/recommended-requiring-type-checking',
|
||||
],
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
tsconfigRootDir: "./",
|
||||
project: [
|
||||
"./tsconfig.json"
|
||||
],
|
||||
ecmaVersion: 12,
|
||||
sourceType: 'module',
|
||||
},
|
||||
plugins: [
|
||||
'@typescript-eslint',
|
||||
],
|
||||
rules: {
|
||||
'@typescript-eslint/consistent-type-assertions': [
|
||||
'error',
|
||||
{
|
||||
assertionStyle: 'never',
|
||||
},
|
||||
],
|
||||
'import/max-dependencies': [
|
||||
'error',
|
||||
{
|
||||
max: 20,
|
||||
ignoreTypeImports: false,
|
||||
},
|
||||
],
|
||||
'no-unused-vars': 'off',
|
||||
'@typescript-eslint/no-unused-vars': 'error',
|
||||
'no-shadow': 'off',
|
||||
'@typescript-eslint/no-shadow': ['error'],
|
||||
'max-len': [
|
||||
1,
|
||||
140,
|
||||
2,
|
||||
],
|
||||
'import/extensions': [
|
||||
'error',
|
||||
'ignorePackages',
|
||||
{
|
||||
js: 'never',
|
||||
jsx: 'never',
|
||||
ts: 'never',
|
||||
tsx: 'never',
|
||||
},
|
||||
],
|
||||
},
|
||||
settings: {
|
||||
'import/resolver': {
|
||||
node: {
|
||||
extensions: ['.js', '.jsx', '.ts', '.tsx'],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
34
.github/workflows/release-package.yml
vendored
Normal file
34
.github/workflows/release-package.yml
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
name: Node.js Package
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 12
|
||||
- run: npm ci
|
||||
- run: npm test
|
||||
|
||||
publish-gpr:
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
packages: write
|
||||
contents: read
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 12
|
||||
registry-url: https://npm.pkg.github.com/
|
||||
- run: npm ci
|
||||
- run: npm run build-ts
|
||||
- run: npm publish
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
||||
134
.gitignore
vendored
Normal file
134
.gitignore
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Snowpack dependency directory (https://snowpack.dev/)
|
||||
web_modules/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional stylelint cache
|
||||
.stylelintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variable files
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
out
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
lib
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# vuepress v2.x temp and cache directory
|
||||
.temp
|
||||
.cache
|
||||
|
||||
# Docusaurus cache and generated files
|
||||
.docusaurus
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
#idea service files
|
||||
.idea
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
||||
src/artifacts/contracts/
|
||||
6
.vscode/settings.json
vendored
Normal file
6
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"cSpell.words": [
|
||||
"bignumber",
|
||||
"denormalized"
|
||||
]
|
||||
}
|
||||
185
README.md
Normal file
185
README.md
Normal file
@@ -0,0 +1,185 @@
|
||||
# Orion Protocol SDK
|
||||
|
||||
## Install
|
||||
|
||||
Before install SDK you need create Personal Access Token.
|
||||
|
||||
1. Create PAT [here](https://github.com/settings/tokens):
|
||||
1. type any name (for example `READ_PACKAGES`)
|
||||
2. select scope `read:packages`)
|
||||
2. At your machine go to `~` (your home directory, **not project!**)
|
||||
3. Create or modify `.npmrc` file with content:
|
||||
|
||||
```
|
||||
//npm.pkg.github.com/:_authToken=YOUR_PAT
|
||||
@orionprotocol:registry=https://npm.pkg.github.com/
|
||||
```
|
||||
|
||||
4. Save `.npmrc` file
|
||||
5. Now you can install `@orionprotocol/sdk` as dependency in your package
|
||||
|
||||
# Usage
|
||||
|
||||
## High level methods
|
||||
|
||||
### Easy start
|
||||
|
||||
```ts
|
||||
import "dotenv/config";
|
||||
import { initOrionUnit } from "@orionprotocol/sdk";
|
||||
import { Wallet } from "ethers";
|
||||
|
||||
const chain = process.env.CHAINID; // 0x56
|
||||
const env = process.env.ENV; // production
|
||||
const privateKey = process.env.PRIVATE_KEY; // 0x...
|
||||
|
||||
if (!chain) throw new Error("CHAINID is required");
|
||||
if (!env) throw new Error("ENV is required");
|
||||
if (!privateKey) throw new Error("PRIVATE_KEY is required");
|
||||
|
||||
const wallet = new Wallet(privateKey);
|
||||
// OrionUnit is chain-in-environment abstraction
|
||||
const orionUnit = initOrionUnit(chain, env);
|
||||
|
||||
// Make market swap
|
||||
orionUnit
|
||||
.swapMarket({
|
||||
type: "exactSpend",
|
||||
assetIn: "ORN",
|
||||
assetOut: "USDT",
|
||||
feeAsset: "ORN",
|
||||
amount: 23.89045345,
|
||||
slippagePercent: 1,
|
||||
signer: wallet,
|
||||
options: {
|
||||
logger: console.log,
|
||||
// Set it to true if you want the issues associated with
|
||||
// the lack of allowance to be automatically corrected
|
||||
autoApprove: true,
|
||||
},
|
||||
})
|
||||
.then(console.log);
|
||||
```
|
||||
|
||||
## Low level methods
|
||||
|
||||
### Get historical price
|
||||
|
||||
```ts
|
||||
const candles = await orionUnit.priceFeed.getCandles(
|
||||
"ORN-USDT",
|
||||
1650287678, // interval start
|
||||
1650374078, // interval end
|
||||
"5m", // interval
|
||||
"all" // exchange
|
||||
);
|
||||
```
|
||||
|
||||
### Using contracts
|
||||
|
||||
```ts
|
||||
import { contracts } from "@orionprotocol/sdk";
|
||||
|
||||
const exchangeContract = contracts.Exchange__factory.connect(
|
||||
exchangeContractAddress,
|
||||
orionUnit.provider
|
||||
);
|
||||
const erc20Contract = contracts.ERC20__factory.connect(
|
||||
tokenAddress,
|
||||
orionUnit.provider
|
||||
);
|
||||
const governanceContract = contracts.OrionGovernance__factory.connect(
|
||||
governanceAddress,
|
||||
orionUnit.provider
|
||||
);
|
||||
const orionVoting = contracts.OrionVoting__factory.connect(
|
||||
votingContractAddress,
|
||||
orionUnit.provider
|
||||
);
|
||||
```
|
||||
|
||||
### Get tradable pairs
|
||||
|
||||
```ts
|
||||
const pairsList = await orionUnit.orionAggregator.getPairsList();
|
||||
```
|
||||
|
||||
### Get swap info
|
||||
|
||||
```ts
|
||||
const swapInfo = await orionUnit.orionAggregator.getSwapInfo(
|
||||
// Use 'exactSpend' when 'amount' is how much you want spend. Use 'exactReceive' otherwise
|
||||
type: 'exactSpend',
|
||||
assetIn: 'ORN',
|
||||
assetOut: 'USDT',
|
||||
amount: 6.23453457,
|
||||
);
|
||||
```
|
||||
|
||||
### Place order in Orion Aggregator
|
||||
|
||||
```ts
|
||||
|
||||
const { orderId } = await orionUnit.orionAggregator.placeOrder(
|
||||
{
|
||||
senderAddress: '0x61eed69c0d112c690fd6f44bb621357b89fbe67f',
|
||||
matcherAddress: '0xfbcad2c3a90fbd94c335fbdf8e22573456da7f68',
|
||||
baseAsset: '0xf223eca06261145b3287a0fefd8cfad371c7eb34',
|
||||
quoteAsset: '0xcb2951e90d8dcf16e1fa84ac0c83f48906d6a744',
|
||||
matcherFeeAsset: '0xf223eca06261145b3287a0fefd8cfad371c7eb34',
|
||||
amount: 500000000
|
||||
price: 334600000,
|
||||
matcherFee: '29296395', // Orion Fee + Network Fee
|
||||
nonce: 1650345051276
|
||||
expiration: 1652850651276
|
||||
buySide: 0,
|
||||
isPersonalSign: false, // https://docs.metamask.io/guide/signing-data.html#a-brief-history
|
||||
},
|
||||
false // Place in internal orderbook
|
||||
)
|
||||
```
|
||||
|
||||
### Orion Aggregator WebSocket
|
||||
|
||||
Available subscriptions:
|
||||
|
||||
```ts
|
||||
ASSET_PAIRS_CONFIG_UPDATES_SUBSCRIBE = 'apcus',
|
||||
AGGREGATED_ORDER_BOOK_UPDATES_SUBSCRIBE = 'aobus',
|
||||
ADDRESS_UPDATES_SUBSCRIBE = 'aus', // Orders history, balances info
|
||||
BROKER_TRADABLE_ATOMIC_SWAP_ASSETS_BALANCE_UPDATES_SUBSCRIBE = 'btasabus',
|
||||
SWAP_SUBSCRIBE = 'ss', // Swap info updates
|
||||
```
|
||||
|
||||
Example:
|
||||
|
||||
```ts
|
||||
import { services } from "@orionprotocol/sdk";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
|
||||
const swapRequestId = uuidv4();
|
||||
orionUnit.orionAggregator.ws.subscribe(
|
||||
services.orionAggregator.ws.SubscriptionType.SWAP_SUBSCRIBE,
|
||||
{
|
||||
payload: {
|
||||
d: swapRequestId,
|
||||
i: assetIn, // asset in
|
||||
o: assetOut, // asset out
|
||||
e: true, // true when type of swap is exactSpend, can be omitted (true bu default)
|
||||
a: 5.62345343,
|
||||
},
|
||||
// Handle data update in your way
|
||||
callback: (swapInfo) => {
|
||||
switch (swapInfo.kind) {
|
||||
case "exactSpend":
|
||||
console.log(swapInfo.availableAmountOut);
|
||||
|
||||
break;
|
||||
case "exactReceive":
|
||||
console.log(swapInfo.availableAmountOut);
|
||||
break;
|
||||
}
|
||||
},
|
||||
}
|
||||
);
|
||||
```
|
||||
15892
package-lock.json
generated
Normal file
15892
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
77
package.json
Normal file
77
package.json
Normal file
@@ -0,0 +1,77 @@
|
||||
{
|
||||
"name": "@orionprotocol/sdk",
|
||||
"version": "0.1.0",
|
||||
"description": "Orion Protocol SDK",
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
"scripts": {
|
||||
"start": "npm run build-ts && node lib/index.js",
|
||||
"develop": "concurrently -i -k -p \"[{name}]\" -n \"Node,TypeScript\" -c \"yellow.bold,cyan.bold\" \"yarn watch-js\" \"yarn watch-ts\"",
|
||||
"clean": "rimraf lib/*",
|
||||
"build-ts": "npm run typechain:generate-types && tsc --skipLibCheck",
|
||||
"watch-ts": "npm run typechain:generate-types && tsc -w --skipLibCheck",
|
||||
"watch-js": "nodemon lib/index.js",
|
||||
"test": "exit 0",
|
||||
"coverage": "jest --coverage",
|
||||
"lint:eslint": "eslint ./src --ext .ts,.js,.tsx,.jsx",
|
||||
"lint:eslint:fix": "eslint ./src --ext .ts,.js,.tsx,.jsx --fix",
|
||||
"typechain:generate-types": "typechain --target=ethers-v5 ./src/abis/*.json --out-dir ./src/artifacts/contracts"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/orionprotocol/sdk.git"
|
||||
},
|
||||
"publishConfig": {
|
||||
"@orionprotocol:registry": "https://npm.pkg.github.com"
|
||||
},
|
||||
"keywords": [
|
||||
"sdk",
|
||||
"orion",
|
||||
"orionprotocol",
|
||||
"trading"
|
||||
],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"bugs": {
|
||||
"url": "https://github.com/orionprotocol/sdk/issues"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@typechain/ethers-v5": "^10.0.0",
|
||||
"@types/csprng": "^0.1.2",
|
||||
"@types/node": "^17.0.23",
|
||||
"@types/node-fetch": "^2.6.1",
|
||||
"@types/socket.io-client": "1.4.33",
|
||||
"@types/uuid": "^8.3.4",
|
||||
"@types/ws": "^8.5.3",
|
||||
"@typescript-eslint/eslint-plugin": "^5.16.0",
|
||||
"@typescript-eslint/parser": "^5.16.0",
|
||||
"concurrently": "^7.0.0",
|
||||
"eslint": "^8.12.0",
|
||||
"eslint-config-airbnb-base": "^15.0.0",
|
||||
"eslint-plugin-import": "^2.25.4",
|
||||
"husky": "^7.0.4",
|
||||
"jest": "^27.5.1",
|
||||
"typechain": "^8.0.0",
|
||||
"typescript": "^4.5.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ethersproject/abstract-signer": "^5.6.0",
|
||||
"@ethersproject/providers": "^5.6.2",
|
||||
"bignumber.js": "^9.0.2",
|
||||
"csprng": "^0.1.2",
|
||||
"ethers": "^5.6.2",
|
||||
"isomorphic-ws": "^4.0.1",
|
||||
"just-clone": "^5.0.1",
|
||||
"node-fetch": "^2.6.7",
|
||||
"socket.io-client": "2.4.0",
|
||||
"tiny-invariant": "^1.2.0",
|
||||
"uuid": "^8.3.2",
|
||||
"websocket-heartbeat-js": "^1.1.0",
|
||||
"ws": "^8.5.0",
|
||||
"zod": "^3.14.4"
|
||||
},
|
||||
"homepage": "https://github.com/orionprotocol/sdk#readme",
|
||||
"files": [
|
||||
"lib/**/*"
|
||||
]
|
||||
}
|
||||
337
src/BalanceGuard.ts
Normal file
337
src/BalanceGuard.ts
Normal file
@@ -0,0 +1,337 @@
|
||||
import BigNumber from 'bignumber.js';
|
||||
import { ethers } from 'ethers';
|
||||
import clone from 'just-clone';
|
||||
import { contracts, utils } from '.';
|
||||
import { APPROVE_ERC20_GAS_LIMIT, NATIVE_CURRENCY_PRECISION } from './constants';
|
||||
import {
|
||||
AggregatedBalanceRequirement, Asset, BalanceIssue, BalanceRequirement, Source,
|
||||
} from './types';
|
||||
|
||||
const arrayEquals = (a: unknown[], b: unknown[]) => a.length === b.length
|
||||
&& a.every((value, index) => value === b[index]);
|
||||
|
||||
// By asset + sources + spender
|
||||
const aggregateBalanceRequirements = (requirements: BalanceRequirement[]) => requirements
|
||||
.reduce<AggregatedBalanceRequirement[]>((prev, curr) => {
|
||||
const aggregatedBalanceRequirement = prev.find(
|
||||
(item) => item.asset.address === curr.asset.address
|
||||
&& arrayEquals(item.sources, curr.sources)
|
||||
&& item.spenderAddress === curr.spenderAddress,
|
||||
);
|
||||
|
||||
if (aggregatedBalanceRequirement) {
|
||||
aggregatedBalanceRequirement.items = {
|
||||
...aggregatedBalanceRequirement.items,
|
||||
[curr.reason]: curr.amount,
|
||||
};
|
||||
return prev;
|
||||
}
|
||||
return [
|
||||
...prev,
|
||||
{
|
||||
asset: curr.asset,
|
||||
sources: curr.sources,
|
||||
spenderAddress: curr.spenderAddress,
|
||||
items: {
|
||||
[curr.reason]: curr.amount,
|
||||
},
|
||||
},
|
||||
|
||||
];
|
||||
}, []);
|
||||
|
||||
export default class BalanceGuard {
|
||||
private readonly balances: Partial<
|
||||
Record<
|
||||
string,
|
||||
Record<
|
||||
'exchange' | 'wallet' | 'allowance',
|
||||
BigNumber>
|
||||
>
|
||||
>;
|
||||
|
||||
public readonly requirements: BalanceRequirement[] = [];
|
||||
|
||||
private readonly nativeCryptocurrency: Asset;
|
||||
|
||||
private readonly provider: ethers.providers.Provider;
|
||||
|
||||
private readonly walletAddress: string;
|
||||
|
||||
constructor(
|
||||
balances: Partial<Record<string, Record<'exchange' | 'wallet' | 'allowance', BigNumber>>>,
|
||||
nativeCryptocurrency: Asset,
|
||||
provider: ethers.providers.Provider,
|
||||
walletAddress: string,
|
||||
) {
|
||||
this.balances = balances;
|
||||
this.nativeCryptocurrency = nativeCryptocurrency;
|
||||
this.provider = provider;
|
||||
this.walletAddress = walletAddress;
|
||||
}
|
||||
|
||||
registerRequirement(expense: BalanceRequirement) {
|
||||
this.requirements.push(expense);
|
||||
}
|
||||
|
||||
// Used for case feeAsset === assetOut
|
||||
setExtraBalance(assetName: string, amount: BigNumber.Value, source: Source) {
|
||||
const assetBalance = this.balances[assetName];
|
||||
if (!assetBalance) throw Error(`Can't set extra balance. Asset ${assetName} not found`);
|
||||
assetBalance[source] = assetBalance[source].plus(amount);
|
||||
}
|
||||
|
||||
private async checkResetRequired(
|
||||
assetAddress: string,
|
||||
spenderAddress: string,
|
||||
walletAddress: string,
|
||||
) {
|
||||
const tokenContract = contracts.ERC20__factory
|
||||
.connect(assetAddress, this.provider);
|
||||
const unsignedTx = await tokenContract.populateTransaction
|
||||
.approve(
|
||||
spenderAddress,
|
||||
ethers.constants.MaxUint256,
|
||||
);
|
||||
unsignedTx.from = walletAddress;
|
||||
let resetRequired = false;
|
||||
try {
|
||||
await this.provider.estimateGas(unsignedTx);
|
||||
} catch {
|
||||
resetRequired = true;
|
||||
}
|
||||
return resetRequired;
|
||||
}
|
||||
|
||||
async check() {
|
||||
const remainingBalances = clone(this.balances);
|
||||
const aggregatedRequirements = aggregateBalanceRequirements(this.requirements);
|
||||
|
||||
// Balance absorption order is important!
|
||||
// 1. Exchange-contract only
|
||||
// 2. Exchange + wallet (can produce approves requirements)
|
||||
// 3. Wallet balance (tokens) (can produce approves requirements)
|
||||
// 4. Wallet balance: native cryptocurrency
|
||||
|
||||
const requiredApproves: AggregatedBalanceRequirement = {
|
||||
asset: this.nativeCryptocurrency,
|
||||
sources: ['wallet'],
|
||||
items: {},
|
||||
};
|
||||
|
||||
const balanceIssues: BalanceIssue[] = [];
|
||||
|
||||
const flattedAggregatedRequirements = Object
|
||||
.values(aggregatedRequirements)
|
||||
.flatMap((item) => item);
|
||||
|
||||
const exchangeOnlyAggregatedRequirements = aggregatedRequirements
|
||||
.filter(({ sources }) => sources.length === 1 && sources[0] === 'exchange');
|
||||
|
||||
exchangeOnlyAggregatedRequirements.forEach(({ asset, items }) => {
|
||||
const remainingBalance = remainingBalances[asset.name];
|
||||
if (!remainingBalance) throw new Error(`No ${asset.name} balance`);
|
||||
const itemsAmountSum = Object.values(items)
|
||||
.reduce<BigNumber>((p, c) => (c ? p.plus(c) : p), new BigNumber(0));
|
||||
|
||||
remainingBalance.exchange = remainingBalance.exchange.minus(itemsAmountSum);
|
||||
if (remainingBalance.exchange.lt(0)) {
|
||||
const lackAmount = remainingBalance.exchange.abs();
|
||||
const exchangeBalance = this.balances?.[asset.name]?.exchange;
|
||||
|
||||
balanceIssues.push({
|
||||
asset,
|
||||
sources: ['exchange'],
|
||||
message: `Not enough ${asset.name} on exchange balance. `
|
||||
+ `Needed: ${itemsAmountSum.toString()}, available: ${exchangeBalance?.toString()}. `
|
||||
+ `You need to deposit at least ${lackAmount.toString()} ${asset.name} into exchange contract`,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const exchangePlusWalletAggregatedRequirements = aggregatedRequirements
|
||||
.filter(({ sources }) => sources[0] === 'exchange' && sources[1] === 'wallet');
|
||||
|
||||
// This requirements can be fulfilled by exchange + wallet
|
||||
await Promise.all(exchangePlusWalletAggregatedRequirements
|
||||
.map(async ({ asset, spenderAddress, items }) => {
|
||||
const remainingBalance = remainingBalances[asset.name];
|
||||
if (!remainingBalance) throw new Error(`No ${asset.name} balance`);
|
||||
const itemsAmountSum = Object.values(items)
|
||||
.reduce<BigNumber>((p, c) => (c ? p.plus(c) : p), new BigNumber(0));
|
||||
|
||||
remainingBalance.exchange = remainingBalance.exchange.minus(itemsAmountSum);
|
||||
if (remainingBalance.exchange.lt(0)) {
|
||||
const lackAmount = remainingBalance.exchange.abs(); // e.g. -435.234234 to 434.234234
|
||||
// Try to take lack amount from wallet
|
||||
const approvedWalletBalance = BigNumber
|
||||
.min(
|
||||
remainingBalance.wallet,
|
||||
remainingBalance.allowance,
|
||||
// For native cryptocurrency allowance is always just current balance
|
||||
);
|
||||
if (lackAmount.lte(approvedWalletBalance)) { // We can take lack amount from wallet
|
||||
remainingBalance.wallet = remainingBalance.wallet.minus(lackAmount);
|
||||
} else {
|
||||
// We can't take lack amount from wallet. Is approve helpful?
|
||||
const approveAvailable = remainingBalance.wallet.gt(approvedWalletBalance)
|
||||
? remainingBalance.wallet.minus(approvedWalletBalance)
|
||||
: new BigNumber(0);
|
||||
const approveIsHelpful = approveAvailable.gte(lackAmount);
|
||||
const targetApprove = approvedWalletBalance.plus(lackAmount);
|
||||
|
||||
const exchangeBalance = this.balances?.[asset.name]?.exchange;
|
||||
const available = exchangeBalance?.plus(approvedWalletBalance);
|
||||
|
||||
const issueMessage = `Not enough ${asset.name} on exchange + wallet balance. `
|
||||
+ `Needed: ${itemsAmountSum.toString()}, available: ${available?.toString()} `
|
||||
+ `(exchange: ${exchangeBalance?.toString()}, wallet: ${approvedWalletBalance.toString()}). ${approveIsHelpful
|
||||
? `You need to be allowed to spend another ${lackAmount.toString()} ${asset.name} more`
|
||||
: 'Approve is not helpful'}`;
|
||||
if (approveIsHelpful) {
|
||||
if (!spenderAddress) throw new Error(`Spender address is required for ${asset.name}`);
|
||||
const resetRequired = await this.checkResetRequired(
|
||||
asset.address,
|
||||
spenderAddress,
|
||||
this.walletAddress,
|
||||
);
|
||||
const gasPriceWei = await this.provider.getGasPrice();
|
||||
const approveTransactionCost = ethers.BigNumber
|
||||
.from(APPROVE_ERC20_GAS_LIMIT)
|
||||
.mul(gasPriceWei);
|
||||
const denormalizedApproveTransactionCost = utils
|
||||
.denormalizeNumber(approveTransactionCost, NATIVE_CURRENCY_PRECISION);
|
||||
|
||||
requiredApproves.items = {
|
||||
...requiredApproves.items,
|
||||
...resetRequired && {
|
||||
[`Reset ${asset.name} from 'wallet' to ${spenderAddress}`]: denormalizedApproveTransactionCost.toString(),
|
||||
},
|
||||
[`Approve ${asset.name} from 'wallet' to ${spenderAddress}`]: denormalizedApproveTransactionCost.toString(),
|
||||
};
|
||||
balanceIssues.push({
|
||||
asset,
|
||||
sources: ['exchange', 'wallet'],
|
||||
approves: [
|
||||
...resetRequired ? [{
|
||||
targetAmount: 0,
|
||||
spenderAddress,
|
||||
}] : [],
|
||||
{
|
||||
targetAmount: targetApprove,
|
||||
spenderAddress,
|
||||
},
|
||||
],
|
||||
message: issueMessage,
|
||||
});
|
||||
} else {
|
||||
balanceIssues.push({
|
||||
asset,
|
||||
sources: ['exchange', 'wallet'],
|
||||
message: issueMessage,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
const walletTokensAggregatedRequirements = flattedAggregatedRequirements
|
||||
.filter(({ sources, asset }) => sources[0] === 'wallet' && asset.name !== this.nativeCryptocurrency.name);
|
||||
|
||||
await Promise.all(walletTokensAggregatedRequirements
|
||||
.map(async ({ asset, spenderAddress, items }) => {
|
||||
const remainingBalance = remainingBalances[asset.name];
|
||||
if (!remainingBalance) throw new Error(`No ${asset.name} balance`);
|
||||
const itemsAmountSum = Object.values(items)
|
||||
.reduce<BigNumber>((p, c) => (c ? p.plus(c) : p), new BigNumber(0));
|
||||
const approvedWalletBalance = BigNumber
|
||||
.min(
|
||||
remainingBalance.wallet,
|
||||
remainingBalance.allowance,
|
||||
);
|
||||
if (itemsAmountSum.lte(approvedWalletBalance)) { // Approved wallet balance is enough
|
||||
remainingBalance.wallet = remainingBalance.wallet.minus(itemsAmountSum);
|
||||
} else {
|
||||
// We can't take lack amount from wallet. Is approve helpful?
|
||||
const lackAmount = itemsAmountSum.minus(approvedWalletBalance).abs();
|
||||
const approveAvailable = remainingBalance.wallet.gt(approvedWalletBalance)
|
||||
? remainingBalance.wallet.minus(approvedWalletBalance)
|
||||
: new BigNumber(0);
|
||||
const approveIsHelpful = approveAvailable.gte(lackAmount);
|
||||
const targetApprove = approvedWalletBalance.plus(lackAmount);
|
||||
|
||||
const issueMessage = `Not enough ${asset.name} on wallet balance. `
|
||||
+ `Needed: ${itemsAmountSum.toString()}, available: ${approvedWalletBalance.toString()}. ${approveIsHelpful
|
||||
? `You need to be allowed to spend another ${lackAmount.toString()} ${asset.name} more`
|
||||
: 'Approve is not helpful'}`;
|
||||
if (approveIsHelpful) {
|
||||
if (!spenderAddress) throw new Error(`Spender address is required for ${asset.name}`);
|
||||
const resetRequired = await this.checkResetRequired(
|
||||
asset.address,
|
||||
spenderAddress,
|
||||
this.walletAddress,
|
||||
);
|
||||
const gasPriceWei = await this.provider.getGasPrice();
|
||||
const approveTransactionCost = ethers.BigNumber
|
||||
.from(APPROVE_ERC20_GAS_LIMIT)
|
||||
.mul(gasPriceWei);
|
||||
const denormalizedApproveTransactionCost = utils
|
||||
.denormalizeNumber(approveTransactionCost, NATIVE_CURRENCY_PRECISION);
|
||||
|
||||
requiredApproves.items = {
|
||||
...requiredApproves.items,
|
||||
...resetRequired && {
|
||||
[`Reset ${asset.name} from 'wallet' to ${spenderAddress}`]: denormalizedApproveTransactionCost.toString(),
|
||||
},
|
||||
[`Approve ${asset.name} from 'wallet' to ${spenderAddress}`]: denormalizedApproveTransactionCost.toString(),
|
||||
};
|
||||
balanceIssues.push({
|
||||
asset,
|
||||
sources: ['wallet'],
|
||||
approves: [
|
||||
...resetRequired ? [{
|
||||
targetAmount: 0,
|
||||
spenderAddress,
|
||||
}] : [],
|
||||
{
|
||||
targetAmount: targetApprove,
|
||||
spenderAddress,
|
||||
},
|
||||
],
|
||||
message: issueMessage,
|
||||
});
|
||||
} else {
|
||||
balanceIssues.push({
|
||||
asset,
|
||||
sources: ['wallet'],
|
||||
message: issueMessage,
|
||||
});
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
const walletNativeAggregatedRequirements = flattedAggregatedRequirements
|
||||
.filter(({ sources, asset }) => sources[0] === 'wallet' && asset.name === this.nativeCryptocurrency.name);
|
||||
|
||||
walletNativeAggregatedRequirements.forEach(({ asset, items }) => {
|
||||
const remainingBalance = remainingBalances[asset.name];
|
||||
if (!remainingBalance) throw new Error(`No ${asset.name} balance`);
|
||||
|
||||
const itemsAmountSum = Object.values({ ...items, ...requiredApproves.items })
|
||||
.reduce<BigNumber>((p, c) => (c ? p.plus(c) : p), new BigNumber(0));
|
||||
|
||||
remainingBalance.wallet = remainingBalance.wallet.minus(itemsAmountSum);
|
||||
if (remainingBalance.wallet.lt(0)) {
|
||||
const lackAmount = remainingBalance.wallet.abs();
|
||||
balanceIssues.push({
|
||||
asset,
|
||||
sources: ['wallet'],
|
||||
message: `Not enough ${asset.name} on wallet balance. `
|
||||
+ `You need to deposit at least ${lackAmount.toString()} ${asset.name} into wallet contract`,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return balanceIssues;
|
||||
}
|
||||
}
|
||||
46
src/OrionUnit/index.ts
Normal file
46
src/OrionUnit/index.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { ethers } from 'ethers';
|
||||
import { OrionAggregator } from '../services/OrionAggregator';
|
||||
import { OrionBlockchain } from '../services/OrionBlockchain';
|
||||
import { PriceFeed } from '../services/PriceFeed';
|
||||
import swapMarket, { SwapMarketParams } from './swapMarket';
|
||||
import { SupportedChainId } from '../types';
|
||||
|
||||
type PureSwapMarketParams= Omit<SwapMarketParams, 'orionUnit'>
|
||||
export default class OrionUnit {
|
||||
public readonly env: string;
|
||||
|
||||
public readonly chainId: SupportedChainId;
|
||||
|
||||
public readonly provider: ethers.providers.StaticJsonRpcProvider;
|
||||
|
||||
public readonly orionBlockchain: OrionBlockchain;
|
||||
|
||||
public readonly orionAggregator: OrionAggregator;
|
||||
|
||||
public readonly priceFeed: PriceFeed;
|
||||
|
||||
public readonly apiUrl: string;
|
||||
|
||||
constructor(
|
||||
chainId: SupportedChainId,
|
||||
rpc: string,
|
||||
env: string,
|
||||
apiUrl: string,
|
||||
) {
|
||||
this.chainId = chainId;
|
||||
this.provider = new ethers.providers.StaticJsonRpcProvider(rpc);
|
||||
this.env = env;
|
||||
this.apiUrl = apiUrl;
|
||||
|
||||
this.orionBlockchain = new OrionBlockchain(apiUrl, chainId);
|
||||
this.orionAggregator = new OrionAggregator(apiUrl, chainId);
|
||||
this.priceFeed = new PriceFeed(apiUrl);
|
||||
}
|
||||
|
||||
public swapMarket(params: PureSwapMarketParams) {
|
||||
return swapMarket({
|
||||
...params,
|
||||
orionUnit: this,
|
||||
});
|
||||
}
|
||||
}
|
||||
419
src/OrionUnit/swapMarket.ts
Normal file
419
src/OrionUnit/swapMarket.ts
Normal file
@@ -0,0 +1,419 @@
|
||||
/* eslint-disable max-len */
|
||||
import BigNumber from 'bignumber.js';
|
||||
import { ethers } from 'ethers';
|
||||
import getBalances from '../utils/getBalances';
|
||||
import BalanceGuard from '../BalanceGuard';
|
||||
import getAvailableSources from '../utils/getAvailableFundsSources';
|
||||
import { Approve, BalanceIssue } from '../types';
|
||||
import OrionUnit from '.';
|
||||
import { contracts, crypt, utils } from '..';
|
||||
import { INTERNAL_ORION_PRECISION, NATIVE_CURRENCY_PRECISION, SWAP_THROUGH_ORION_POOL_GAS_LIMIT } from '../constants';
|
||||
|
||||
export type SwapMarketParams = {
|
||||
type: 'exactSpend' | 'exactReceive',
|
||||
assetIn: string,
|
||||
assetOut: string,
|
||||
amount: BigNumber.Value,
|
||||
feeAsset: string,
|
||||
slippagePercent: BigNumber.Value,
|
||||
signer: ethers.Signer,
|
||||
orionUnit: OrionUnit,
|
||||
options?: {
|
||||
logger?: (message: string) => void,
|
||||
// route?: 'pool' | 'aggregator',
|
||||
autoApprove?: boolean,
|
||||
}
|
||||
}
|
||||
|
||||
type AggregatorOrder = {
|
||||
through: 'aggregator'
|
||||
id: string,
|
||||
}
|
||||
|
||||
type PoolSwap = {
|
||||
through: 'orion_pool'
|
||||
txHash: string,
|
||||
}
|
||||
|
||||
type Swap = AggregatorOrder | PoolSwap;
|
||||
|
||||
export default async function swapMarket({
|
||||
type,
|
||||
assetIn,
|
||||
assetOut,
|
||||
amount,
|
||||
feeAsset,
|
||||
slippagePercent,
|
||||
signer,
|
||||
orionUnit,
|
||||
options,
|
||||
}: SwapMarketParams): Promise<Swap> {
|
||||
if (amount === '') throw new Error('Amount can not be empty');
|
||||
if (assetIn === '') throw new Error('AssetIn can not be empty');
|
||||
if (assetOut === '') throw new Error('AssetOut can not be empty');
|
||||
if (feeAsset === '') throw new Error('Fee asset can not be empty');
|
||||
if (slippagePercent === '') throw new Error('Slippage percent can not be empty');
|
||||
|
||||
const amountBN = new BigNumber(amount);
|
||||
if (amountBN.isNaN()) throw new Error(`Amount '${amount.toString()}' is not a number`);
|
||||
|
||||
const slippagePercentBN = new BigNumber(slippagePercent);
|
||||
if (slippagePercentBN.isNaN()) throw new Error(`Slippage percent '${slippagePercent.toString()}' is not a number`);
|
||||
if (slippagePercentBN.lte(0)) throw new Error('Slippage percent should be greater than 0');
|
||||
if (slippagePercentBN.gte(50)) throw new Error('Slippage percent should be less than 50');
|
||||
|
||||
const walletAddress = await signer.getAddress();
|
||||
options?.logger?.(`Wallet address is ${walletAddress}`);
|
||||
|
||||
const {
|
||||
orionBlockchain, orionAggregator, provider, chainId,
|
||||
} = orionUnit;
|
||||
const {
|
||||
exchangeContractAddress,
|
||||
matcherAddress,
|
||||
assetToAddress,
|
||||
} = await orionBlockchain.getInfo();
|
||||
const addressToAsset = Object
|
||||
.entries(assetToAddress)
|
||||
.reduce<Partial<Record<string, string>>>((prev, [asset, address]) => {
|
||||
if (!address) return prev;
|
||||
return {
|
||||
...prev,
|
||||
[address]: asset,
|
||||
};
|
||||
}, {});
|
||||
|
||||
const nativeCryptocurrency = addressToAsset[ethers.constants.AddressZero];
|
||||
if (!nativeCryptocurrency) throw new Error('Native cryptocurrency asset is not found');
|
||||
|
||||
const exchangeContract = contracts.Exchange__factory.connect(exchangeContractAddress, provider);
|
||||
const feeAssets = await orionBlockchain.getTokensFee();
|
||||
const pricesInOrn = await orionBlockchain.getPrices();
|
||||
const gasPriceWei = await orionBlockchain.getGasPriceWei();
|
||||
|
||||
const gasPriceGwei = ethers.utils.formatUnits(gasPriceWei, 'gwei').toString();
|
||||
|
||||
const assetInAddress = assetToAddress[assetIn];
|
||||
if (!assetInAddress) throw new Error(`Asset '${assetIn}' not found`);
|
||||
const feeAssetAddress = assetToAddress[feeAsset];
|
||||
if (!feeAssetAddress) throw new Error(`Fee asset '${feeAsset}' not found. Available assets: ${Object.keys(feeAssets).join(', ')}`);
|
||||
|
||||
const balances = await getBalances(
|
||||
{
|
||||
[assetIn]: assetInAddress,
|
||||
[feeAsset]: feeAssetAddress,
|
||||
[nativeCryptocurrency]: ethers.constants.AddressZero,
|
||||
},
|
||||
orionAggregator,
|
||||
walletAddress,
|
||||
exchangeContract,
|
||||
provider,
|
||||
);
|
||||
|
||||
const balanceGuard = new BalanceGuard(
|
||||
balances,
|
||||
{
|
||||
name: nativeCryptocurrency,
|
||||
address: ethers.constants.AddressZero,
|
||||
},
|
||||
provider,
|
||||
walletAddress,
|
||||
);
|
||||
|
||||
const swapInfo = await orionAggregator.getSwapInfo(type, assetIn, assetOut, amount.toString());
|
||||
|
||||
if (swapInfo.type === 'exactReceive' && amountBN.lt(swapInfo.minAmountOut)) {
|
||||
throw new Error(`Amount is too low. Min amountOut is ${swapInfo.minAmountOut} ${assetOut}`);
|
||||
}
|
||||
|
||||
if (swapInfo.type === 'exactSpend' && amountBN.lt(swapInfo.minAmountIn)) {
|
||||
throw new Error(`Amount is too low. Min amountIn is ${swapInfo.minAmountIn} ${assetIn}`);
|
||||
}
|
||||
|
||||
if (swapInfo.orderInfo === null) throw new Error(swapInfo.executionInfo);
|
||||
|
||||
const percent = new BigNumber(slippagePercent).div(100);
|
||||
|
||||
const fixBalanceIssue = async (issue: BalanceIssue) => {
|
||||
const tokenContract = contracts.ERC20__factory.connect(issue.asset.address, provider);
|
||||
const approve = async ({ spenderAddress, targetAmount }: Approve) => {
|
||||
const bnTargetAmount = new BigNumber(targetAmount);
|
||||
const unsignedApproveTx = await tokenContract
|
||||
.populateTransaction
|
||||
.approve(
|
||||
spenderAddress,
|
||||
bnTargetAmount.isZero()
|
||||
? '0' // Reset
|
||||
: ethers.constants.MaxUint256, // Infinite approve
|
||||
);
|
||||
|
||||
const nonce = await provider.getTransactionCount(walletAddress, 'pending');
|
||||
|
||||
unsignedApproveTx.chainId = parseInt(chainId, 16);
|
||||
unsignedApproveTx.gasPrice = ethers.BigNumber.from(gasPriceWei);
|
||||
unsignedApproveTx.nonce = nonce;
|
||||
unsignedApproveTx.from = walletAddress;
|
||||
const gasLimit = await provider.estimateGas(unsignedApproveTx);
|
||||
unsignedApproveTx.gasLimit = gasLimit;
|
||||
|
||||
const signedTx = await signer.signTransaction(unsignedApproveTx);
|
||||
const txResponse = await provider.sendTransaction(signedTx);
|
||||
options?.logger?.(`${issue.asset.name} approve transaction sent ${txResponse.hash}. Waiting for confirmation...`);
|
||||
await txResponse.wait();
|
||||
options?.logger?.(`${issue.asset.name} approve transaction confirmed.`);
|
||||
};
|
||||
await issue.approves?.reduce(async (promise, item) => {
|
||||
await promise;
|
||||
return approve(item);
|
||||
}, Promise.resolve());
|
||||
};
|
||||
|
||||
if (swapInfo.isThroughPoolOptimal) {
|
||||
options?.logger?.('Swap through pool');
|
||||
const pathAddresses = swapInfo.path.map((name) => {
|
||||
const assetAddress = assetToAddress?.[name];
|
||||
if (!assetAddress) throw new Error(`No asset address for ${name}`);
|
||||
return assetAddress;
|
||||
});
|
||||
|
||||
const amountOutWithSlippage = new BigNumber(swapInfo.amountOut)
|
||||
.multipliedBy(new BigNumber(1).minus(percent))
|
||||
.toString();
|
||||
const amountInWithSlippage = new BigNumber(swapInfo.amountIn)
|
||||
.multipliedBy(new BigNumber(1).plus(percent))
|
||||
.toString();
|
||||
|
||||
const amountSpend = swapInfo.type === 'exactSpend' ? swapInfo.amountIn : amountInWithSlippage;
|
||||
|
||||
balanceGuard.registerRequirement({
|
||||
reason: 'Amount spend',
|
||||
asset: {
|
||||
name: assetIn,
|
||||
address: assetInAddress,
|
||||
},
|
||||
amount: amountSpend.toString(),
|
||||
spenderAddress: exchangeContractAddress,
|
||||
sources: getAvailableSources('amount', assetInAddress, 'orion_pool'),
|
||||
});
|
||||
|
||||
const amountReceive = swapInfo.type === 'exactReceive' ? swapInfo.amountOut : amountOutWithSlippage;
|
||||
const unsignedSwapThroughOrionPoolTx = await exchangeContract.populateTransaction.swapThroughOrionPool(
|
||||
utils.normalizeNumber(
|
||||
amountSpend,
|
||||
INTERNAL_ORION_PRECISION,
|
||||
BigNumber.ROUND_CEIL,
|
||||
),
|
||||
utils.normalizeNumber(
|
||||
amountReceive,
|
||||
INTERNAL_ORION_PRECISION,
|
||||
BigNumber.ROUND_FLOOR,
|
||||
),
|
||||
pathAddresses,
|
||||
type === 'exactSpend',
|
||||
);
|
||||
|
||||
unsignedSwapThroughOrionPoolTx.chainId = parseInt(chainId, 16);
|
||||
unsignedSwapThroughOrionPoolTx.gasPrice = ethers.BigNumber.from(gasPriceWei);
|
||||
|
||||
unsignedSwapThroughOrionPoolTx.from = walletAddress;
|
||||
const amountSpendBN = new BigNumber(amountSpend);
|
||||
|
||||
let value = new BigNumber(0);
|
||||
const denormalizedAssetInExchangeBalance = balances[assetIn]?.exchange;
|
||||
if (!denormalizedAssetInExchangeBalance) throw new Error(`Asset '${assetIn}' exchange balance is not found`);
|
||||
if (assetIn === nativeCryptocurrency && amountSpendBN.gt(denormalizedAssetInExchangeBalance)) {
|
||||
value = amountSpendBN.minus(denormalizedAssetInExchangeBalance);
|
||||
}
|
||||
unsignedSwapThroughOrionPoolTx.value = utils.normalizeNumber(value, NATIVE_CURRENCY_PRECISION, BigNumber.ROUND_CEIL);
|
||||
unsignedSwapThroughOrionPoolTx.gasLimit = ethers.BigNumber.from(SWAP_THROUGH_ORION_POOL_GAS_LIMIT);
|
||||
|
||||
const transactionCost = ethers.BigNumber.from(SWAP_THROUGH_ORION_POOL_GAS_LIMIT).mul(gasPriceWei);
|
||||
const denormalizedTransactionCost = utils.denormalizeNumber(transactionCost, NATIVE_CURRENCY_PRECISION);
|
||||
|
||||
balanceGuard.registerRequirement({
|
||||
reason: 'Network fee',
|
||||
asset: {
|
||||
name: nativeCryptocurrency,
|
||||
address: ethers.constants.AddressZero,
|
||||
},
|
||||
amount: denormalizedTransactionCost.toString(),
|
||||
sources: getAvailableSources('network_fee', ethers.constants.AddressZero, 'orion_pool'),
|
||||
});
|
||||
|
||||
if (value.gt(0)) {
|
||||
balanceGuard.registerRequirement({
|
||||
reason: 'Transaction value (extra amount)',
|
||||
asset: {
|
||||
name: nativeCryptocurrency,
|
||||
address: ethers.constants.AddressZero,
|
||||
},
|
||||
amount: value.toString(),
|
||||
sources: getAvailableSources('amount', ethers.constants.AddressZero, 'orion_pool'),
|
||||
});
|
||||
}
|
||||
|
||||
options?.logger?.(`Balance requirements: ${balanceGuard.requirements
|
||||
.map((requirement) => `${requirement.amount} ${requirement.asset.name} `
|
||||
+ `for '${requirement.reason}' `
|
||||
+ `from [${requirement.sources.join(' + ')}]`)
|
||||
.join(', ')}`);
|
||||
|
||||
const balanceIssues = await balanceGuard.check();
|
||||
const autofixableBalanceIssues = balanceIssues.filter((balanceIssue) => balanceIssue.approves);
|
||||
const allBalanceIssuesIsAutofixable = autofixableBalanceIssues.length === balanceIssues.length;
|
||||
if (!allBalanceIssuesIsAutofixable) options?.logger?.('Some balance issues is not autofixable');
|
||||
|
||||
if (!allBalanceIssuesIsAutofixable || (options !== undefined && !options.autoApprove)) {
|
||||
throw new Error(`Balance issues: ${balanceIssues.map((issue, i) => `${i + 1}. ${issue.message}`).join('\n')}`);
|
||||
}
|
||||
|
||||
await autofixableBalanceIssues.reduce(async (promise, item) => {
|
||||
await promise;
|
||||
return fixBalanceIssue(item);
|
||||
}, Promise.resolve());
|
||||
|
||||
const nonce = await provider.getTransactionCount(walletAddress, 'pending');
|
||||
unsignedSwapThroughOrionPoolTx.nonce = nonce;
|
||||
|
||||
const signedSwapThroughOrionPoolTx = await signer.signTransaction(unsignedSwapThroughOrionPoolTx);
|
||||
const swapThroughOrionPoolTxResponse = await provider.sendTransaction(signedSwapThroughOrionPoolTx);
|
||||
return {
|
||||
through: 'orion_pool',
|
||||
txHash: swapThroughOrionPoolTxResponse.hash,
|
||||
};
|
||||
}
|
||||
options?.logger?.('Swap through aggregator');
|
||||
|
||||
const slippageMultiplier = new BigNumber(1).plus(
|
||||
swapInfo.orderInfo.side === 'SELL'
|
||||
? percent.negated() // e.g. -0.01
|
||||
: percent, // e.g. 0.01
|
||||
);
|
||||
|
||||
const safePriceWithDeviation = percent.isZero()
|
||||
? swapInfo.orderInfo.safePrice
|
||||
: new BigNumber(swapInfo.orderInfo.safePrice)
|
||||
.multipliedBy(slippageMultiplier)
|
||||
.toString();
|
||||
|
||||
const [baseAssetName, quoteAssetName] = swapInfo.orderInfo.assetPair.split('-');
|
||||
const pairConfig = await orionAggregator.getPairConfig(`${baseAssetName}-${quoteAssetName}`);
|
||||
if (!pairConfig) throw new Error(`Pair config ${baseAssetName}-${quoteAssetName} not found`);
|
||||
|
||||
const baseAssetAddress = assetToAddress[baseAssetName];
|
||||
if (!baseAssetAddress) throw new Error(`No asset address for ${baseAssetName}`);
|
||||
const quoteAssetAddress = assetToAddress[quoteAssetName];
|
||||
if (!quoteAssetAddress) throw new Error(`No asset address for ${quoteAssetName}`);
|
||||
|
||||
const safePriceWithAppliedPrecision = new BigNumber(safePriceWithDeviation)
|
||||
.decimalPlaces(
|
||||
pairConfig.pricePrecision,
|
||||
swapInfo.orderInfo.side === 'BUY'
|
||||
? BigNumber.ROUND_CEIL
|
||||
: BigNumber.ROUND_FLOOR,
|
||||
);
|
||||
|
||||
balanceGuard.registerRequirement({
|
||||
reason: 'Amount',
|
||||
asset: {
|
||||
name: assetIn,
|
||||
address: assetInAddress,
|
||||
},
|
||||
amount: swapInfo.orderInfo.side === 'SELL'
|
||||
? swapInfo.orderInfo.amount.toString()
|
||||
: safePriceWithAppliedPrecision.multipliedBy(swapInfo.orderInfo.amount).toString(),
|
||||
spenderAddress: exchangeContractAddress,
|
||||
sources: getAvailableSources('amount', assetInAddress, 'aggregator'),
|
||||
});
|
||||
|
||||
// Fee calculation
|
||||
const baseAssetPriceInOrn = pricesInOrn?.[baseAssetAddress];
|
||||
if (!baseAssetPriceInOrn) throw new Error(`Base asset price ${baseAssetName} in ORN not found`);
|
||||
const baseCurrencyPriceInOrn = pricesInOrn[ethers.constants.AddressZero];
|
||||
if (!baseCurrencyPriceInOrn) throw new Error('Base currency price in ORN not found');
|
||||
const feeAssetPriceInOrn = pricesInOrn[feeAssetAddress];
|
||||
if (!feeAssetPriceInOrn) throw new Error(`Fee asset price ${feeAsset} in ORN not found`);
|
||||
const feePercent = feeAssets?.[feeAsset];
|
||||
if (!feePercent) throw new Error(`Fee asset ${feeAsset} not available`);
|
||||
|
||||
const { orionFeeInFeeAsset, networkFeeInFeeAsset, totalFeeInFeeAsset } = utils.calculateFeeInFeeAsset(
|
||||
swapInfo.orderInfo.amount,
|
||||
feeAssetPriceInOrn,
|
||||
baseAssetPriceInOrn,
|
||||
baseCurrencyPriceInOrn,
|
||||
gasPriceGwei,
|
||||
feePercent,
|
||||
);
|
||||
|
||||
if (feeAsset === assetOut) {
|
||||
options?.logger?.('Fee asset equals received asset. The fee can be paid from the amount received');
|
||||
options?.logger?.(`Set extra balance: + ${swapInfo.amountOut} ${assetOut} to exchange`);
|
||||
|
||||
balanceGuard.setExtraBalance(feeAsset, swapInfo.amountOut, 'exchange');
|
||||
}
|
||||
|
||||
balanceGuard.registerRequirement({
|
||||
reason: 'Network fee',
|
||||
asset: {
|
||||
name: feeAsset,
|
||||
address: feeAssetAddress,
|
||||
},
|
||||
amount: networkFeeInFeeAsset,
|
||||
spenderAddress: exchangeContractAddress,
|
||||
sources: getAvailableSources('network_fee', feeAssetAddress, 'aggregator'),
|
||||
});
|
||||
|
||||
balanceGuard.registerRequirement({
|
||||
reason: 'Orion fee',
|
||||
asset: {
|
||||
name: feeAsset,
|
||||
address: feeAssetAddress,
|
||||
},
|
||||
amount: orionFeeInFeeAsset,
|
||||
spenderAddress: exchangeContractAddress,
|
||||
sources: getAvailableSources('orion_fee', feeAssetAddress, 'aggregator'),
|
||||
});
|
||||
|
||||
options?.logger?.(`Balance requirements: ${balanceGuard.requirements
|
||||
.map((requirement) => `${requirement.amount} ${requirement.asset.name} `
|
||||
+ `for '${requirement.reason}' `
|
||||
+ `from [${requirement.sources.join(' + ')}]`)
|
||||
.join(', ')}`);
|
||||
|
||||
const balanceIssues = await balanceGuard.check();
|
||||
const autofixableBalanceIssues = balanceIssues.filter((balanceIssue) => balanceIssue.approves);
|
||||
const allBalanceIssuesIsAutofixable = autofixableBalanceIssues.length === balanceIssues.length;
|
||||
if (!allBalanceIssuesIsAutofixable) options?.logger?.('Some balance issues is not autofixable');
|
||||
|
||||
if (!allBalanceIssuesIsAutofixable || (options !== undefined && !options.autoApprove)) {
|
||||
throw new Error(`Balance issues: ${balanceIssues.map((issue, i) => `${i + 1}. ${issue.message}`).join('\n')}`);
|
||||
}
|
||||
|
||||
await autofixableBalanceIssues.reduce(async (promise, item) => {
|
||||
await promise;
|
||||
return fixBalanceIssue(item);
|
||||
}, Promise.resolve());
|
||||
|
||||
const signedOrder = await crypt.signOrder(
|
||||
baseAssetAddress,
|
||||
quoteAssetAddress,
|
||||
swapInfo.orderInfo.side,
|
||||
safePriceWithAppliedPrecision.toString(),
|
||||
swapInfo.orderInfo.amount,
|
||||
totalFeeInFeeAsset,
|
||||
walletAddress,
|
||||
matcherAddress,
|
||||
feeAssetAddress,
|
||||
false,
|
||||
signer,
|
||||
chainId,
|
||||
);
|
||||
const orderIsOk = await exchangeContract.validateOrder(signedOrder);
|
||||
if (!orderIsOk) throw new Error('Order is not valid');
|
||||
|
||||
const { orderId } = await orionAggregator.placeOrder(signedOrder, false);
|
||||
return {
|
||||
through: 'aggregator',
|
||||
id: orderId,
|
||||
};
|
||||
}
|
||||
494
src/abis/CustomStakingReward.json
Normal file
494
src/abis/CustomStakingReward.json
Normal file
@@ -0,0 +1,494 @@
|
||||
[
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "previousOwner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "newOwner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "OwnershipTransferred",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "reward",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "RewardAdded",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "user",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "reward",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "RewardPaid",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "user",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Staked",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "user",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Withdrawn",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "_balances",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "account",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "balanceOf",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "account",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "earned",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "asset",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "emergencyAssetWithdrawal",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "exit",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "getReward",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "_stakingToken",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "_rewardsToken",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "_owner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "initialize",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "lastTimeRewardApplicable",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "lastUpdateTime",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "_reward",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "_rewardsDuration",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "notifyRewardAmount",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "owner",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "periodFinish",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "renounceOwnership",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "rewardPerToken",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "rewardPerTokenStored",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "rewardRate",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "rewards",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "rewardsDuration",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "rewardsToken",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "contract IERC20",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "stake",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "to",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "stakeTo",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "deadline",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint8",
|
||||
"name": "v",
|
||||
"type": "uint8"
|
||||
},
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "r",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "s",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"name": "stakeWithPermit",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "stakingToken",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "contract IERC20",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "totalSupply",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "newOwner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "transferOwnership",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "userRewardPerTokenPaid",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "withdraw",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
}
|
||||
]
|
||||
222
src/abis/ERC20.json
Normal file
222
src/abis/ERC20.json
Normal file
@@ -0,0 +1,222 @@
|
||||
[
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "name",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_spender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "approve",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "totalSupply",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_from",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "transferFrom",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "decimals",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint8"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_owner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "balanceOf",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "balance",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "symbol",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "transfer",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "_owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"name": "_spender",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "allowance",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"payable": true,
|
||||
"stateMutability": "payable",
|
||||
"type": "fallback"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "owner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "spender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Approval",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "from",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"name": "to",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"name": "value",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Transfer",
|
||||
"type": "event"
|
||||
}
|
||||
]
|
||||
1687
src/abis/Exchange.json
Normal file
1687
src/abis/Exchange.json
Normal file
File diff suppressed because it is too large
Load Diff
524
src/abis/IDOCollector.json
Normal file
524
src/abis/IDOCollector.json
Normal file
@@ -0,0 +1,524 @@
|
||||
[
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "bytes32",
|
||||
"name": "role",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "bytes32",
|
||||
"name": "previousAdminRole",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "bytes32",
|
||||
"name": "newAdminRole",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"name": "RoleAdminChanged",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "bytes32",
|
||||
"name": "role",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "account",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "sender",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "RoleGranted",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "bytes32",
|
||||
"name": "role",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "account",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "sender",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "RoleRevoked",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "address",
|
||||
"name": "receiver",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "time",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "TokensClaimed",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "address",
|
||||
"name": "participant",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "time",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "UserParticipated",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "DEFAULT_ADMIN_ROLE",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "ORNToken",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "OWNER_ROLE",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "_owner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "addOwner",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "allocation",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "claimTokens",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "asset",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "wallet",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "emergencyAssetWithdrawal",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "finishTime",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint32",
|
||||
"name": "",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "role",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"name": "getRoleAdmin",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "role",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "index",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "getRoleMember",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "role",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"name": "getRoleMemberCount",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "role",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "account",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "grantRole",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "role",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "account",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "hasRole",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "bool",
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "idoToken",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "initialize",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "participate",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "role",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "account",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "renounceRole",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "role",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "account",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "revokeRole",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "_ornToken",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "_idoToken",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint32",
|
||||
"name": "_startTime",
|
||||
"type": "uint32"
|
||||
},
|
||||
{
|
||||
"internalType": "uint32",
|
||||
"name": "_finishTime",
|
||||
"type": "uint32"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "_allocation",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint32",
|
||||
"name": "_startClaimTime",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"name": "setIDOParams",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "bool",
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "startClaimTime",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint32",
|
||||
"name": "",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "startTime",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint32",
|
||||
"name": "",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "bytes4",
|
||||
"name": "interfaceId",
|
||||
"type": "bytes4"
|
||||
}
|
||||
],
|
||||
"name": "supportsInterface",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "bool",
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "totalORN",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "userBalances",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
}
|
||||
]
|
||||
362
src/abis/IDODistributor.json
Normal file
362
src/abis/IDODistributor.json
Normal file
@@ -0,0 +1,362 @@
|
||||
[
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "NewTokenDistribution",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "previousOwner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "newOwner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "OwnershipTransferred",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "address",
|
||||
"name": "receiver",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint192",
|
||||
"name": "amount",
|
||||
"type": "uint192"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "bytes32",
|
||||
"name": "orderHash",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"name": "TokensClaimed",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "accrued",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "sender",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "receiver",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "asset",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint192",
|
||||
"name": "amount",
|
||||
"type": "uint192"
|
||||
},
|
||||
{
|
||||
"internalType": "uint64",
|
||||
"name": "startTime",
|
||||
"type": "uint64"
|
||||
},
|
||||
{
|
||||
"internalType": "bytes",
|
||||
"name": "signature",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"internalType": "struct IDOAccruedDistributor.Order",
|
||||
"name": "order_",
|
||||
"type": "tuple"
|
||||
}
|
||||
],
|
||||
"name": "claimTokens",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"name": "claimedOrders",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "bool",
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint32",
|
||||
"name": "finishClaimTime_",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"name": "distibuteNewTokens",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "asset",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "emergencyAssetWithdrawal",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "finishClaimTime",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "idoToken",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "idoToken_",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "verifier_",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint32",
|
||||
"name": "startClaimTime_",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"name": "initialize",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "lastTimeRewardApplicable",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "owner",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "payouts",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "renounceOwnership",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "startClaimTime",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint32",
|
||||
"name": "",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "term",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "tokensAllocation",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "newOwner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "transferOwnership",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "idoToken_",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "verifier_",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint32",
|
||||
"name": "startClaimTime_",
|
||||
"type": "uint32"
|
||||
}
|
||||
],
|
||||
"name": "updateParams",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "verifier",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
}
|
||||
]
|
||||
1
src/abis/IUniswapV2Pair.json
Normal file
1
src/abis/IUniswapV2Pair.json
Normal file
File diff suppressed because one or more lines are too long
1
src/abis/IUniswapV2Router.json
Normal file
1
src/abis/IUniswapV2Router.json
Normal file
File diff suppressed because one or more lines are too long
159
src/abis/LiquidityMigrator.json
Normal file
159
src/abis/LiquidityMigrator.json
Normal file
@@ -0,0 +1,159 @@
|
||||
[
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "previousOwner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "newOwner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "OwnershipTransferred",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "WETH9",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "contract IWETH9",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "exchange",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "contract IExchangeWithAtomic",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "exchangeAllowances",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "bool",
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "_exchange",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "_WETH9",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "initialize",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "pairAddress",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "tokensToMigrate",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "secretHash0",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "secretHash1",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"internalType": "uint64",
|
||||
"name": "expiration",
|
||||
"type": "uint64"
|
||||
},
|
||||
{
|
||||
"internalType": "uint24",
|
||||
"name": "targetChainId",
|
||||
"type": "uint24"
|
||||
}
|
||||
],
|
||||
"name": "migrate",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "owner",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "renounceOwnership",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "newOwner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "transferOwnership",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"stateMutability": "payable",
|
||||
"type": "receive"
|
||||
}
|
||||
]
|
||||
851
src/abis/OrionGovernance.json
Normal file
851
src/abis/OrionGovernance.json
Normal file
@@ -0,0 +1,851 @@
|
||||
[
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "previousOwner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "newOwner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "OwnershipTransferred",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "reward",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "RewardAdded",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "user",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "reward",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "RewardPaid",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "user",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Staked",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "user",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Withdrawn",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "user",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint56",
|
||||
"name": "lock_increase_amount",
|
||||
"type": "uint56"
|
||||
}
|
||||
],
|
||||
"name": "acceptLock",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "user",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint56",
|
||||
"name": "new_lock_amount",
|
||||
"type": "uint56"
|
||||
}
|
||||
],
|
||||
"name": "acceptNewLockAmount",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "user",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint56",
|
||||
"name": "lock_decrease_amount",
|
||||
"type": "uint56"
|
||||
}
|
||||
],
|
||||
"name": "acceptUnlock",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "balances_",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint56",
|
||||
"name": "balance",
|
||||
"type": "uint56"
|
||||
},
|
||||
{
|
||||
"internalType": "uint56",
|
||||
"name": "locked_balance",
|
||||
"type": "uint56"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "basic_fee_percent",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint16",
|
||||
"name": "",
|
||||
"type": "uint16"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint56",
|
||||
"name": "burn_size",
|
||||
"type": "uint56"
|
||||
}
|
||||
],
|
||||
"name": "burn",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "burn_vote_end_",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint64",
|
||||
"name": "",
|
||||
"type": "uint64"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "account",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "earned",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "asset",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "emergencyAssetWithdrawal",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "exit",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "extra_fee_percent",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint16",
|
||||
"name": "",
|
||||
"type": "uint16"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "extra_fee_seconds",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint64",
|
||||
"name": "",
|
||||
"type": "uint64"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "fee_total",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint56",
|
||||
"name": "",
|
||||
"type": "uint56"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "user",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "getAvailableWithdrawBalance",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint56",
|
||||
"name": "",
|
||||
"type": "uint56"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "user",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "getBalance",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint56",
|
||||
"name": "",
|
||||
"type": "uint56"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "user",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "getLockedBalance",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint56",
|
||||
"name": "",
|
||||
"type": "uint56"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "getReward",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "getRewardForDuration",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "getTotalBalance",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint56",
|
||||
"name": "",
|
||||
"type": "uint56"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "user",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "getTotalLockedBalance",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint56",
|
||||
"name": "",
|
||||
"type": "uint56"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "wallet",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "getVaults",
|
||||
"outputs": [
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"internalType": "uint56",
|
||||
"name": "amount",
|
||||
"type": "uint56"
|
||||
},
|
||||
{
|
||||
"internalType": "uint64",
|
||||
"name": "created_time",
|
||||
"type": "uint64"
|
||||
}
|
||||
],
|
||||
"internalType": "struct OrionGovernance.UserVault[]",
|
||||
"name": "",
|
||||
"type": "tuple[]"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "staking_token",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "initialize",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "lastTimeRewardApplicable",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "lastUpdateTime",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "reward",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "_rewardsDuration",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "notifyRewardAmount",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "owner",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "periodFinish",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "renounceOwnership",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "rewardPerToken",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "rewardPerTokenStored",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "rewardRate",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "rewards",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "rewardsDuration",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint64",
|
||||
"name": "burn_vote_end",
|
||||
"type": "uint64"
|
||||
}
|
||||
],
|
||||
"name": "setBurnVoteEnd",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint16",
|
||||
"name": "extra_fee_percent_",
|
||||
"type": "uint16"
|
||||
},
|
||||
{
|
||||
"internalType": "uint64",
|
||||
"name": "extra_fee_seconds_",
|
||||
"type": "uint64"
|
||||
},
|
||||
{
|
||||
"internalType": "uint16",
|
||||
"name": "basic_fee_percent_",
|
||||
"type": "uint16"
|
||||
}
|
||||
],
|
||||
"name": "setVaultParameters",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "voting_contract_address",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "setVotingContractAddress",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint56",
|
||||
"name": "adding_amount",
|
||||
"type": "uint56"
|
||||
}
|
||||
],
|
||||
"name": "stake",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "staking_token_",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "contract IERC20",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "total_balance_",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint56",
|
||||
"name": "",
|
||||
"type": "uint56"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "total_votes_burn_",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint56",
|
||||
"name": "",
|
||||
"type": "uint56"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "total_votes_dont_burn_",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint56",
|
||||
"name": "",
|
||||
"type": "uint56"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "newOwner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "transferOwnership",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "userRewardPerTokenPaid",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "user_burn_votes_",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint56",
|
||||
"name": "",
|
||||
"type": "uint56"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "index",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "vaultWithdraw",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "vaults_",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint56",
|
||||
"name": "amount",
|
||||
"type": "uint56"
|
||||
},
|
||||
{
|
||||
"internalType": "uint64",
|
||||
"name": "created_time",
|
||||
"type": "uint64"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint56",
|
||||
"name": "voting_amount",
|
||||
"type": "uint56"
|
||||
},
|
||||
{
|
||||
"internalType": "bool",
|
||||
"name": "vote_for_burn",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"name": "voteBurn",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "voteBurnAvailable",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "bool",
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "voting_contract_address_",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint56",
|
||||
"name": "removing_amount",
|
||||
"type": "uint56"
|
||||
}
|
||||
],
|
||||
"name": "withdraw",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
}
|
||||
]
|
||||
1
src/abis/OrionMigrator.json
Normal file
1
src/abis/OrionMigrator.json
Normal file
@@ -0,0 +1 @@
|
||||
[{"inputs":[{"internalType":"address","name":"_pair","type":"address"},{"internalType":"address","name":"_router","type":"address"},{"internalType":"address","name":"_WETH9","type":"address"},{"internalType":"address","name":"_stakingRewards","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount0V1","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1V1","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount0V2","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1V2","type":"uint256"}],"name":"TestCalc","type":"event"},{"inputs":[{"internalType":"uint256","name":"tokensToMigrate","type":"uint256"},{"internalType":"uint256","name":"amount0Min","type":"uint256"},{"internalType":"uint256","name":"amount1Min","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"migrate","outputs":[],"stateMutability":"nonpayable","type":"function"}]
|
||||
1
src/abis/OrionPoolV2Factory.json
Normal file
1
src/abis/OrionPoolV2Factory.json
Normal file
@@ -0,0 +1 @@
|
||||
[{"inputs":[{"internalType":"address","name":"_feeToSetter","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token0","type":"address"},{"indexed":true,"internalType":"address","name":"token1","type":"address"},{"indexed":false,"internalType":"address","name":"pair","type":"address"},{"indexed":false,"internalType":"uint256","name":"","type":"uint256"}],"name":"PairCreated","type":"event"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"allPairs","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"allPairsLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"value","type":"bytes32"}],"name":"bytes32ToString","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"}],"name":"createPair","outputs":[{"internalType":"address","name":"pair","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feeTo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeToSetter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"getPair","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_feeTo","type":"address"}],"name":"setFeeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeToSetter","type":"address"}],"name":"setFeeToSetter","outputs":[],"stateMutability":"nonpayable","type":"function"}]
|
||||
507
src/abis/OrionStakingReward.json
Normal file
507
src/abis/OrionStakingReward.json
Normal file
@@ -0,0 +1,507 @@
|
||||
[
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "previousOwner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "newOwner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "OwnershipTransferred",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "reward",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "RewardAdded",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "user",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "reward",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "RewardPaid",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "user",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Staked",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "balances_account",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "rewardPerToken",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "userRewardPerTokenPaid_account",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "rewards_account",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "voting_contract_getPoolRewards",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "TestEarnedCalc",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "_rewardPerToken",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "TestRewardPerToken",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "_rewardPerTokenStored",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "_voting_pool_accumulator_stored",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "TestUpdateReward",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "rewards",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "userRewardPerTokenPaid",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "TestUpdateRewardUser",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "user",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Withdrawn",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "_balances",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "account",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "balanceOf",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "account",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "earned",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "asset",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "emergencyAssetWithdrawal",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "exit",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "getReward",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "_stakingToken",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "voting_contract_address",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "initialize",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "owner",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "renounceOwnership",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "rewardPerToken",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "rewardPerTokenStored",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "rewards",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "stake",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "to",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "stakeTo",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "deadline",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint8",
|
||||
"name": "v",
|
||||
"type": "uint8"
|
||||
},
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "r",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "s",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"name": "stakeWithPermit",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "stakingToken",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "contract IERC20",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "totalSupply",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "newOwner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "transferOwnership",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "userRewardPerTokenPaid",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "voting_contract_",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "contract IOrionVoting",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "voting_pool_accumulator_stored_",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "withdraw",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
}
|
||||
]
|
||||
1
src/abis/OrionVoting.json
Normal file
1
src/abis/OrionVoting.json
Normal file
@@ -0,0 +1 @@
|
||||
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[{"internalType":"address","name":"poolAddress","type":"address"},{"internalType":"uint56","name":"amount","type":"uint56"}],"name":"cease","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint56","name":"amount","type":"uint56"},{"internalType":"address","name":"to","type":"address"}],"name":"claimRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pool_address","type":"address"}],"name":"getPoolRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRewardPerVotingToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"rewards_token","type":"address"},{"internalType":"address","name":"governance_contract_address","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"pool_states_","outputs":[{"internalType":"uint8","name":"state","type":"uint8"},{"internalType":"uint56","name":"votes","type":"uint56"},{"internalType":"uint256","name":"last_acc_reward_per_voting_token","type":"uint256"},{"internalType":"uint256","name":"acc_reward","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"reward_rate_","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewards_token_","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pool_address","type":"address"},{"internalType":"uint8","name":"new_state","type":"uint8"}],"name":"setPoolState","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"rewards","type":"uint64"},{"internalType":"uint64","name":"duration","type":"uint64"}],"name":"setRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint56","name":"","type":"uint56"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"total_supply_","outputs":[{"internalType":"uint56","name":"","type":"uint56"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"user_votes_","outputs":[{"internalType":"uint56","name":"voted_amount","type":"uint56"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"poolAddress","type":"address"},{"internalType":"uint56","name":"amount","type":"uint56"}],"name":"vote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pool_address","type":"address"}],"name":"votes","outputs":[{"internalType":"uint56","name":"","type":"uint56"}],"stateMutability":"view","type":"function"}]
|
||||
273
src/abis/PriceOracle.json
Normal file
273
src/abis/PriceOracle.json
Normal file
@@ -0,0 +1,273 @@
|
||||
[
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "publicKey",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "_baseAsset",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "constructor"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "previousOwner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "newOwner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "OwnershipTransferred",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "assetPrices",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint64",
|
||||
"name": "price",
|
||||
"type": "uint64"
|
||||
},
|
||||
{
|
||||
"internalType": "uint64",
|
||||
"name": "timestamp",
|
||||
"type": "uint64"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "baseAsset",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "chainLinkETHAggregator",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address[]",
|
||||
"name": "added",
|
||||
"type": "address[]"
|
||||
},
|
||||
{
|
||||
"internalType": "address[]",
|
||||
"name": "removed",
|
||||
"type": "address[]"
|
||||
}
|
||||
],
|
||||
"name": "changePriceProviderAuthorization",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address[]",
|
||||
"name": "assets",
|
||||
"type": "address[]"
|
||||
}
|
||||
],
|
||||
"name": "getChainLinkPriceData",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address[]",
|
||||
"name": "assetAddresses",
|
||||
"type": "address[]"
|
||||
}
|
||||
],
|
||||
"name": "givePrices",
|
||||
"outputs": [
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"internalType": "uint64",
|
||||
"name": "price",
|
||||
"type": "uint64"
|
||||
},
|
||||
{
|
||||
"internalType": "uint64",
|
||||
"name": "timestamp",
|
||||
"type": "uint64"
|
||||
}
|
||||
],
|
||||
"internalType": "struct PriceOracle.PriceDataOut[]",
|
||||
"name": "",
|
||||
"type": "tuple[]"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "oraclePublicKey",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "owner",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "priceProviderAuthorization",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "bool",
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"internalType": "address[]",
|
||||
"name": "assetAddresses",
|
||||
"type": "address[]"
|
||||
},
|
||||
{
|
||||
"internalType": "uint64[]",
|
||||
"name": "prices",
|
||||
"type": "uint64[]"
|
||||
},
|
||||
{
|
||||
"internalType": "uint64",
|
||||
"name": "timestamp",
|
||||
"type": "uint64"
|
||||
},
|
||||
{
|
||||
"internalType": "bytes",
|
||||
"name": "signature",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"internalType": "struct PriceOracle.Prices",
|
||||
"name": "priceFeed",
|
||||
"type": "tuple"
|
||||
}
|
||||
],
|
||||
"name": "provideDataAddressAuthorization",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "renounceOwnership",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address[]",
|
||||
"name": "assets",
|
||||
"type": "address[]"
|
||||
},
|
||||
{
|
||||
"internalType": "address[]",
|
||||
"name": "aggregatorAddresses",
|
||||
"type": "address[]"
|
||||
}
|
||||
],
|
||||
"name": "setChainLinkAggregators",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "newOwner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "transferOwnership",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
}
|
||||
]
|
||||
1
src/abis/StakingRewardsWithLongTermBonus.json
Normal file
1
src/abis/StakingRewardsWithLongTermBonus.json
Normal file
File diff suppressed because one or more lines are too long
58
src/config/chains.json
Normal file
58
src/config/chains.json
Normal file
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"0x1": {
|
||||
"chainId": "0x1",
|
||||
"explorer": "https://etherscan.io/",
|
||||
"label": "Ethereum",
|
||||
"code": "eth",
|
||||
"rpc": "https://trade.orionprotocol.io/rpc",
|
||||
"baseCurrencyName": "ETH"
|
||||
},
|
||||
"0x38": {
|
||||
"chainId": "0x38",
|
||||
"explorer": "https://bscscan.com/",
|
||||
"label": "Binance Smart Chain",
|
||||
"code": "bsc",
|
||||
"rpc": "https://bsc-dataseed.binance.org/",
|
||||
"baseCurrencyName": "BNB"
|
||||
},
|
||||
"0x61": {
|
||||
"chainId": "0x61",
|
||||
"explorer": "https://testnet.bscscan.com/",
|
||||
"label": "Binance Smart Chain Testnet",
|
||||
"code": "bsc",
|
||||
"rpc": "https://bsc-stage.node.orionprotocol.io/",
|
||||
"baseCurrencyName": "BNB"
|
||||
},
|
||||
"0x3": {
|
||||
"chainId": "0x3",
|
||||
"explorer": "https://ropsten.etherscan.io/",
|
||||
"label": "Ropsten",
|
||||
"code": "eth",
|
||||
"rpc": "https://testing.orionprotocol.io/eth-ropsten/rpc",
|
||||
"baseCurrencyName": "ETH"
|
||||
},
|
||||
"0xfa2": {
|
||||
"chainId": "0xfa2",
|
||||
"explorer": "https://testnet.ftmscan.com/",
|
||||
"label": "Fantom Testnet",
|
||||
"code": "ftm",
|
||||
"rpc": "https://testing.orionprotocol.io/ftm-testnet/rpc",
|
||||
"baseCurrencyName": "FTM"
|
||||
},
|
||||
"0xfa": {
|
||||
"chainId": "0xfa",
|
||||
"explorer": "https://ftmscan.com/",
|
||||
"label": "Fantom",
|
||||
"code": "ftm",
|
||||
"rpc": "https://rpcapi.fantom.network/",
|
||||
"baseCurrencyName": "FTM"
|
||||
},
|
||||
"0x0": {
|
||||
"chainId": "0x0",
|
||||
"explorer": "https://brokenscan.io/",
|
||||
"label": "BrokenChain",
|
||||
"code": "bkn",
|
||||
"rpc": "https://brokenscan.io/rpc",
|
||||
"baseCurrencyName": "BKN"
|
||||
}
|
||||
}
|
||||
5
src/config/eip712DomainData.json
Normal file
5
src/config/eip712DomainData.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "Orion Exchange",
|
||||
"version": "1",
|
||||
"salt": "0xf2d857f4a3edcb9b78b4d503bfe733db1e3f6cdc2b7971ee739626c97e86a557"
|
||||
}
|
||||
69
src/config/envs.json
Normal file
69
src/config/envs.json
Normal file
@@ -0,0 +1,69 @@
|
||||
{
|
||||
"production": {
|
||||
"networks": {
|
||||
"0x1": {
|
||||
"api": "trade.orionprotocol.io",
|
||||
"liquidityMigratorAddress": "0x23a1820a47BcD022E29f6058a5FD224242F50D1A"
|
||||
},
|
||||
"0x38": {
|
||||
"api": "trade-exp.orionprotocol.io"
|
||||
}
|
||||
}
|
||||
},
|
||||
"testing": {
|
||||
"networks": {
|
||||
"0x61": {
|
||||
"api": "testing.orionprotocol.io/bsc-testnet",
|
||||
"liquidityMigratorAddress": "0x01b10dd12478C88A5E18e2707E729906bC25CfF6"
|
||||
},
|
||||
"0x3": {
|
||||
"api": "testing.orionprotocol.io/eth-ropsten",
|
||||
"liquidityMigratorAddress": "0x36969a25622AE31bA9946e0c8151f0dc08b3A1c8"
|
||||
},
|
||||
"0xfa2": {
|
||||
"api": "testing.orionprotocol.io/ftm-testnet"
|
||||
}
|
||||
}
|
||||
},
|
||||
"staging": {
|
||||
"networks": {
|
||||
"0x1": {
|
||||
"api": "staging.orionprotocol.io"
|
||||
},
|
||||
"0x38": {
|
||||
"api": "staging-bsc.orionprotocol.io"
|
||||
},
|
||||
"0xfa": {
|
||||
"api": "staging-ftm.orionprotocol.io"
|
||||
}
|
||||
}
|
||||
},
|
||||
"broken": {
|
||||
"networks": {
|
||||
"0x0": {
|
||||
"api": "broken0.orionprotocol.io/everything-is-fine/this-url-was-created-for-tests-of-a-partially-broken-environment"
|
||||
},
|
||||
"0x61": {
|
||||
"api": "broken1.orionprotocol.io/everything-is-fine/this-url-was-created-for-tests-of-a-partially-broken-environment"
|
||||
}
|
||||
}
|
||||
},
|
||||
"partially-broken": {
|
||||
"networks": {
|
||||
"0x61": {
|
||||
"api": "testing.orionprotocol.io/bsc-testnet",
|
||||
"liquidityMigratorAddress": "0x01b10dd12478C88A5E18e2707E729906bC25CfF6"
|
||||
},
|
||||
"0x3": {
|
||||
"api": "testing.orionprotocol.io/eth-ropsten",
|
||||
"liquidityMigratorAddress": "0x36969a25622AE31bA9946e0c8151f0dc08b3A1c8"
|
||||
},
|
||||
"0xfa2": {
|
||||
"api": "testing.orionprotocol.io/ftm-testnet"
|
||||
},
|
||||
"0x0": {
|
||||
"api": "broken.orionprotocol.io/everything-is-fine/this-url-was-created-for-tests-of-a-partially-broken-environment"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
13
src/config/index.ts
Normal file
13
src/config/index.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import jsonChains from './chains.json';
|
||||
import jsonEnvs from './envs.json';
|
||||
import { pureEnvSchema, pureChainInfoSchema } from './schemas';
|
||||
|
||||
const chains = pureChainInfoSchema.parse(jsonChains);
|
||||
const envs = pureEnvSchema.parse(jsonEnvs);
|
||||
|
||||
export {
|
||||
chains,
|
||||
envs,
|
||||
};
|
||||
|
||||
export * as schemas from './schemas';
|
||||
16
src/config/schemas/eip712DomainSchema.ts
Normal file
16
src/config/schemas/eip712DomainSchema.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
const eip712DomainSchema = z.object({
|
||||
name: z.string(),
|
||||
version: z.string(),
|
||||
chainId: z.string(),
|
||||
verifyingContract: z.string(),
|
||||
salt: z.string(),
|
||||
})
|
||||
.partial()
|
||||
.refine(
|
||||
(data) => Object.keys(data).length > 0,
|
||||
'At least one property should be filled in.',
|
||||
);
|
||||
|
||||
export default eip712DomainSchema;
|
||||
3
src/config/schemas/index.ts
Normal file
3
src/config/schemas/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export { default as eip712DomainSchema } from './eip712DomainSchema';
|
||||
export * from './pureEnvSchema';
|
||||
export * from './pureChainSchema';
|
||||
16
src/config/schemas/pureChainSchema.ts
Normal file
16
src/config/schemas/pureChainSchema.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { z } from 'zod';
|
||||
import { SupportedChainId } from '../../types';
|
||||
|
||||
export const pureChainInfoPayloadSchema = z.object({
|
||||
chainId: z.nativeEnum(SupportedChainId),
|
||||
label: z.string(),
|
||||
code: z.string(),
|
||||
explorer: z.string(),
|
||||
rpc: z.string(),
|
||||
baseCurrencyName: z.string(),
|
||||
});
|
||||
|
||||
export const pureChainInfoSchema = z.record(
|
||||
z.nativeEnum(SupportedChainId),
|
||||
pureChainInfoPayloadSchema,
|
||||
);
|
||||
18
src/config/schemas/pureEnvSchema.ts
Normal file
18
src/config/schemas/pureEnvSchema.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { z } from 'zod';
|
||||
import { SupportedChainId } from '../../types';
|
||||
|
||||
export const pureEnvPayloadSchema = z.object({
|
||||
networks: z.record(
|
||||
z.nativeEnum(SupportedChainId),
|
||||
z.object({
|
||||
api: z.string(),
|
||||
rpc: z.string().optional(),
|
||||
liquidityMigratorAddress: z.string().optional(),
|
||||
}),
|
||||
),
|
||||
});
|
||||
|
||||
export const pureEnvSchema = z.record(
|
||||
z.string(),
|
||||
pureEnvPayloadSchema,
|
||||
);
|
||||
8
src/constants/cancelOrderTypes.ts
Normal file
8
src/constants/cancelOrderTypes.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
const CANCEL_ORDER_TYPES = {
|
||||
DeleteOrder: [
|
||||
{ name: 'senderAddress', type: 'address' },
|
||||
{ name: 'id', type: 'string' },
|
||||
],
|
||||
};
|
||||
|
||||
export default CANCEL_ORDER_TYPES;
|
||||
4
src/constants/chains.ts
Normal file
4
src/constants/chains.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import { SupportedChainId } from '../types';
|
||||
|
||||
export const developmentChains = [SupportedChainId.BSC_TESTNET, SupportedChainId.ROPSTEN, SupportedChainId.FANTOM_TESTNET];
|
||||
export const productionChains = [SupportedChainId.MAINNET, SupportedChainId.BSC, SupportedChainId.FANTOM_OPERA];
|
||||
30
src/constants/gasLimits.ts
Normal file
30
src/constants/gasLimits.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
export const DEPOSIT_ETH_GAS_LIMIT = 70000;
|
||||
export const DEPOSIT_ERC20_GAS_LIMIT = 150000;
|
||||
export const WITHDRAW_GAS_LIMIT = DEPOSIT_ERC20_GAS_LIMIT;
|
||||
export const APPROVE_ERC20_GAS_LIMIT = 70000;
|
||||
export const STAKE_ERC20_GAS_LIMIT = 150000;
|
||||
export const VOTE_ERC20_GAS_LIMIT = 150000;
|
||||
export const FILL_ORDERS_GAS_LIMIT = 220000;
|
||||
export const SWAP_THROUGH_ORION_POOL_GAS_LIMIT = 600000;
|
||||
export const ADD_LIQUIDITY_GAS_LIMIT = 600000;
|
||||
export const FARMING_STAKE_GAS_LIMIT = 350000;
|
||||
export const FARMING_CLAIM_GAS_LIMIT = 350000;
|
||||
export const FARMING_EXIT_GAS_LIMIT = 500000;
|
||||
export const FARMING_WITHDRAW_GAS_LIMIT = 350000;
|
||||
export const GOVERNANCE_GET_REWARD_GAS_LIMIT = 250000;
|
||||
export const GOVERNANCE_STAKE_GAS_LIMIT = 300000;
|
||||
export const GOVERNANCE_UNSTAKE_GAS_LIMIT = 250000;
|
||||
export const GOVERNANCE_VOTE_GAS_LIMIT = 200000;
|
||||
export const MIGRATE_GAS_LIMIT = 800000;
|
||||
export const LOCKATOMIC_GAS_LIMIT = 200000;
|
||||
export const REDEEMATOMIC_GAS_LIMIT = 200000;
|
||||
export const LIQUIDITY_MIGRATE_GAS_LIMIT = 600000;
|
||||
|
||||
export const DEFAULT_GAS_LIMIT = 700000;
|
||||
|
||||
export const TOKEN_EXCEPTIONS: Record<string, Record<string, number>> = {
|
||||
CUMMIES: {
|
||||
deposit: 300000,
|
||||
withdraw: 300000,
|
||||
},
|
||||
};
|
||||
8
src/constants/index.ts
Normal file
8
src/constants/index.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export { default as cancelOrderTypes } from './cancelOrderTypes';
|
||||
export { default as orderStatuses } from './orderStatuses';
|
||||
export { default as orderTypes } from './orderTypes';
|
||||
export { default as subOrderStatuses } from './subOrderStatuses';
|
||||
|
||||
export * from './chains';
|
||||
export * from './precisions';
|
||||
export * from './gasLimits';
|
||||
9
src/constants/orderStatuses.ts
Normal file
9
src/constants/orderStatuses.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import subOrderStatuses from './subOrderStatuses';
|
||||
|
||||
// https://github.com/orionprotocol/orion-aggregator/blob/develop/src/main/java/io/orionprotocol/aggregator/model/order/status/OrderStatus.java
|
||||
const orderStatuses = [
|
||||
...subOrderStatuses,
|
||||
'ROUTING', // order got sub orders, but not all of them have status ACCEPTED
|
||||
] as const;
|
||||
|
||||
export default orderStatuses;
|
||||
17
src/constants/orderTypes.ts
Normal file
17
src/constants/orderTypes.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
const ORDER_TYPES = {
|
||||
Order: [
|
||||
{ name: 'senderAddress', type: 'address' },
|
||||
{ name: 'matcherAddress', type: 'address' },
|
||||
{ name: 'baseAsset', type: 'address' },
|
||||
{ name: 'quoteAsset', type: 'address' },
|
||||
{ name: 'matcherFeeAsset', type: 'address' },
|
||||
{ name: 'amount', type: 'uint64' },
|
||||
{ name: 'price', type: 'uint64' },
|
||||
{ name: 'matcherFee', type: 'uint64' },
|
||||
{ name: 'nonce', type: 'uint64' },
|
||||
{ name: 'expiration', type: 'uint64' },
|
||||
{ name: 'buySide', type: 'uint8' },
|
||||
],
|
||||
};
|
||||
|
||||
export default ORDER_TYPES;
|
||||
2
src/constants/precisions.ts
Normal file
2
src/constants/precisions.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export const INTERNAL_ORION_PRECISION = 8;
|
||||
export const NATIVE_CURRENCY_PRECISION = 18;
|
||||
15
src/constants/subOrderStatuses.ts
Normal file
15
src/constants/subOrderStatuses.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
// https://github.com/orionprotocol/orion-aggregator/blob/develop/src/main/java/io/orionprotocol/aggregator/model/order/status/SubOrderStatus.java
|
||||
const subOrderStatuses = [
|
||||
'NEW', // created, wasn't added to IOB or wasn't accepted by the broker
|
||||
'ACCEPTED', // added to IOB or accepted by the broker
|
||||
'PARTIALLY_FILLED', // partially filled
|
||||
'FILLED', // fully filled
|
||||
'TX_PENDING', // sub order was filled and at least one of its trades is pending
|
||||
'CANCELED', // canceled by user or by expiration
|
||||
'REJECTED', // rejected by broker
|
||||
'FAILED', // at least one trade failed
|
||||
'SETTLED', // all trades successfully settled
|
||||
'NOT_FOUND', // broker not processed sub order yet
|
||||
] as const;
|
||||
|
||||
export default subOrderStatuses;
|
||||
151
src/crypt.ts
Normal file
151
src/crypt.ts
Normal file
@@ -0,0 +1,151 @@
|
||||
/* eslint-disable no-underscore-dangle */
|
||||
import { TypedDataSigner } from '@ethersproject/abstract-signer';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import { ethers } from 'ethers';
|
||||
import {
|
||||
CancelOrderRequest, Order, SignedCancelOrderRequest, SignedOrder, SupportedChainId,
|
||||
} from './types';
|
||||
import eip712DomainData from './config/eip712DomainData.json';
|
||||
import eip712DomainSchema from './config/schemas/eip712DomainSchema';
|
||||
import { hashOrder, normalizeNumber } from './utils';
|
||||
|
||||
import { INTERNAL_ORION_PRECISION } from './constants/precisions';
|
||||
import ORDER_TYPES from './constants/orderTypes';
|
||||
import CANCEL_ORDER_TYPES from './constants/cancelOrderTypes';
|
||||
import signOrderPersonal from './utils/signOrderPersonal';
|
||||
|
||||
const DEFAULT_EXPIRATION = 29 * 24 * 60 * 60 * 1000; // 29 days
|
||||
|
||||
type SignerWithTypedDataSign = ethers.Signer & TypedDataSigner;
|
||||
|
||||
const EIP712Domain = eip712DomainSchema.parse(eip712DomainData);
|
||||
const { arrayify, joinSignature, splitSignature } = ethers.utils;
|
||||
|
||||
/**
|
||||
* See {@link https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator}
|
||||
*/
|
||||
const getDomainData = (chainId: SupportedChainId) => ({
|
||||
...EIP712Domain,
|
||||
chainId,
|
||||
});
|
||||
|
||||
export const signOrder = async (
|
||||
baseAssetAddr: string,
|
||||
quoteAssetAddr: string,
|
||||
side: 'BUY' | 'SELL',
|
||||
price: BigNumber.Value,
|
||||
amount: BigNumber.Value,
|
||||
matcherFee: BigNumber.Value,
|
||||
senderAddress: string,
|
||||
matcherAddress: string,
|
||||
orionFeeAssetAddr: string,
|
||||
usePersonalSign: boolean,
|
||||
signer: ethers.Signer,
|
||||
chainId: SupportedChainId,
|
||||
) => {
|
||||
const nonce = Date.now();
|
||||
const expiration = nonce + DEFAULT_EXPIRATION;
|
||||
|
||||
const order: Order = {
|
||||
senderAddress,
|
||||
matcherAddress,
|
||||
baseAsset: baseAssetAddr,
|
||||
quoteAsset: quoteAssetAddr,
|
||||
matcherFeeAsset: orionFeeAssetAddr,
|
||||
amount: normalizeNumber(
|
||||
amount,
|
||||
INTERNAL_ORION_PRECISION,
|
||||
BigNumber.ROUND_FLOOR,
|
||||
).toNumber(),
|
||||
price: normalizeNumber(
|
||||
price,
|
||||
INTERNAL_ORION_PRECISION,
|
||||
BigNumber.ROUND_FLOOR,
|
||||
).toNumber(),
|
||||
matcherFee: normalizeNumber(
|
||||
matcherFee,
|
||||
INTERNAL_ORION_PRECISION,
|
||||
BigNumber.ROUND_CEIL, // ROUND_CEIL because we don't want get "not enough fee" error
|
||||
).toNumber(),
|
||||
nonce,
|
||||
expiration,
|
||||
buySide: side === 'BUY' ? 1 : 0,
|
||||
isPersonalSign: usePersonalSign,
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
||||
const typedDataSigner = signer as SignerWithTypedDataSign;
|
||||
|
||||
const signature = usePersonalSign
|
||||
? await signOrderPersonal(order, signer)
|
||||
: await typedDataSigner._signTypedData(
|
||||
getDomainData(chainId),
|
||||
ORDER_TYPES,
|
||||
order,
|
||||
);
|
||||
|
||||
// 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));
|
||||
|
||||
if (!fixedSignature) throw new Error("Can't sign order");
|
||||
|
||||
const signedOrder: SignedOrder = {
|
||||
...order,
|
||||
id: hashOrder(order),
|
||||
signature: fixedSignature,
|
||||
};
|
||||
return signedOrder;
|
||||
};
|
||||
|
||||
export const signCancelOrderPersonal = async (
|
||||
cancelOrderRequest: CancelOrderRequest,
|
||||
signer: ethers.Signer,
|
||||
) => {
|
||||
const types = ['string', 'string', 'address'];
|
||||
const message = ethers.utils.solidityKeccak256(
|
||||
types,
|
||||
['cancelOrder', cancelOrderRequest.id, cancelOrderRequest.senderAddress],
|
||||
);
|
||||
const signature = await signer.signMessage(arrayify(message));
|
||||
|
||||
// NOTE: metamask broke sig.v value and we fix it in next line
|
||||
return joinSignature(splitSignature(signature));
|
||||
};
|
||||
|
||||
export const signCancelOrder = async (
|
||||
senderAddress: string,
|
||||
id: string,
|
||||
usePersonalSign: boolean,
|
||||
signer: ethers.Signer,
|
||||
chainId: SupportedChainId,
|
||||
) => {
|
||||
const cancelOrderRequest: CancelOrderRequest = {
|
||||
id,
|
||||
senderAddress,
|
||||
isPersonalSign: usePersonalSign,
|
||||
};
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
||||
const typedDataSigner = signer as SignerWithTypedDataSign;
|
||||
|
||||
const signature = usePersonalSign
|
||||
? await signCancelOrderPersonal(cancelOrderRequest, signer)
|
||||
// https://docs.ethers.io/v5/api/signer/#Signer-signTypedData
|
||||
: await typedDataSigner._signTypedData(
|
||||
getDomainData(chainId),
|
||||
CANCEL_ORDER_TYPES,
|
||||
cancelOrderRequest,
|
||||
);
|
||||
|
||||
// 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));
|
||||
|
||||
if (!fixedSignature) throw new Error("Can't sign order cancel");
|
||||
|
||||
const signedCancelOrderReqeust: SignedCancelOrderRequest = {
|
||||
...cancelOrderRequest,
|
||||
signature: fixedSignature,
|
||||
};
|
||||
return signedCancelOrderReqeust;
|
||||
};
|
||||
109
src/entities/Exchange.ts
Normal file
109
src/entities/Exchange.ts
Normal file
@@ -0,0 +1,109 @@
|
||||
/* eslint-disable camelcase */
|
||||
import { Provider } from '@ethersproject/providers';
|
||||
import { BytesLike, ethers, Signer } from 'ethers';
|
||||
import {
|
||||
Exchange as ExchangeContract,
|
||||
Exchange__factory as ExchangeContract__factory,
|
||||
} from '../artifacts/contracts';
|
||||
import { LibAtomic } from '../artifacts/contracts/Exchange';
|
||||
import {
|
||||
DEPOSIT_ERC20_GAS_LIMIT, DEPOSIT_ETH_GAS_LIMIT, LOCKATOMIC_GAS_LIMIT,
|
||||
REDEEMATOMIC_GAS_LIMIT, SWAP_THROUGH_ORION_POOL_GAS_LIMIT, WITHDRAW_GAS_LIMIT,
|
||||
} from '../constants';
|
||||
import { SupportedChainId } from '../types';
|
||||
|
||||
export default class Exchange {
|
||||
chainId: SupportedChainId;
|
||||
|
||||
private exchangeContract: ExchangeContract;
|
||||
|
||||
constructor(chainId: SupportedChainId, signerOrProvider: Signer | Provider, address: string) {
|
||||
this.chainId = chainId;
|
||||
this.exchangeContract = ExchangeContract__factory.connect(address, signerOrProvider);
|
||||
}
|
||||
|
||||
swapThroughOrionPool(
|
||||
amount_spend: ethers.BigNumberish,
|
||||
amount_receive: ethers.BigNumberish,
|
||||
path: string[],
|
||||
is_exact_spend: boolean,
|
||||
value?: ethers.BigNumberish,
|
||||
) {
|
||||
return this.exchangeContract.populateTransaction.swapThroughOrionPool(
|
||||
amount_spend,
|
||||
amount_receive,
|
||||
path,
|
||||
is_exact_spend,
|
||||
{
|
||||
gasLimit: SWAP_THROUGH_ORION_POOL_GAS_LIMIT,
|
||||
value,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
depositNativeCurrency(value: ethers.BigNumberish) {
|
||||
return this.exchangeContract.populateTransaction.deposit({
|
||||
gasLimit: DEPOSIT_ETH_GAS_LIMIT,
|
||||
value,
|
||||
});
|
||||
}
|
||||
|
||||
depositERC20(assetAddress: string, amount: ethers.BigNumberish) {
|
||||
return this.exchangeContract.populateTransaction.depositAsset(
|
||||
assetAddress,
|
||||
amount,
|
||||
{
|
||||
gasLimit: DEPOSIT_ERC20_GAS_LIMIT,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
withdraw(assetAddress: string, amount: ethers.BigNumberish) {
|
||||
return this.exchangeContract.populateTransaction.withdraw(
|
||||
assetAddress,
|
||||
amount,
|
||||
{
|
||||
gasLimit: WITHDRAW_GAS_LIMIT,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
lockAtomic(lockOrder: LibAtomic.LockOrderStruct) {
|
||||
return this.exchangeContract.populateTransaction.lockAtomic(
|
||||
lockOrder,
|
||||
{
|
||||
gasLimit: LOCKATOMIC_GAS_LIMIT,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
redeemAtomic(redeemOrder: LibAtomic.RedeemOrderStruct, secret: BytesLike) {
|
||||
return this.exchangeContract.populateTransaction.redeemAtomic(
|
||||
redeemOrder,
|
||||
secret,
|
||||
{
|
||||
gasLimit: REDEEMATOMIC_GAS_LIMIT,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
redeem2Atomics(
|
||||
order1: LibAtomic.RedeemOrderStruct,
|
||||
secret1: BytesLike,
|
||||
order2: LibAtomic.RedeemOrderStruct,
|
||||
secret2: BytesLike,
|
||||
) {
|
||||
return this.exchangeContract.populateTransaction.redeem2Atomics(
|
||||
order1,
|
||||
secret1,
|
||||
order2,
|
||||
secret2,
|
||||
);
|
||||
}
|
||||
|
||||
refundAtomic(secretHash: BytesLike) {
|
||||
return this.exchangeContract.populateTransaction.refundAtomic(
|
||||
secretHash,
|
||||
);
|
||||
}
|
||||
}
|
||||
1
src/entities/index.ts
Normal file
1
src/entities/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { default as Exchange } from './Exchange';
|
||||
55
src/fetchWithValidation.ts
Normal file
55
src/fetchWithValidation.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
import { Schema, z } from 'zod';
|
||||
import fetch, { RequestInit } from 'node-fetch';
|
||||
import { isWithError, isWithReason, HttpError } from './utils';
|
||||
|
||||
export class ExtendedError extends Error {
|
||||
public url: string;
|
||||
|
||||
public status: number | null;
|
||||
|
||||
constructor(url: string, status: number | null, message: string) {
|
||||
super();
|
||||
this.url = url;
|
||||
this.status = status;
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
|
||||
export const fetchJsonWithValidation = async <DataOut, DataIn, ErrorOut, ErrorIn>(
|
||||
url: string,
|
||||
schema: Schema<DataOut, z.ZodTypeDef, DataIn>,
|
||||
options?: RequestInit,
|
||||
errorSchema?: Schema<ErrorOut, z.ZodTypeDef, ErrorIn>,
|
||||
) => {
|
||||
const response = await fetch(url, {
|
||||
...options || {},
|
||||
headers: {
|
||||
'Cache-Control': 'no-store, max-age=0',
|
||||
...(options ? options.headers : {}),
|
||||
},
|
||||
});
|
||||
const text = await response.text();
|
||||
|
||||
// The ok read-only property of the Response interface contains a Boolean
|
||||
// stating whether the response was successful (status in the range 200 - 299) or not.
|
||||
|
||||
if (!response.ok) {
|
||||
throw new HttpError(response.status, text, 'HTTP', response.statusText);
|
||||
}
|
||||
|
||||
const payload: unknown = JSON.parse(text);
|
||||
|
||||
try {
|
||||
const data = schema.parse(payload);
|
||||
return data;
|
||||
} catch (e) {
|
||||
if (errorSchema) {
|
||||
const errorObj = errorSchema.parse(payload);
|
||||
if (isWithError(errorObj) && isWithReason(errorObj.error)) {
|
||||
throw new ExtendedError(url, response.status, errorObj.error.reason);
|
||||
}
|
||||
}
|
||||
if (e instanceof Error) throw new ExtendedError(url, response.status, e.message);
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
11
src/index.ts
Normal file
11
src/index.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
export * as config from './config';
|
||||
// export * from './entities';
|
||||
export { default as OrionUnit } from './OrionUnit';
|
||||
export { default as initOrionUnit } from './initOrionUnit';
|
||||
export * from './fetchWithValidation';
|
||||
export * as utils from './utils';
|
||||
export * as services from './services';
|
||||
export * as contracts from './artifacts/contracts';
|
||||
export * as crypt from './crypt';
|
||||
export * from './constants';
|
||||
export * from './types';
|
||||
30
src/initOrionUnit.ts
Normal file
30
src/initOrionUnit.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { config, OrionUnit } from '.';
|
||||
import { isValidChainId } from './utils';
|
||||
|
||||
const { chains, envs } = config;
|
||||
|
||||
export default function initOrionUnit(chain: string, env: string) {
|
||||
if (!isValidChainId(chain)) throw new Error(`Chain '${chain}' is not valid.`);
|
||||
|
||||
if (!(env in envs)) throw new Error(`Env '${env}' not found. Available environments is: ${Object.keys(envs).join(', ')}`);
|
||||
const envInfo = envs[env];
|
||||
const envNetworks = envInfo?.networks;
|
||||
|
||||
if (!(chain in envNetworks)) {
|
||||
throw new Error(`Chain '${chain}' not found. `
|
||||
+ `Available chains in selected environment (${env}) is: ${Object.keys(envNetworks).join(', ')}`);
|
||||
}
|
||||
|
||||
const envNetworkInfo = envNetworks[chain];
|
||||
const chainInfo = chains[chain];
|
||||
|
||||
if (!envNetworkInfo) throw new Error('Env network info is required');
|
||||
if (!chainInfo) throw new Error('Chain info is required');
|
||||
|
||||
return new OrionUnit(
|
||||
chainInfo.chainId,
|
||||
envNetworkInfo.rpc ?? chainInfo.rpc,
|
||||
env,
|
||||
envNetworkInfo.api,
|
||||
);
|
||||
}
|
||||
11
src/services/OrionAggregator/errorSchema.ts
Normal file
11
src/services/OrionAggregator/errorSchema.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
const errorSchema = z.object({
|
||||
error: z.object({
|
||||
code: z.number(),
|
||||
reason: z.string(),
|
||||
}),
|
||||
timestamp: z.string(),
|
||||
});
|
||||
|
||||
export default errorSchema;
|
||||
212
src/services/OrionAggregator/index.ts
Normal file
212
src/services/OrionAggregator/index.ts
Normal file
@@ -0,0 +1,212 @@
|
||||
import BigNumber from 'bignumber.js';
|
||||
import { z } from 'zod';
|
||||
import { fetchJsonWithValidation } from '../../fetchWithValidation';
|
||||
import swapInfoSchema from './schemas/swapInfoSchema';
|
||||
import exchangeInfoSchema from './schemas/exchangeInfoSchema';
|
||||
import cancelOrderSchema from './schemas/cancelOrderSchema';
|
||||
import orderBenefitsSchema from './schemas/orderBenefitsSchema';
|
||||
import errorSchema from './errorSchema';
|
||||
import placeAtomicSwapSchema from './schemas/placeAtomicSwapSchema';
|
||||
import { OrionAggregatorWS } from './ws';
|
||||
import atomicSwapHistorySchema from './schemas/atomicSwapHistorySchema';
|
||||
import { SignedCancelOrderRequest, SignedOrder, SupportedChainId } from '../../types';
|
||||
import { pairConfigSchema } from './schemas';
|
||||
|
||||
class OrionAggregator {
|
||||
private readonly apiUrl: string;
|
||||
|
||||
readonly ws: OrionAggregatorWS;
|
||||
|
||||
constructor(apiUrl: string, chainId: SupportedChainId) {
|
||||
this.apiUrl = apiUrl;
|
||||
this.ws = new OrionAggregatorWS(this.aggregatorWSUrl, chainId);
|
||||
}
|
||||
|
||||
get aggregatorWSUrl() { return `wss://${this.apiUrl}/v1`; }
|
||||
|
||||
get aggregatorUrl() {
|
||||
return `https://${this.apiUrl}/backend`;
|
||||
}
|
||||
|
||||
getPairsList() {
|
||||
return fetchJsonWithValidation(
|
||||
`${this.aggregatorUrl}/api/v1/pairs/list`,
|
||||
z.array(z.string()),
|
||||
);
|
||||
}
|
||||
|
||||
getPairConfigs() {
|
||||
return fetchJsonWithValidation(
|
||||
`${this.aggregatorUrl}/api/v1/pairs/exchangeInfo`,
|
||||
exchangeInfoSchema,
|
||||
undefined,
|
||||
errorSchema,
|
||||
);
|
||||
}
|
||||
|
||||
getPairConfig(assetPair: string) {
|
||||
return fetchJsonWithValidation(
|
||||
`${this.aggregatorUrl}/api/v1/pairs/exchangeInfo/${assetPair}`,
|
||||
pairConfigSchema,
|
||||
undefined,
|
||||
errorSchema,
|
||||
);
|
||||
}
|
||||
|
||||
checkWhitelisted(address: string) {
|
||||
return fetchJsonWithValidation(
|
||||
`${this.aggregatorUrl}/api/v1/whitelist/check?address=${address}`,
|
||||
z.boolean(),
|
||||
undefined,
|
||||
errorSchema,
|
||||
);
|
||||
}
|
||||
|
||||
placeOrder(
|
||||
signedOrder: SignedOrder,
|
||||
isCreateInternalOrder: boolean,
|
||||
partnerId?: string,
|
||||
) {
|
||||
const headers = {
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'application/json',
|
||||
...partnerId && { 'X-Partner-Id': partnerId },
|
||||
};
|
||||
|
||||
return fetchJsonWithValidation(
|
||||
`${this.aggregatorUrl}/api/v1/order/${isCreateInternalOrder ? 'internal' : ''}`,
|
||||
z.object({
|
||||
orderId: z.string(),
|
||||
placementRequests: z.array(
|
||||
z.object({
|
||||
amount: z.number(),
|
||||
brokerAddress: z.string(),
|
||||
exchange: z.string(),
|
||||
}),
|
||||
).optional(),
|
||||
}),
|
||||
{
|
||||
headers,
|
||||
method: 'POST',
|
||||
body: JSON.stringify(signedOrder),
|
||||
},
|
||||
errorSchema,
|
||||
);
|
||||
}
|
||||
|
||||
cancelOrder(signedCancelOrderRequest: SignedCancelOrderRequest) {
|
||||
return fetchJsonWithValidation(
|
||||
`${this.aggregatorUrl}/api/v1/order`,
|
||||
cancelOrderSchema,
|
||||
{
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
...signedCancelOrderRequest,
|
||||
sender: signedCancelOrderRequest.senderAddress,
|
||||
}),
|
||||
},
|
||||
errorSchema,
|
||||
);
|
||||
}
|
||||
|
||||
getSwapInfo(
|
||||
type: 'exactSpend' | 'exactReceive',
|
||||
assetIn: string,
|
||||
assetOut: string,
|
||||
amount: string,
|
||||
) {
|
||||
const url = new URL(`${this.aggregatorUrl}/api/v1/swap`);
|
||||
url.searchParams.append('assetIn', assetIn);
|
||||
url.searchParams.append('assetOut', assetOut);
|
||||
if (type === 'exactSpend') {
|
||||
url.searchParams.append('amountIn', amount);
|
||||
} else {
|
||||
url.searchParams.append('amountOut', amount);
|
||||
}
|
||||
|
||||
return fetchJsonWithValidation(
|
||||
url.toString(),
|
||||
swapInfoSchema,
|
||||
undefined,
|
||||
errorSchema,
|
||||
);
|
||||
}
|
||||
|
||||
getLockedBalance(address: string, currency: string) {
|
||||
const url = new URL(`${this.aggregatorUrl}/api/v1/address/balance/reserved/${currency}`);
|
||||
url.searchParams.append('address', address);
|
||||
return fetchJsonWithValidation(
|
||||
url.toString(),
|
||||
z.object({
|
||||
[currency]: z.number(),
|
||||
}).partial(),
|
||||
undefined,
|
||||
errorSchema,
|
||||
);
|
||||
}
|
||||
|
||||
getTradeProfits(
|
||||
symbol: string,
|
||||
amount: BigNumber,
|
||||
isBuy: boolean,
|
||||
) {
|
||||
const url = new URL(`${this.aggregatorUrl}/api/v1/orderBenefits`);
|
||||
url.searchParams.append('symbol', symbol);
|
||||
url.searchParams.append('amount', amount.toString());
|
||||
url.searchParams.append('side', isBuy ? 'buy' : 'sell');
|
||||
|
||||
return fetchJsonWithValidation(
|
||||
url.toString(),
|
||||
orderBenefitsSchema,
|
||||
undefined,
|
||||
errorSchema,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Placing atomic swap. Placement must take place on the target chain.
|
||||
* @param secretHash Secret hash
|
||||
* @param sourceNetworkCode uppercase, e.g. BSC, ETH
|
||||
* @returns Fetch promise
|
||||
*/
|
||||
placeAtomicSwap(
|
||||
secretHash: string,
|
||||
sourceNetworkCode: string,
|
||||
) {
|
||||
return fetchJsonWithValidation(
|
||||
`${this.aggregatorUrl}/api/v1/atomic-swap`,
|
||||
placeAtomicSwapSchema,
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'application/json',
|
||||
},
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
secretHash,
|
||||
sourceNetworkCode,
|
||||
}),
|
||||
},
|
||||
errorSchema,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get placed atomic swaps. Each atomic swap received from this list has a target chain corresponding to this Orion Aggregator
|
||||
* @param sender Sender address
|
||||
* @returns Fetch promise
|
||||
*/
|
||||
getHistoryAtomicSwaps(sender: string, limit = 1000) {
|
||||
const url = new URL(`${this.aggregatorUrl}/api/v1/atomic-swap/history/all`);
|
||||
url.searchParams.append('sender', sender);
|
||||
url.searchParams.append('limit', limit.toString());
|
||||
return fetchJsonWithValidation(url.toString(), atomicSwapHistorySchema);
|
||||
}
|
||||
}
|
||||
export * as schemas from './schemas';
|
||||
export * as ws from './ws';
|
||||
export { OrionAggregator };
|
||||
@@ -0,0 +1,21 @@
|
||||
import { z } from 'zod';
|
||||
import redeemOrderSchema from './redeemOrderSchema';
|
||||
|
||||
export const atomicSwapHistorySchema = z.array(z.object({
|
||||
id: z.string(),
|
||||
sender: z.string(),
|
||||
lockOrder: z.object({
|
||||
sender: z.string(),
|
||||
asset: z.string(),
|
||||
amount: z.number(),
|
||||
expiration: z.number(),
|
||||
secretHash: z.string(),
|
||||
used: z.boolean(),
|
||||
sourceNetworkCode: z.string(),
|
||||
}),
|
||||
redeemOrder: redeemOrderSchema,
|
||||
status: z.enum(['SETTLED', 'EXPIRED', 'ACTIVE']),
|
||||
creationTime: z.number(),
|
||||
}));
|
||||
|
||||
export default atomicSwapHistorySchema;
|
||||
13
src/services/OrionAggregator/schemas/cancelOrderSchema.ts
Normal file
13
src/services/OrionAggregator/schemas/cancelOrderSchema.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
const cancelOrderSchema = z.object({
|
||||
orderId: z.union([z.number(), z.string()]),
|
||||
cancellationRequests: z.array(z.object({
|
||||
amount: z.number(),
|
||||
brokerAddress: z.string(),
|
||||
exchange: z.string(),
|
||||
})).optional(),
|
||||
remainingAmount: z.number().optional(),
|
||||
});
|
||||
|
||||
export default cancelOrderSchema;
|
||||
@@ -0,0 +1,6 @@
|
||||
import { z } from 'zod';
|
||||
import pairConfigSchema from './pairConfigSchema';
|
||||
|
||||
const exchangeInfoSchema = z.array(pairConfigSchema);
|
||||
|
||||
export default exchangeInfoSchema;
|
||||
8
src/services/OrionAggregator/schemas/index.ts
Normal file
8
src/services/OrionAggregator/schemas/index.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export { default as atomicSwapHistorySchema } from './atomicSwapHistorySchema';
|
||||
export { default as cancelOrderSchema } from './cancelOrderSchema';
|
||||
export { default as exchangeInfoSchema } from './exchangeInfoSchema';
|
||||
export { default as orderBenefitsSchema } from './orderBenefitsSchema';
|
||||
export { default as pairConfigSchema } from './pairConfigSchema';
|
||||
export { default as placeAtomicSwapSchema } from './placeAtomicSwapSchema';
|
||||
export { default as redeemOrderSchema } from './redeemOrderSchema';
|
||||
export { default as swapInfoSchema } from './swapInfoSchema';
|
||||
@@ -0,0 +1,8 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
const orderBenefitsSchema = z.record(z.object({
|
||||
benefitBtc: z.string(),
|
||||
benefitPct: z.string(),
|
||||
}));
|
||||
|
||||
export default orderBenefitsSchema;
|
||||
16
src/services/OrionAggregator/schemas/pairConfigSchema.ts
Normal file
16
src/services/OrionAggregator/schemas/pairConfigSchema.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
const pairConfigSchema = z.object({
|
||||
baseAssetPrecision: z.number().int(),
|
||||
executableOnBrokersPriceDeviation: z.number().nullable(),
|
||||
maxPrice: z.number(),
|
||||
maxQty: z.number(),
|
||||
minPrice: z.number(),
|
||||
minQty: z.number(),
|
||||
name: z.string(),
|
||||
pricePrecision: z.number().int(),
|
||||
qtyPrecision: z.number().int(),
|
||||
quoteAssetPrecision: z.number().int(),
|
||||
});
|
||||
|
||||
export default pairConfigSchema;
|
||||
@@ -0,0 +1,18 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
const placeAtomicSwapSchema = z.object({
|
||||
redeemOrder: z.object({
|
||||
amount: z.number(),
|
||||
asset: z.string(),
|
||||
expiration: z.number(),
|
||||
receiver: z.string(),
|
||||
secretHash: z.string(),
|
||||
sender: z.string(),
|
||||
signature: z.string(),
|
||||
claimReceiver: z.string(),
|
||||
}),
|
||||
secretHash: z.string(),
|
||||
sender: z.string(),
|
||||
});
|
||||
|
||||
export default placeAtomicSwapSchema;
|
||||
14
src/services/OrionAggregator/schemas/redeemOrderSchema.ts
Normal file
14
src/services/OrionAggregator/schemas/redeemOrderSchema.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
const redeemOrderSchema = z.object({
|
||||
asset: z.string(),
|
||||
amount: z.number(),
|
||||
secretHash: z.string(),
|
||||
sender: z.string(),
|
||||
receiver: z.string(),
|
||||
expiration: z.number(),
|
||||
signature: z.string(),
|
||||
claimReceiver: z.string(),
|
||||
});
|
||||
|
||||
export default redeemOrderSchema;
|
||||
46
src/services/OrionAggregator/schemas/swapInfoSchema.ts
Normal file
46
src/services/OrionAggregator/schemas/swapInfoSchema.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
const swapInfoBase = z.object({
|
||||
id: z.string(),
|
||||
amountIn: z.number(),
|
||||
amountOut: z.number(),
|
||||
assetIn: z.string(),
|
||||
assetOut: z.string(),
|
||||
path: z.array(z.string()),
|
||||
isThroughPoolOptimal: z.boolean(),
|
||||
executionInfo: z.string(),
|
||||
orderInfo: z.object({
|
||||
assetPair: z.string(),
|
||||
side: z.enum(['BUY', 'SELL']),
|
||||
amount: z.number(),
|
||||
safePrice: z.number(),
|
||||
}).nullable(),
|
||||
price: z.number().nullable(), // spending asset price
|
||||
minAmountOut: z.number(),
|
||||
minAmountIn: z.number(),
|
||||
marketPrice: z.number().nullable(), // spending asset market price
|
||||
});
|
||||
|
||||
const swapInfoByAmountIn = swapInfoBase.extend({
|
||||
availableAmountOut: z.null(),
|
||||
availableAmountIn: z.number(),
|
||||
marketAmountOut: z.number().nullable(),
|
||||
marketAmountIn: z.null(),
|
||||
}).transform((val) => ({
|
||||
...val,
|
||||
type: 'exactSpend' as const,
|
||||
}));
|
||||
|
||||
const swapInfoByAmountOut = swapInfoBase.extend({
|
||||
availableAmountOut: z.number(),
|
||||
availableAmountIn: z.null(),
|
||||
marketAmountOut: z.null(),
|
||||
marketAmountIn: z.number().nullable(),
|
||||
}).transform((val) => ({
|
||||
...val,
|
||||
type: 'exactReceive' as const,
|
||||
}));
|
||||
|
||||
const swapInfoSchema = swapInfoByAmountIn.or(swapInfoByAmountOut);
|
||||
|
||||
export default swapInfoSchema;
|
||||
12
src/services/OrionAggregator/ws/MessageType.ts
Normal file
12
src/services/OrionAggregator/ws/MessageType.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
enum MessageType {
|
||||
ERROR = 'e',
|
||||
PING_PONG = 'pp',
|
||||
SWAP_INFO = 'si',
|
||||
INITIALIZATION = 'i',
|
||||
AGGREGATED_ORDER_BOOK_UPDATE = 'aobu',
|
||||
ASSET_PAIRS_CONFIG_UPDATE = 'apcu',
|
||||
ADDRESS_UPDATE = 'au',
|
||||
BROKER_TRADABLE_ATOMIC_SWAP_ASSETS_BALANCE_UPDATE = 'btasabu'
|
||||
}
|
||||
|
||||
export default MessageType;
|
||||
9
src/services/OrionAggregator/ws/SubscriptionType.ts
Normal file
9
src/services/OrionAggregator/ws/SubscriptionType.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
enum SubscriptionType {
|
||||
ASSET_PAIRS_CONFIG_UPDATES_SUBSCRIBE = 'apcus',
|
||||
AGGREGATED_ORDER_BOOK_UPDATES_SUBSCRIBE = 'aobus',
|
||||
ADDRESS_UPDATES_SUBSCRIBE = 'aus',
|
||||
BROKER_TRADABLE_ATOMIC_SWAP_ASSETS_BALANCE_UPDATES_SUBSCRIBE = 'btasabus',
|
||||
SWAP_SUBSCRIBE = 'ss',
|
||||
}
|
||||
|
||||
export default SubscriptionType;
|
||||
5
src/services/OrionAggregator/ws/UnsubscriptionType.ts
Normal file
5
src/services/OrionAggregator/ws/UnsubscriptionType.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
enum UnsubscriptionType {
|
||||
ASSET_PAIRS_CONFIG_UPDATES_UNSUBSCRIBE = 'apcu',
|
||||
BROKER_TRADABLE_ATOMIC_SWAP_ASSETS_BALANCE_UPDATES_UNSUBSCRIBE = 'btasabu',
|
||||
}
|
||||
export default UnsubscriptionType;
|
||||
318
src/services/OrionAggregator/ws/index.ts
Normal file
318
src/services/OrionAggregator/ws/index.ts
Normal file
@@ -0,0 +1,318 @@
|
||||
import { z } from 'zod';
|
||||
import WebSocket from 'isomorphic-ws';
|
||||
import { validate as uuidValidate } from 'uuid';
|
||||
import { fullOrderSchema, orderUpdateSchema } from './schemas/addressUpdateSchema';
|
||||
import MessageType from './MessageType';
|
||||
import SubscriptionType from './SubscriptionType';
|
||||
import {
|
||||
pingPongMessageSchema, initMessageSchema,
|
||||
errorSchema, brokerMessageSchema, orderBookSchema,
|
||||
assetPairsConfigSchema, addressUpdateSchema, swapInfoSchema,
|
||||
} from './schemas';
|
||||
import UnsubscriptionType from './UnsubscriptionType';
|
||||
import { SwapInfoByAmountIn, SwapInfoByAmountOut } from '../../..';
|
||||
import { SupportedChainId } from '../../../types';
|
||||
// import errorSchema from './schemas/errorSchema';
|
||||
|
||||
const UNSUBSCRIBE = 'u';
|
||||
|
||||
// https://github.com/orionprotocol/orion-aggregator/tree/feature/OP-1752-symmetric-swap#swap-info-subscribe
|
||||
type SwapSubscriptionRequest = {
|
||||
d: string, // swap request UUID, set by client side
|
||||
i: string, // asset in
|
||||
o: string, // asset out
|
||||
a: number // amount IN/OUT
|
||||
e?: boolean; // is amount IN? Value `false` means a = amount OUT, `true` if omitted
|
||||
}
|
||||
|
||||
type BrokerTradableAtomicSwapBalanceSubscription = {
|
||||
callback: (balances: {
|
||||
asset: string;
|
||||
balance: number;
|
||||
}[]) => void,
|
||||
}
|
||||
|
||||
type PairConfigSubscription = {
|
||||
callback: (
|
||||
chainId: SupportedChainId,
|
||||
data: z.infer<typeof assetPairsConfigSchema>['u'],
|
||||
) => void,
|
||||
}
|
||||
|
||||
type AggregatedOrderbookSubscription = {
|
||||
payload: string,
|
||||
callback: (
|
||||
asks: z.infer<typeof orderBookSchema>['ob']['a'],
|
||||
bids: z.infer<typeof orderBookSchema>['ob']['b'],
|
||||
pair: string
|
||||
) => void,
|
||||
}
|
||||
|
||||
type SwapInfoSubscription = {
|
||||
payload: SwapSubscriptionRequest,
|
||||
callback: (swapInfo: SwapInfoByAmountIn | SwapInfoByAmountOut) => void,
|
||||
}
|
||||
|
||||
type AddressUpdateSubscription = {
|
||||
payload: string,
|
||||
callback: ({ fullOrders, orderUpdate, balances } : {
|
||||
fullOrders?: z.infer<typeof fullOrderSchema>[],
|
||||
orderUpdate?: z.infer<typeof orderUpdateSchema> | z.infer<typeof fullOrderSchema>,
|
||||
balances?: Partial<
|
||||
Record<
|
||||
string,
|
||||
[
|
||||
string,
|
||||
string,
|
||||
string,
|
||||
string,
|
||||
string
|
||||
]>
|
||||
>,
|
||||
}) => void,
|
||||
}
|
||||
|
||||
type Subscription = {
|
||||
[SubscriptionType.ADDRESS_UPDATES_SUBSCRIBE]: AddressUpdateSubscription,
|
||||
[SubscriptionType.AGGREGATED_ORDER_BOOK_UPDATES_SUBSCRIBE]: AggregatedOrderbookSubscription,
|
||||
[SubscriptionType.ASSET_PAIRS_CONFIG_UPDATES_SUBSCRIBE]: PairConfigSubscription,
|
||||
[SubscriptionType.BROKER_TRADABLE_ATOMIC_SWAP_ASSETS_BALANCE_UPDATES_SUBSCRIBE]: BrokerTradableAtomicSwapBalanceSubscription,
|
||||
[SubscriptionType.SWAP_SUBSCRIBE]: SwapInfoSubscription
|
||||
}
|
||||
|
||||
type Subscriptions<T extends SubscriptionType> = { [K in T]: Subscription[K] }
|
||||
class OrionAggregatorWS {
|
||||
private ws: WebSocket | undefined;
|
||||
|
||||
private chainId: SupportedChainId;
|
||||
|
||||
private subscriptions: Partial<Subscriptions<SubscriptionType>> = {};
|
||||
|
||||
private onError?: (err: string) => void;
|
||||
|
||||
constructor(url: string, chainId: SupportedChainId, onError?: (err: string) => void) {
|
||||
this.chainId = chainId;
|
||||
this.onError = onError;
|
||||
this.init(url);
|
||||
}
|
||||
|
||||
sendRaw(data: string | ArrayBufferLike | Blob | ArrayBufferView) {
|
||||
if (this.ws?.readyState === 1) {
|
||||
this.ws.send(data);
|
||||
} else if (this.ws?.readyState === 0) {
|
||||
setTimeout(() => {
|
||||
this.sendRaw(data);
|
||||
}, 50);
|
||||
}
|
||||
}
|
||||
|
||||
send(data: unknown) {
|
||||
if (this.ws?.readyState === 1) {
|
||||
this.ws.send(JSON.stringify(data));
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
this.send(data);
|
||||
}, 50);
|
||||
}
|
||||
}
|
||||
|
||||
subscribe<T extends SubscriptionType>(
|
||||
type: T,
|
||||
subscription: Subscription[T],
|
||||
) {
|
||||
this.send({
|
||||
T: type,
|
||||
...('payload' in subscription) && {
|
||||
S: subscription.payload,
|
||||
},
|
||||
});
|
||||
|
||||
this.subscriptions[type] = subscription;
|
||||
}
|
||||
|
||||
unsubscribe(subscription: UnsubscriptionType | string) {
|
||||
this.send({
|
||||
T: UNSUBSCRIBE,
|
||||
S: subscription,
|
||||
});
|
||||
|
||||
if (subscription.includes('0x')) { // is wallet address (ADDRESS_UPDATE)
|
||||
delete this.subscriptions[SubscriptionType.ADDRESS_UPDATES_SUBSCRIBE];
|
||||
} else if (uuidValidate(subscription)) { // is swap info subscription (contains hyphen)
|
||||
delete this.subscriptions[SubscriptionType.SWAP_SUBSCRIBE];
|
||||
// !!! swap info subscription is uuid that contains hyphen
|
||||
} else if (subscription.includes('-') && subscription.split('-').length === 2) { // is pair name(AGGREGATED_ORDER_BOOK_UPDATE)
|
||||
delete this.subscriptions[SubscriptionType.AGGREGATED_ORDER_BOOK_UPDATES_SUBSCRIBE];
|
||||
} else if (subscription === UnsubscriptionType.ASSET_PAIRS_CONFIG_UPDATES_UNSUBSCRIBE) {
|
||||
delete this.subscriptions[SubscriptionType.ASSET_PAIRS_CONFIG_UPDATES_SUBSCRIBE];
|
||||
} else if (subscription === UnsubscriptionType.BROKER_TRADABLE_ATOMIC_SWAP_ASSETS_BALANCE_UPDATES_UNSUBSCRIBE) {
|
||||
delete this.subscriptions[SubscriptionType.BROKER_TRADABLE_ATOMIC_SWAP_ASSETS_BALANCE_UPDATES_SUBSCRIBE];
|
||||
}
|
||||
}
|
||||
|
||||
init(url: string) {
|
||||
this.ws = new WebSocket(url);
|
||||
this.ws.onclose = () => {
|
||||
console.log(`Orion Aggregator ${this.chainId} WS Connection closed`);
|
||||
this.init(url);
|
||||
};
|
||||
this.ws.onopen = () => {
|
||||
console.log(`Orion Aggregator ${this.chainId} WS Connection established`);
|
||||
|
||||
Object.entries(this.subscriptions).forEach(([type, subscription]) => {
|
||||
this.send({
|
||||
T: type,
|
||||
...('payload' in subscription) && {
|
||||
S: subscription.payload,
|
||||
},
|
||||
});
|
||||
});
|
||||
};
|
||||
this.ws.onmessage = (e) => {
|
||||
const { data } = e;
|
||||
const rawJson: unknown = JSON.parse(data.toString());
|
||||
|
||||
const messageSchema = z.union([
|
||||
initMessageSchema,
|
||||
pingPongMessageSchema,
|
||||
addressUpdateSchema,
|
||||
assetPairsConfigSchema,
|
||||
brokerMessageSchema,
|
||||
orderBookSchema,
|
||||
swapInfoSchema,
|
||||
errorSchema,
|
||||
]);
|
||||
|
||||
const json = messageSchema.parse(rawJson);
|
||||
|
||||
switch (json.T) {
|
||||
case MessageType.ERROR: {
|
||||
const { m: errorMessage } = errorSchema.parse(json);
|
||||
this.onError?.(errorMessage);
|
||||
}
|
||||
break;
|
||||
case MessageType.PING_PONG:
|
||||
this.sendRaw(data.toString());
|
||||
break;
|
||||
case MessageType.SWAP_INFO:
|
||||
switch (json.k) { // kind
|
||||
case 'exactSpend':
|
||||
this.subscriptions[SubscriptionType.SWAP_SUBSCRIBE]?.callback({
|
||||
kind: json.k,
|
||||
swapRequestId: json.S,
|
||||
assetIn: json.ai,
|
||||
assetOut: json.ao,
|
||||
amountIn: json.a,
|
||||
amountOut: json.o,
|
||||
price: json.p,
|
||||
marketAmountOut: json.mo,
|
||||
marketPrice: json.mp,
|
||||
minAmounOut: json.mao,
|
||||
minAmounIn: json.ma,
|
||||
availableAmountIn: json.aa,
|
||||
...json.oi && {
|
||||
orderInfo: {
|
||||
pair: json.oi.p,
|
||||
side: json.oi.s,
|
||||
amount: json.oi.a,
|
||||
safePrice: json.oi.sp,
|
||||
},
|
||||
},
|
||||
path: json.ps,
|
||||
poolOptimal: json.po,
|
||||
});
|
||||
break;
|
||||
case 'exactReceive':
|
||||
this.subscriptions[SubscriptionType.SWAP_SUBSCRIBE]?.callback({
|
||||
kind: json.k,
|
||||
swapRequestId: json.S,
|
||||
assetIn: json.ai,
|
||||
assetOut: json.ao,
|
||||
amountIn: json.a,
|
||||
amountOut: json.o,
|
||||
price: json.p,
|
||||
marketAmountIn: json.mi,
|
||||
marketPrice: json.mp,
|
||||
minAmounOut: json.mao,
|
||||
minAmounIn: json.ma,
|
||||
availableAmountOut: json.aao,
|
||||
...json.oi && {
|
||||
orderInfo: {
|
||||
pair: json.oi.p,
|
||||
side: json.oi.s,
|
||||
amount: json.oi.a,
|
||||
safePrice: json.oi.sp,
|
||||
},
|
||||
},
|
||||
path: json.ps,
|
||||
poolOptimal: json.po,
|
||||
});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
// case MessageType.INITIALIZATION:
|
||||
// break;
|
||||
case MessageType.AGGREGATED_ORDER_BOOK_UPDATE: {
|
||||
const { ob, S } = json;
|
||||
this.subscriptions[
|
||||
SubscriptionType.AGGREGATED_ORDER_BOOK_UPDATES_SUBSCRIBE
|
||||
]?.callback(ob.a, ob.b, S);
|
||||
}
|
||||
break;
|
||||
case MessageType.ASSET_PAIRS_CONFIG_UPDATE: {
|
||||
const pairs = json;
|
||||
this.subscriptions[
|
||||
SubscriptionType.ASSET_PAIRS_CONFIG_UPDATES_SUBSCRIBE
|
||||
]?.callback(this.chainId, pairs.u);
|
||||
}
|
||||
break;
|
||||
case MessageType.ADDRESS_UPDATE:
|
||||
switch (json.k) { // kind
|
||||
case 'i': // initial
|
||||
this.subscriptions[
|
||||
SubscriptionType.ADDRESS_UPDATES_SUBSCRIBE
|
||||
]?.callback({
|
||||
fullOrders: json.o,
|
||||
balances: json.b,
|
||||
});
|
||||
break;
|
||||
case 'u': // update
|
||||
this.subscriptions[
|
||||
SubscriptionType.ADDRESS_UPDATES_SUBSCRIBE
|
||||
]?.callback({
|
||||
orderUpdate: json.o?.[0],
|
||||
balances: json.b,
|
||||
});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MessageType.BROKER_TRADABLE_ATOMIC_SWAP_ASSETS_BALANCE_UPDATE: {
|
||||
const updatedBrokerBalances = json.bb.map((bb) => {
|
||||
const [asset, balance] = bb;
|
||||
return { asset, balance };
|
||||
});
|
||||
|
||||
this.subscriptions[
|
||||
SubscriptionType.BROKER_TRADABLE_ATOMIC_SWAP_ASSETS_BALANCE_UPDATES_SUBSCRIBE
|
||||
]?.callback(updatedBrokerBalances);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export * as schemas from './schemas';
|
||||
export {
|
||||
OrionAggregatorWS,
|
||||
SubscriptionType,
|
||||
UnsubscriptionType,
|
||||
MessageType,
|
||||
};
|
||||
@@ -0,0 +1,79 @@
|
||||
import { z } from 'zod';
|
||||
import orderStatuses from '../../../../constants/orderStatuses';
|
||||
import subOrderStatuses from '../../../../constants/subOrderStatuses';
|
||||
import MessageType from '../MessageType';
|
||||
import balancesSchema from './balancesSchema';
|
||||
import baseMessageSchema from './baseMessageSchema';
|
||||
|
||||
const baseAddressUpdate = baseMessageSchema.extend({
|
||||
T: z.literal(MessageType.ADDRESS_UPDATE),
|
||||
S: z.string(), // subscription
|
||||
uc: z.array(z.enum(['b', 'o'])), // update content
|
||||
});
|
||||
|
||||
const subOrderSchema = z.object({
|
||||
i: z.number(), // id
|
||||
I: z.string(), // parent order id
|
||||
O: z.string(), // sender (owner)
|
||||
P: z.string(), // asset pair
|
||||
s: z.enum(['BUY', 'SELL']), // side
|
||||
a: z.number(), // amount
|
||||
A: z.number(), // settled amount
|
||||
p: z.number(), // avg weighed settlement price
|
||||
e: z.string(), // exchange
|
||||
b: z.string(), // broker address
|
||||
S: z.enum(subOrderStatuses), // status
|
||||
o: z.boolean(), // internal only
|
||||
});
|
||||
|
||||
export const orderUpdateSchema = z.object({
|
||||
I: z.string(), // id
|
||||
A: z.number(), // settled amount
|
||||
S: z.enum(orderStatuses), // status
|
||||
t: z.number(), // update time
|
||||
c: subOrderSchema.array(),
|
||||
})
|
||||
.transform((val) => ({
|
||||
...val,
|
||||
k: 'update' as const,
|
||||
}));
|
||||
|
||||
export const fullOrderSchema = z.object({
|
||||
I: z.string(), // id
|
||||
O: z.string(), // sender (owner)
|
||||
P: z.string(), // asset pair
|
||||
s: z.enum(['BUY', 'SELL']), // side
|
||||
a: z.number(), // amount
|
||||
A: z.number(), // settled amount
|
||||
p: z.number(), // price
|
||||
F: z.string(), // fee asset
|
||||
f: z.number(), // fee
|
||||
o: z.boolean(), // internal only
|
||||
S: z.enum(orderStatuses), // status
|
||||
T: z.number(), // creation time / unix timestamp
|
||||
t: z.number(), // update time
|
||||
c: subOrderSchema.array(),
|
||||
}).transform((val) => ({
|
||||
...val,
|
||||
k: 'full' as const,
|
||||
}));
|
||||
|
||||
const updateMessageSchema = baseAddressUpdate.extend({
|
||||
k: z.literal('u'), // kind of message: "u" - updates
|
||||
uc: z.array(z.enum(['b', 'o'])), // update content: "o" - orders updates, "b" - balance updates
|
||||
b: balancesSchema.optional(),
|
||||
o: z.tuple([fullOrderSchema.or(orderUpdateSchema)]).optional(),
|
||||
});
|
||||
|
||||
const initialMessageSchema = baseAddressUpdate.extend({
|
||||
k: z.literal('i'), // kind of message: "i" - initial
|
||||
b: balancesSchema,
|
||||
o: z.array(fullOrderSchema).optional(), // When no orders — no field
|
||||
});
|
||||
|
||||
const addressUpdateSchema = z.union([
|
||||
initialMessageSchema,
|
||||
updateMessageSchema,
|
||||
]);
|
||||
|
||||
export default addressUpdateSchema;
|
||||
@@ -0,0 +1,16 @@
|
||||
import { z } from 'zod';
|
||||
import MessageType from '../MessageType';
|
||||
import baseMessageSchema from './baseMessageSchema';
|
||||
|
||||
const assetPairsConfigSchema = baseMessageSchema.extend({
|
||||
T: z.literal(MessageType.ASSET_PAIRS_CONFIG_UPDATE),
|
||||
u: z.array(
|
||||
z.tuple([
|
||||
z.string(), // pairName
|
||||
z.number(), // minQty
|
||||
z.number(), // pricePrecision
|
||||
]),
|
||||
),
|
||||
});
|
||||
|
||||
export default assetPairsConfigSchema;
|
||||
14
src/services/OrionAggregator/ws/schemas/balancesSchema.ts
Normal file
14
src/services/OrionAggregator/ws/schemas/balancesSchema.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { z } from 'zod';
|
||||
import { makePartial } from '../../../../utils';
|
||||
|
||||
const balancesSchema = z.record( // changed balances in format
|
||||
z.string(), // asset
|
||||
z.tuple([
|
||||
z.string(), // tradable balance
|
||||
z.string(), // reserved balance
|
||||
z.string(), // contract balance
|
||||
z.string(), // wallet balance
|
||||
z.string(), // allowance
|
||||
]),
|
||||
).transform(makePartial);
|
||||
export default balancesSchema;
|
||||
@@ -0,0 +1,9 @@
|
||||
import { z } from 'zod';
|
||||
import MessageType from '../MessageType';
|
||||
|
||||
const baseMessageSchema = z.object({
|
||||
T: z.nativeEnum(MessageType),
|
||||
_: z.number(),
|
||||
});
|
||||
|
||||
export default baseMessageSchema;
|
||||
@@ -0,0 +1,15 @@
|
||||
import { z } from 'zod';
|
||||
import MessageType from '../MessageType';
|
||||
import baseMessageSchema from './baseMessageSchema';
|
||||
|
||||
const brokerMessageSchema = baseMessageSchema.extend({
|
||||
T: z.literal(MessageType.BROKER_TRADABLE_ATOMIC_SWAP_ASSETS_BALANCE_UPDATE),
|
||||
bb: z.array(
|
||||
z.tuple([
|
||||
z.string(), // Asset name
|
||||
z.number(), // limit
|
||||
]),
|
||||
),
|
||||
});
|
||||
|
||||
export default brokerMessageSchema;
|
||||
11
src/services/OrionAggregator/ws/schemas/errorSchema.ts
Normal file
11
src/services/OrionAggregator/ws/schemas/errorSchema.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { z } from 'zod';
|
||||
import MessageType from '../MessageType';
|
||||
import baseMessageSchema from './baseMessageSchema';
|
||||
|
||||
const errorSchema = baseMessageSchema.extend({
|
||||
T: z.literal(MessageType.ERROR),
|
||||
c: z.number(), // code
|
||||
m: z.string(), // error message,
|
||||
});
|
||||
|
||||
export default errorSchema;
|
||||
11
src/services/OrionAggregator/ws/schemas/index.ts
Normal file
11
src/services/OrionAggregator/ws/schemas/index.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
export { default as addressUpdateSchema } from './addressUpdateSchema';
|
||||
export { default as assetPairsConfigSchema } from './assetPairsConfigSchema';
|
||||
export { default as baseMessageSchema } from './baseMessageSchema';
|
||||
export { default as brokerMessageSchema } from './brokerMessageSchema';
|
||||
export { default as errorSchema } from './errorSchema';
|
||||
export { default as initMessageSchema } from './initMessageSchema';
|
||||
export { default as pingPongMessageSchema } from './pingPongMessageSchema';
|
||||
export { default as swapInfoSchema } from './swapInfoSchema';
|
||||
export { default as balancesSchema } from './balancesSchema';
|
||||
|
||||
export * from './orderBookSchema';
|
||||
10
src/services/OrionAggregator/ws/schemas/initMessageSchema.ts
Normal file
10
src/services/OrionAggregator/ws/schemas/initMessageSchema.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { z } from 'zod';
|
||||
import MessageType from '../MessageType';
|
||||
import baseMessageSchema from './baseMessageSchema';
|
||||
|
||||
const initMessageSchema = baseMessageSchema.extend({
|
||||
T: z.literal(MessageType.INITIALIZATION),
|
||||
i: z.string(),
|
||||
});
|
||||
|
||||
export default initMessageSchema;
|
||||
22
src/services/OrionAggregator/ws/schemas/orderBookSchema.ts
Normal file
22
src/services/OrionAggregator/ws/schemas/orderBookSchema.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { z } from 'zod';
|
||||
import MessageType from '../MessageType';
|
||||
import baseMessageSchema from './baseMessageSchema';
|
||||
|
||||
export const orderBookItemSchema = z.tuple([
|
||||
z.string(), // price
|
||||
z.string(), // size
|
||||
z.array(z.string()), // exchanges
|
||||
z.array(z.tuple([
|
||||
z.enum(['SELL', 'BUY']), // side
|
||||
z.string(), // pairname
|
||||
])),
|
||||
]);
|
||||
|
||||
export const orderBookSchema = baseMessageSchema.extend({
|
||||
T: z.literal(MessageType.AGGREGATED_ORDER_BOOK_UPDATE),
|
||||
S: z.string(),
|
||||
ob: z.object({
|
||||
a: z.array(orderBookItemSchema),
|
||||
b: z.array(orderBookItemSchema),
|
||||
}),
|
||||
});
|
||||
@@ -0,0 +1,9 @@
|
||||
import { z } from 'zod';
|
||||
import MessageType from '../MessageType';
|
||||
import baseMessageSchema from './baseMessageSchema';
|
||||
|
||||
const pingPongMessageSchema = baseMessageSchema.extend({
|
||||
T: z.literal(MessageType.PING_PONG),
|
||||
});
|
||||
|
||||
export default pingPongMessageSchema;
|
||||
48
src/services/OrionAggregator/ws/schemas/swapInfoSchema.ts
Normal file
48
src/services/OrionAggregator/ws/schemas/swapInfoSchema.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { z } from 'zod';
|
||||
import MessageType from '../MessageType';
|
||||
import baseMessageSchema from './baseMessageSchema';
|
||||
|
||||
const swapInfoSchemaBase = baseMessageSchema.extend({
|
||||
T: z.literal(MessageType.SWAP_INFO),
|
||||
S: z.string(), // swap request id
|
||||
ai: z.string(), // asset in,
|
||||
ao: z.string(), // asset out
|
||||
a: z.number(), // amount in
|
||||
o: z.number(), // amount out
|
||||
ma: z.number(), // min amount in
|
||||
mao: z.number(), // min amount out
|
||||
ps: z.string().array(), // path
|
||||
po: z.boolean(), // is swap through pool optimal
|
||||
|
||||
p: z.number().optional(), // price
|
||||
mp: z.number().optional(), // market price
|
||||
oi: z.object({ // info about order equivalent to this swap
|
||||
p: z.string(), // asset pair
|
||||
s: z.enum(['SELL', 'BUY']), // side
|
||||
a: z.number(), // amount
|
||||
sp: z.number(), // safe price (with safe deviation but without slippage)
|
||||
}).optional(),
|
||||
});
|
||||
|
||||
const swapInfoSchemaByAmountIn = swapInfoSchemaBase.extend({
|
||||
mo: z.number().optional(), // market amount out
|
||||
aa: z.number(), // available amount in
|
||||
}).transform((content) => ({
|
||||
...content,
|
||||
k: 'exactSpend' as const,
|
||||
}));
|
||||
|
||||
const swapInfoSchemaByAmountOut = swapInfoSchemaBase.extend({
|
||||
mi: z.number().optional(), // market amount in
|
||||
aao: z.number(), // available amount out
|
||||
}).transform((content) => ({
|
||||
...content,
|
||||
k: 'exactReceive' as const,
|
||||
}));
|
||||
|
||||
const swapInfoSchema = z.union([
|
||||
swapInfoSchemaByAmountIn,
|
||||
swapInfoSchemaByAmountOut,
|
||||
]);
|
||||
|
||||
export default swapInfoSchema;
|
||||
276
src/services/OrionBlockchain/index.ts
Normal file
276
src/services/OrionBlockchain/index.ts
Normal file
@@ -0,0 +1,276 @@
|
||||
import { z } from 'zod';
|
||||
import { fetchJsonWithValidation } from '../../fetchWithValidation';
|
||||
import { PairStatusEnum, pairStatusSchema } from './schemas/adminPoolsListSchema';
|
||||
import {
|
||||
IDOSchema, atomicHistorySchema,
|
||||
poolsConfigSchema, poolsInfoSchema, infoSchema, historySchema,
|
||||
addPoolSchema, adminPoolsListSchema,
|
||||
} from './schemas';
|
||||
import { OrionBlockchainSocketIO } from './ws';
|
||||
import redeemOrderSchema from '../OrionAggregator/schemas/redeemOrderSchema';
|
||||
import { sourceAtomicHistorySchema, targetAtomicHistorySchema } from './schemas/atomicHistorySchema';
|
||||
import { SupportedChainId } from '../../types';
|
||||
import { utils } from '../..';
|
||||
|
||||
interface IAdminAuthHeaders {
|
||||
auth: string;
|
||||
[key: string]: string
|
||||
}
|
||||
|
||||
export interface IEditPool {
|
||||
tokenAIcon?: string;
|
||||
tokenBIcon?: string;
|
||||
symbol?: string;
|
||||
status: PairStatusEnum;
|
||||
qtyPrecision?: number;
|
||||
pricePrecision?: number;
|
||||
minQty?: number;
|
||||
tokenASymbol?: string;
|
||||
tokenBSymbol?: string;
|
||||
tokensReversed?: boolean;
|
||||
}
|
||||
|
||||
type AtomicSwapHistoryBaseQuery = {
|
||||
limit?: number
|
||||
sender?: string,
|
||||
receiver?: string,
|
||||
used?: 0 | 1,
|
||||
page?: number,
|
||||
}
|
||||
|
||||
type AtomicSwapHistorySourceQuery = AtomicSwapHistoryBaseQuery & {
|
||||
type?: 'source',
|
||||
expiredLock?: 0 | 1,
|
||||
state?: 'LOCKED' | 'CLAIMED' |'REFUNDED',
|
||||
|
||||
}
|
||||
type AtomicSwapHistoryTargetQuery = AtomicSwapHistoryBaseQuery & {
|
||||
type?: 'target',
|
||||
expiredRedeem?: 0 | 1,
|
||||
state?: 'REDEEMED' | 'BEFORE-REDEEM',
|
||||
}
|
||||
class OrionBlockchain {
|
||||
private readonly apiUrl: string;
|
||||
|
||||
readonly ws: OrionBlockchainSocketIO;
|
||||
|
||||
constructor(
|
||||
apiUrl: string,
|
||||
chainId: SupportedChainId,
|
||||
) {
|
||||
this.apiUrl = apiUrl;
|
||||
this.ws = new OrionBlockchainSocketIO(`https://${apiUrl}/`);
|
||||
}
|
||||
|
||||
get orionBlockchainWsUrl() {
|
||||
return `https://${this.apiUrl}/`;
|
||||
}
|
||||
|
||||
getAuthToken() {
|
||||
return fetchJsonWithValidation(`https://${this.apiUrl}/api/auth/token`, z.object({ token: z.string() }));
|
||||
}
|
||||
|
||||
getCirculatingSupply() {
|
||||
return fetchJsonWithValidation(`https://${this.apiUrl}/api/circulating-supply`, z.number());
|
||||
}
|
||||
|
||||
getInfo() {
|
||||
return fetchJsonWithValidation(`https://${this.apiUrl}/api/info`, infoSchema);
|
||||
}
|
||||
|
||||
getPoolsConfig() {
|
||||
return fetchJsonWithValidation(`https://${this.apiUrl}/api/pools/config`, poolsConfigSchema);
|
||||
}
|
||||
|
||||
getPoolsInfo() {
|
||||
return fetchJsonWithValidation(`https://${this.apiUrl}/api/pools/info`, poolsInfoSchema);
|
||||
}
|
||||
|
||||
getHistory(address: string) {
|
||||
return fetchJsonWithValidation(`https://${this.apiUrl}/api/history/${address}`, historySchema);
|
||||
}
|
||||
|
||||
getPrices() {
|
||||
return fetchJsonWithValidation(`https://${this.apiUrl}/api/prices`, z.record(z.string()).transform(utils.makePartial));
|
||||
}
|
||||
|
||||
getTokensFee() {
|
||||
return fetchJsonWithValidation(`https://${this.apiUrl}/api/tokensFee`, z.record(z.string()).transform(utils.makePartial));
|
||||
}
|
||||
|
||||
getGasPriceWei() {
|
||||
return fetchJsonWithValidation(`https://${this.apiUrl}/api/gasPrice`, z.string());
|
||||
}
|
||||
|
||||
checkFreeRedeemAvailable(walletAddress: string) {
|
||||
return fetchJsonWithValidation(`https://${this.apiUrl}/api/atomic/has-free-redeem/${walletAddress}`, z.boolean());
|
||||
}
|
||||
|
||||
redeemAtomicSwap(
|
||||
redeemOrder: z.infer<typeof redeemOrderSchema>,
|
||||
secret: string,
|
||||
sourceNetwork: string,
|
||||
) {
|
||||
return fetchJsonWithValidation(
|
||||
`https://${this.apiUrl}/api/atomic/matcher-redeem`,
|
||||
z.string(),
|
||||
{
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
order: redeemOrder,
|
||||
secret,
|
||||
sourceNetwork,
|
||||
}),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
redeem2AtomicSwaps(
|
||||
redeemOrder1: z.infer<typeof redeemOrderSchema>,
|
||||
secret1: string,
|
||||
redeemOrder2: z.infer<typeof redeemOrderSchema>,
|
||||
secret2: string,
|
||||
sourceNetwork: string,
|
||||
) {
|
||||
return fetchJsonWithValidation(
|
||||
`https://${this.apiUrl}/api/atomic/matcher-redeem2atomics`,
|
||||
z.string(),
|
||||
{
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
order1: redeemOrder1,
|
||||
secret1,
|
||||
order2: redeemOrder2,
|
||||
secret2,
|
||||
sourceNetwork,
|
||||
}),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
checkRedeem(secretHash: string) {
|
||||
return fetchJsonWithValidation(
|
||||
`https://${this.apiUrl}/api/atomic/matcher-redeem/${secretHash}`,
|
||||
z.enum(['OK', 'FAIL']).nullable(),
|
||||
);
|
||||
}
|
||||
|
||||
checkRedeem2Atomics(firstSecretHash: string, secondSecretHash: string) {
|
||||
return fetchJsonWithValidation(
|
||||
`https://${this.apiUrl}/api/atomic/matcher-redeem/${firstSecretHash}-${secondSecretHash}`,
|
||||
z.enum(['OK', 'FAIL']).nullable(),
|
||||
);
|
||||
}
|
||||
|
||||
getIDOInfo() {
|
||||
return fetchJsonWithValidation(`https://${this.apiUrl}/api/solarflare`, IDOSchema);
|
||||
}
|
||||
|
||||
checkAuth(headers: IAdminAuthHeaders) {
|
||||
return fetchJsonWithValidation(`https://${this.apiUrl}/api/auth/check`, z.object({
|
||||
auth: z.boolean(),
|
||||
}), { headers });
|
||||
}
|
||||
|
||||
getPoolsList(headers: IAdminAuthHeaders) {
|
||||
return fetchJsonWithValidation(
|
||||
`https://${this.apiUrl}/api/pools/list`,
|
||||
adminPoolsListSchema,
|
||||
{ headers },
|
||||
);
|
||||
}
|
||||
|
||||
editPool(address: string, data: IEditPool, headers: IAdminAuthHeaders) {
|
||||
return fetchJsonWithValidation(
|
||||
`https://${this.apiUrl}/api/pools/edit/${address}`,
|
||||
pairStatusSchema,
|
||||
{
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
...headers,
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
addPool(data: z.infer<typeof addPoolSchema>) {
|
||||
return fetchJsonWithValidation(`https://${this.apiUrl}/api/pools/add`, z.number(), {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'application/json',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
checkPoolInformation(poolAddress: string) {
|
||||
return fetchJsonWithValidation(`https://${this.apiUrl}/api/pools/check/${poolAddress}`, pairStatusSchema);
|
||||
}
|
||||
|
||||
getAtomicSwapAssets() {
|
||||
return fetchJsonWithValidation(`https://${this.apiUrl}/api/atomic/swap-assets`, z.array(z.string()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sender is user address in source Orion Blockchain instance \
|
||||
* Receiver is user address in target Orion Blockchain instance
|
||||
*/
|
||||
getAtomicSwapHistory(query: AtomicSwapHistorySourceQuery | AtomicSwapHistoryTargetQuery) {
|
||||
const url = new URL(`https://${this.apiUrl}/api/atomic/history/`);
|
||||
|
||||
Object.entries(query)
|
||||
.forEach(([key, value]) => url.searchParams.append(key, value.toString()));
|
||||
|
||||
return fetchJsonWithValidation(url.toString(), atomicHistorySchema);
|
||||
}
|
||||
|
||||
getSourceAtomicSwapHistory(query: AtomicSwapHistorySourceQuery) {
|
||||
const url = new URL(`https://${this.apiUrl}/api/atomic/history/`);
|
||||
|
||||
Object.entries(query)
|
||||
.forEach(([key, value]) => url.searchParams.append(key, value.toString()));
|
||||
|
||||
if (!query.type) url.searchParams.append('type', 'source');
|
||||
|
||||
return fetchJsonWithValidation(url.toString(), sourceAtomicHistorySchema);
|
||||
}
|
||||
|
||||
getTargetAtomicSwapHistory(query: AtomicSwapHistoryTargetQuery) {
|
||||
const url = new URL(`https://${this.apiUrl}/api/atomic/history/`);
|
||||
|
||||
Object.entries(query)
|
||||
.forEach(([key, value]) => url.searchParams.append(key, value.toString()));
|
||||
|
||||
if (!query.type) url.searchParams.append('type', 'target');
|
||||
|
||||
return fetchJsonWithValidation(url.toString(), targetAtomicHistorySchema);
|
||||
}
|
||||
|
||||
checkIfHashUsed(secretHashes: string[]) {
|
||||
return fetchJsonWithValidation(
|
||||
`https://${this.apiUrl}/api/atomic/is-hash-used`,
|
||||
z.record(z.boolean()).transform(utils.makePartial),
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'application/json',
|
||||
},
|
||||
method: 'POST',
|
||||
body: JSON.stringify(secretHashes),
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export * as ws from './ws';
|
||||
export * as schemas from './schemas';
|
||||
export { OrionBlockchain };
|
||||
10
src/services/OrionBlockchain/schemas/IDOSchema.ts
Normal file
10
src/services/OrionBlockchain/schemas/IDOSchema.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
const IDOSchema = z.object({
|
||||
amount: z.number().or(z.null()),
|
||||
amountInWei: z.number().or(z.null()),
|
||||
amountInUSDT: z.number().or(z.null()),
|
||||
address: z.string(),
|
||||
});
|
||||
|
||||
export default IDOSchema;
|
||||
11
src/services/OrionBlockchain/schemas/addPoolSchema.ts
Normal file
11
src/services/OrionBlockchain/schemas/addPoolSchema.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
const addPoolSchema = z.object({
|
||||
poolAddress: z.string(),
|
||||
tokenAIcon: z.string().optional(),
|
||||
tokenAName: z.string().optional(),
|
||||
tokenBIcon: z.string().optional(),
|
||||
tokenBName: z.string().optional(),
|
||||
});
|
||||
|
||||
export default addPoolSchema;
|
||||
38
src/services/OrionBlockchain/schemas/adminPoolsListSchema.ts
Normal file
38
src/services/OrionBlockchain/schemas/adminPoolsListSchema.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
export enum PairStatusEnum {
|
||||
DOESNT_EXIST = -1,
|
||||
REVIEW = 0,
|
||||
ACCEPTED = 1,
|
||||
REJECTED = 2,
|
||||
}
|
||||
|
||||
export const pairStatusSchema = z.nativeEnum(PairStatusEnum);
|
||||
|
||||
const tokenSchema = z.object({
|
||||
symbol: z.string(),
|
||||
icon: z.string().optional(),
|
||||
address: z.string(),
|
||||
decimals: z.number().optional(),
|
||||
isUser: z.boolean().optional(),
|
||||
});
|
||||
|
||||
const poolOnVerificationSchema = z.object({
|
||||
tokenA: tokenSchema,
|
||||
tokenB: tokenSchema,
|
||||
_id: z.string().optional(),
|
||||
address: z.string(),
|
||||
symbol: z.string(),
|
||||
isUser: z.boolean(),
|
||||
minQty: z.number().optional(),
|
||||
tokensReversed: z.boolean(),
|
||||
status: pairStatusSchema,
|
||||
updatedAt: z.number(),
|
||||
createdAt: z.number(),
|
||||
qtyPrecision: z.number().optional(),
|
||||
pricePrecision: z.number().optional(),
|
||||
});
|
||||
|
||||
export type adminPoolType = z.infer<typeof poolOnVerificationSchema>;
|
||||
|
||||
export const adminPoolsListSchema = z.array(poolOnVerificationSchema);
|
||||
72
src/services/OrionBlockchain/schemas/atomicHistorySchema.ts
Normal file
72
src/services/OrionBlockchain/schemas/atomicHistorySchema.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
const baseAtomicHistorySchema = z.object({
|
||||
success: z.boolean(),
|
||||
count: z.number(),
|
||||
total: z.number(),
|
||||
pagination: z.object({}),
|
||||
});
|
||||
|
||||
const baseAtomicHistoryItem = z.object({
|
||||
used: z.boolean(),
|
||||
claimed: z.boolean(),
|
||||
isAggApplied: z.boolean(),
|
||||
_id: z.string(),
|
||||
__v: z.number(),
|
||||
asset: z.string(),
|
||||
sender: z.string(),
|
||||
secretHash: z.string(),
|
||||
receiver: z.string().optional(),
|
||||
secret: z.string().optional(),
|
||||
});
|
||||
|
||||
const sourceAtomicHistorySchemaItem = baseAtomicHistoryItem.extend({
|
||||
type: z.literal('source'),
|
||||
amountToReceive: z.number().optional(),
|
||||
amountToSpend: z.number().optional(),
|
||||
timestamp: z.object({
|
||||
lock: z.number().optional(),
|
||||
claim: z.number().optional(),
|
||||
refund: z.number().optional(),
|
||||
}).optional(),
|
||||
expiration: z.object({
|
||||
lock: z.number().optional(),
|
||||
}).optional(),
|
||||
state: z.enum(['LOCKED', 'REFUNDED', 'CLAIMED']),
|
||||
targetChainId: z.number(),
|
||||
transactions: z.object({
|
||||
lock: z.string().optional(),
|
||||
claim: z.string().optional(),
|
||||
refund: z.string().optional(),
|
||||
}).optional(),
|
||||
});
|
||||
|
||||
const targetAtomicHistorySchemaItem = baseAtomicHistoryItem.extend({
|
||||
type: z.literal('target'),
|
||||
timestamp: z.object({
|
||||
redeem: z.number().optional(),
|
||||
}).optional(),
|
||||
expiration: z.object({
|
||||
redeem: z.number().optional(),
|
||||
}).optional(),
|
||||
state: z.enum(['REDEEMED', 'BEFORE-REDEEM']),
|
||||
transactions: z.object({
|
||||
redeem: z.string().optional(),
|
||||
}).optional(),
|
||||
});
|
||||
|
||||
export const sourceAtomicHistorySchema = baseAtomicHistorySchema.extend({
|
||||
data: z.array(sourceAtomicHistorySchemaItem),
|
||||
});
|
||||
|
||||
export const targetAtomicHistorySchema = baseAtomicHistorySchema.extend({
|
||||
data: z.array(targetAtomicHistorySchemaItem),
|
||||
});
|
||||
|
||||
const atomicHistorySchema = baseAtomicHistorySchema.extend({
|
||||
data: z.array(
|
||||
z.discriminatedUnion('type', [sourceAtomicHistorySchemaItem, targetAtomicHistorySchemaItem]),
|
||||
),
|
||||
});
|
||||
|
||||
export default atomicHistorySchema;
|
||||
@@ -0,0 +1,9 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
const checkRedeemOrderSchema = z.object({
|
||||
redeemTxHash: z.string(),
|
||||
secret: z.string().nullable(),
|
||||
secretHash: z.string(),
|
||||
});
|
||||
|
||||
export default checkRedeemOrderSchema;
|
||||
20
src/services/OrionBlockchain/schemas/historySchema.ts
Normal file
20
src/services/OrionBlockchain/schemas/historySchema.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
const historySchema = z.array(z.object(
|
||||
{
|
||||
amount: z.string(),
|
||||
amountNumber: z.string(),
|
||||
asset: z.string(),
|
||||
assetAddress: z.string(),
|
||||
contractBalance: z.string().optional(),
|
||||
createdAt: z.number(),
|
||||
transactionHash: z.string(),
|
||||
type: z.string(),
|
||||
user: z.string(),
|
||||
walletBalance: z.string().optional(),
|
||||
__v: z.number(),
|
||||
_id: z.string(),
|
||||
},
|
||||
));
|
||||
|
||||
export default historySchema;
|
||||
9
src/services/OrionBlockchain/schemas/index.ts
Normal file
9
src/services/OrionBlockchain/schemas/index.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
export * from './adminPoolsListSchema';
|
||||
export { default as addPoolSchema } from './addPoolSchema';
|
||||
export { default as atomicHistorySchema } from './atomicHistorySchema';
|
||||
export { default as checkRedeemOrderSchema } from './checkRedeemOrderSchema';
|
||||
export { default as historySchema } from './historySchema';
|
||||
export { default as IDOSchema } from './IDOSchema';
|
||||
export { default as infoSchema } from './infoSchema';
|
||||
export { default as poolsConfigSchema } from './poolsConfigSchema';
|
||||
export { default as poolsInfoSchema } from './poolsInfoSchema';
|
||||
16
src/services/OrionBlockchain/schemas/infoSchema.ts
Normal file
16
src/services/OrionBlockchain/schemas/infoSchema.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { z } from 'zod';
|
||||
import { makePartial } from '../../../utils';
|
||||
|
||||
const infoSchema = z.object({
|
||||
chainId: z.number(),
|
||||
chainName: z.string(),
|
||||
exchangeContractAddress: z.string(),
|
||||
oracleContractAddress: z.string(),
|
||||
matcherAddress: z.string(),
|
||||
orderFeePercent: z.number(),
|
||||
assetToAddress: z.record(z.string()).transform(makePartial),
|
||||
assetToDecimals: z.record(z.number()).transform(makePartial),
|
||||
assetToIcons: z.record(z.string()).transform(makePartial).optional(),
|
||||
});
|
||||
|
||||
export default infoSchema;
|
||||
28
src/services/OrionBlockchain/schemas/poolsConfigSchema.ts
Normal file
28
src/services/OrionBlockchain/schemas/poolsConfigSchema.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { z } from 'zod';
|
||||
import { makePartial } from '../../../utils';
|
||||
|
||||
const poolsConfigSchema = z.object({
|
||||
WETHAddress: z.string().optional(),
|
||||
factoryAddress: z.string(),
|
||||
governanceAddress: z.string(),
|
||||
routerAddress: z.string(),
|
||||
votingAddress: z.string(),
|
||||
pools: z.record(
|
||||
z.string(),
|
||||
z.object({
|
||||
lpTokenAddress: z.string(),
|
||||
minQty: z.number().optional(),
|
||||
pricePrecision: z.number().int().optional(),
|
||||
qtyPrecision: z.number().int().optional(),
|
||||
reverted: z.boolean().optional(),
|
||||
rewardToken: z.string().nullable().optional(),
|
||||
state: z.number().int().optional(),
|
||||
rewardTokenDecimals: z.number().int().optional(),
|
||||
stakingRewardFinish: z.number().optional(),
|
||||
stakingRewardAddress: z.string(),
|
||||
vote_rewards_disabled: z.boolean().optional(),
|
||||
}),
|
||||
).transform(makePartial),
|
||||
});
|
||||
|
||||
export default poolsConfigSchema;
|
||||
25
src/services/OrionBlockchain/schemas/poolsInfoSchema.ts
Normal file
25
src/services/OrionBlockchain/schemas/poolsInfoSchema.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
const poolsInfoSchema = z.object({
|
||||
governance: z.object({
|
||||
apr: z.string(),
|
||||
rewardRate: z.string(),
|
||||
totalBalance: z.string(),
|
||||
}),
|
||||
totalRewardRatePerWeek: z.string(),
|
||||
pools: z.record(
|
||||
z.object({
|
||||
currentAPR: z.string(),
|
||||
isUser: z.boolean().optional(),
|
||||
price: z.string(),
|
||||
reserves: z.record(z.string()),
|
||||
totalLiquidityInDollars: z.string(),
|
||||
totalRewardRatePerWeek: z.string(),
|
||||
totalStakedAmountInDollars: z.string(),
|
||||
totalVoted: z.string(),
|
||||
weight: z.string(),
|
||||
}),
|
||||
),
|
||||
});
|
||||
|
||||
export default poolsInfoSchema;
|
||||
63
src/services/OrionBlockchain/ws/index.ts
Normal file
63
src/services/OrionBlockchain/ws/index.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import io from 'socket.io-client';
|
||||
import { z } from 'zod';
|
||||
import balancesSchema from './schemas/balancesSchema';
|
||||
|
||||
const handleBalancesMessage = (
|
||||
rawData: unknown,
|
||||
updateData: (balancesData: z.infer<typeof balancesSchema>) => void,
|
||||
) => {
|
||||
const data = balancesSchema.parse(rawData);
|
||||
updateData(data);
|
||||
};
|
||||
|
||||
type UpdateBalanceDataHandler = (balancesData: z.infer<typeof balancesSchema>) => void;
|
||||
|
||||
export class OrionBlockchainSocketIO {
|
||||
private socket: typeof io.Socket;
|
||||
|
||||
constructor(orionBlockchainWSUrl: string) {
|
||||
const url = new URL(orionBlockchainWSUrl);
|
||||
// https://stackoverflow.com/questions/29511404/connect-to-socket-io-server-with-specific-path-and-namespace
|
||||
this.socket = io(url.origin, {
|
||||
path: `${url.pathname}socket.io`,
|
||||
transports: ['websocket'],
|
||||
autoConnect: false,
|
||||
});
|
||||
}
|
||||
|
||||
connect(updateDataHandler: UpdateBalanceDataHandler) {
|
||||
if (updateDataHandler) {
|
||||
this.socket.on('balanceChange', (data: unknown) => handleBalancesMessage(data, updateDataHandler));
|
||||
this.socket.on('balances', (data: unknown) => handleBalancesMessage(data, updateDataHandler));
|
||||
}
|
||||
this.socket.connect();
|
||||
}
|
||||
|
||||
close() {
|
||||
this.socket.removeAllListeners();
|
||||
this.socket.close();
|
||||
}
|
||||
|
||||
resetConnection() {
|
||||
// Because Orion Blockchain does not have a subscription / unsubscribe system
|
||||
// Only way to "unsubscribe" is reset connection
|
||||
this.socket.disconnect();
|
||||
this.socket.open();
|
||||
}
|
||||
|
||||
subscribeBalancesUpdate(walletAddress: string) {
|
||||
if (this.socket.connected) {
|
||||
this.socket.emit('clientAddress', walletAddress);
|
||||
} else {
|
||||
this.socket.on('connect', () => {
|
||||
this.socket.emit('clientAddress', walletAddress);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
updateAllBalances(walletAddress: string) {
|
||||
this.socket.emit('getAllBalances', walletAddress);
|
||||
}
|
||||
}
|
||||
|
||||
export * as schemas from './schemas';
|
||||
10
src/services/OrionBlockchain/ws/schemas/balancesSchema.ts
Normal file
10
src/services/OrionBlockchain/ws/schemas/balancesSchema.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { z } from 'zod';
|
||||
import { makePartial } from '../../../../utils';
|
||||
|
||||
const balancesSchema = z.object({
|
||||
contractBalances: z.record(z.string()).transform(makePartial).optional(),
|
||||
walletBalances: z.record(z.string()).transform(makePartial),
|
||||
allowances: z.record(z.string()).transform(makePartial).optional(),
|
||||
});
|
||||
|
||||
export default balancesSchema;
|
||||
1
src/services/OrionBlockchain/ws/schemas/index.ts
Normal file
1
src/services/OrionBlockchain/ws/schemas/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { default as balancesSchema } from './balancesSchema';
|
||||
45
src/services/PriceFeed/index.ts
Normal file
45
src/services/PriceFeed/index.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { fetchJsonWithValidation } from '../../fetchWithValidation';
|
||||
import candlesSchema from './schemas/candlesSchema';
|
||||
|
||||
class PriceFeed {
|
||||
private apiUrl: string;
|
||||
|
||||
constructor(apiUrl: string) {
|
||||
this.apiUrl = apiUrl;
|
||||
}
|
||||
|
||||
getCandles(
|
||||
symbol: string,
|
||||
timeStart: number,
|
||||
timeEnd: number,
|
||||
interval: '5m' | '30m' | '1h' | '1d',
|
||||
exchange: string,
|
||||
) {
|
||||
const url = new URL(`https://${this.apiUrl}/candles/candles`);
|
||||
url.searchParams.append('symbol', symbol);
|
||||
url.searchParams.append('timeStart', timeStart.toString());
|
||||
url.searchParams.append('timeEnd', timeEnd.toString());
|
||||
url.searchParams.append('interval', interval);
|
||||
url.searchParams.append('exchange', exchange);
|
||||
|
||||
return fetchJsonWithValidation(
|
||||
url.toString(),
|
||||
candlesSchema,
|
||||
);
|
||||
}
|
||||
|
||||
get candlesUrl() { return `https://${this.apiUrl}/candles/candles`; }
|
||||
|
||||
get allTickersWSUrl() { return `wss://${this.apiUrl}/ws2/allTickers`; }
|
||||
|
||||
get tickerWSUrl() { return `wss://${this.apiUrl}/ws2/ticker/`; }
|
||||
|
||||
get lastPriceWSUrl() { return `wss://${this.apiUrl}/ws2/lastPrice/`; }
|
||||
}
|
||||
|
||||
export * as schemas from './schemas';
|
||||
export * as ws from './ws';
|
||||
|
||||
export {
|
||||
PriceFeed,
|
||||
};
|
||||
18
src/services/PriceFeed/schemas/candlesSchema.ts
Normal file
18
src/services/PriceFeed/schemas/candlesSchema.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
const candlesSchema = z.object({
|
||||
candles: z.array(z.object({
|
||||
close: z.string(),
|
||||
high: z.string(),
|
||||
low: z.string(),
|
||||
open: z.string(),
|
||||
time: z.number(),
|
||||
timeEnd: z.number(),
|
||||
timeStart: z.number(),
|
||||
volume: z.string(),
|
||||
})),
|
||||
timeStart: z.number(),
|
||||
timeEnd: z.number(),
|
||||
});
|
||||
|
||||
export default candlesSchema;
|
||||
1
src/services/PriceFeed/schemas/index.ts
Normal file
1
src/services/PriceFeed/schemas/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { default as candlesSchema } from './candlesSchema';
|
||||
32
src/services/PriceFeed/ws/PriceFeedAllTickersWS.ts
Normal file
32
src/services/PriceFeed/ws/PriceFeedAllTickersWS.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import WebsocketHeartbeatJs from 'websocket-heartbeat-js';
|
||||
import { z } from 'zod';
|
||||
import tickerInfoSchema from './schemas/tickerInfoSchema';
|
||||
|
||||
const schema = z.array(z.union([
|
||||
z.number(),
|
||||
tickerInfoSchema,
|
||||
]));
|
||||
export default class PriceFeedAllTickersWS {
|
||||
private pairsWebSocket: WebsocketHeartbeatJs;
|
||||
|
||||
constructor(
|
||||
url: string,
|
||||
updateData: (pairs: z.infer<typeof tickerInfoSchema>[]) => void,
|
||||
) {
|
||||
this.pairsWebSocket = new WebsocketHeartbeatJs({ url });
|
||||
|
||||
this.pairsWebSocket.onmessage = (e) => {
|
||||
if (e.data === 'pong') return;
|
||||
const json = JSON.parse(e.data);
|
||||
const data = schema.parse(json);
|
||||
data.shift(); // Unnecessary timestamp
|
||||
const tickersData = z.array(tickerInfoSchema).parse(data);
|
||||
|
||||
updateData(tickersData);
|
||||
};
|
||||
}
|
||||
|
||||
kill() {
|
||||
this.pairsWebSocket.close();
|
||||
}
|
||||
}
|
||||
31
src/services/PriceFeed/ws/PriceFeedLastPriceWS.ts
Normal file
31
src/services/PriceFeed/ws/PriceFeedLastPriceWS.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import WebsocketHeartbeatJs from 'websocket-heartbeat-js';
|
||||
import { z } from 'zod';
|
||||
|
||||
const schema = z.tuple([
|
||||
z.number(), // unix timestamp
|
||||
z.string(), // pair
|
||||
z.number(), // price
|
||||
]);
|
||||
export default class PriceFeedLastPriceWS {
|
||||
private pairsWebSocket: WebsocketHeartbeatJs;
|
||||
|
||||
constructor(
|
||||
url: string,
|
||||
pair: string,
|
||||
updateData: (price: number) => void,
|
||||
) {
|
||||
this.pairsWebSocket = new WebsocketHeartbeatJs({ url: url + pair });
|
||||
|
||||
this.pairsWebSocket.onmessage = (e) => {
|
||||
if (e.data === 'pong') return;
|
||||
const json = JSON.parse(e.data);
|
||||
const [,, price] = schema.parse(json);
|
||||
|
||||
updateData(price);
|
||||
};
|
||||
}
|
||||
|
||||
kill() {
|
||||
this.pairsWebSocket.close();
|
||||
}
|
||||
}
|
||||
35
src/services/PriceFeed/ws/PriceFeedTickerWS.ts
Normal file
35
src/services/PriceFeed/ws/PriceFeedTickerWS.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import WebsocketHeartbeatJs from 'websocket-heartbeat-js';
|
||||
import { z } from 'zod';
|
||||
import tickerInfoSchema from './schemas/tickerInfoSchema';
|
||||
|
||||
const schema = z.tuple([
|
||||
z.number(), // timestamp
|
||||
tickerInfoSchema,
|
||||
]);
|
||||
|
||||
export default class PriceFeedTickerWS {
|
||||
priceWebSocket: WebsocketHeartbeatJs;
|
||||
|
||||
constructor(
|
||||
symbol: string,
|
||||
url: string,
|
||||
updateData: (pair: z.infer<typeof tickerInfoSchema>) => void,
|
||||
) {
|
||||
this.priceWebSocket = new WebsocketHeartbeatJs({
|
||||
url: `${url}${symbol}`,
|
||||
});
|
||||
|
||||
this.priceWebSocket.onmessage = (e) => {
|
||||
if (e.data === 'pong') return;
|
||||
const data = JSON.parse(e.data);
|
||||
const [, tickerData] = schema.parse(data);
|
||||
|
||||
if (tickerData === undefined) return;
|
||||
updateData(tickerData);
|
||||
};
|
||||
}
|
||||
|
||||
kill() {
|
||||
this.priceWebSocket.close();
|
||||
}
|
||||
}
|
||||
5
src/services/PriceFeed/ws/index.ts
Normal file
5
src/services/PriceFeed/ws/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export { default as PriceFeedAllTickersWS } from './PriceFeedAllTickersWS';
|
||||
export { default as PriceFeedTickerWS } from './PriceFeedTickerWS';
|
||||
export { default as PriceFeedLastPriceWS } from './PriceFeedLastPriceWS';
|
||||
|
||||
export * as schemas from './schemas';
|
||||
1
src/services/PriceFeed/ws/schemas/index.ts
Normal file
1
src/services/PriceFeed/ws/schemas/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { default as tickerInfoSchema } from './tickerInfoSchema';
|
||||
12
src/services/PriceFeed/ws/schemas/tickerInfoSchema.ts
Normal file
12
src/services/PriceFeed/ws/schemas/tickerInfoSchema.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
const tickerInfoSchema = z.tuple([
|
||||
z.string(), // pair name
|
||||
z.string(), // lastPrice
|
||||
z.string(), // openPrice
|
||||
z.string(), // high price
|
||||
z.string(), // low price
|
||||
z.string(), // volume 24h
|
||||
]);
|
||||
|
||||
export default tickerInfoSchema;
|
||||
3
src/services/index.ts
Normal file
3
src/services/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export * as orionAggregator from './OrionAggregator';
|
||||
export * as orionBlockchain from './OrionBlockchain';
|
||||
export * as priceFeed from './PriceFeed';
|
||||
129
src/types.ts
Normal file
129
src/types.ts
Normal file
@@ -0,0 +1,129 @@
|
||||
import BigNumber from 'bignumber.js';
|
||||
|
||||
export interface Order {
|
||||
senderAddress: string; // address
|
||||
matcherAddress: string; // address
|
||||
baseAsset: string; // address
|
||||
quoteAsset: string; // address
|
||||
matcherFeeAsset: string; // address
|
||||
amount: number; // uint64
|
||||
price: number; // uint64
|
||||
matcherFee: number; // uint64
|
||||
nonce: number; // uint64
|
||||
expiration: number; // uint64
|
||||
buySide: number; // uint8, 1=buy, 0=sell
|
||||
isPersonalSign: boolean; // bool
|
||||
}
|
||||
export interface SignedOrder extends Order {
|
||||
id: string; // hash of Order (it's not part of order structure in smart-contract)
|
||||
signature: string; // bytes
|
||||
needWithdraw?: boolean; // bool (not supported yet by smart-contract)
|
||||
}
|
||||
|
||||
export interface CancelOrderRequest {
|
||||
id: number | string;
|
||||
senderAddress: string;
|
||||
isPersonalSign: boolean;
|
||||
}
|
||||
|
||||
export interface SignedCancelOrderRequest extends CancelOrderRequest {
|
||||
id: number | string;
|
||||
senderAddress: string;
|
||||
signature: string;
|
||||
}
|
||||
|
||||
export interface Pair {
|
||||
name: string;
|
||||
baseCurrency: string;
|
||||
quoteCurrency: string;
|
||||
lastPrice: string;
|
||||
openPrice: string;
|
||||
change24h: string;
|
||||
high: string;
|
||||
low: string;
|
||||
vol24h: string;
|
||||
}
|
||||
|
||||
type SwapInfoBase = {
|
||||
swapRequestId: string,
|
||||
assetIn: string,
|
||||
assetOut: string,
|
||||
amountIn: number,
|
||||
amountOut: number,
|
||||
minAmounIn: number,
|
||||
minAmounOut: number,
|
||||
|
||||
path: string[],
|
||||
poolOptimal: boolean,
|
||||
|
||||
price?: number,
|
||||
marketPrice?: number,
|
||||
orderInfo?: {
|
||||
pair: string,
|
||||
side: 'BUY' | 'SELL',
|
||||
amount: number,
|
||||
safePrice: number,
|
||||
}
|
||||
}
|
||||
|
||||
export type SwapInfoByAmountIn = SwapInfoBase & {
|
||||
kind: 'exactSpend',
|
||||
availableAmountIn?: number,
|
||||
marketAmountOut?: number,
|
||||
}
|
||||
|
||||
export type SwapInfoByAmountOut = SwapInfoBase & {
|
||||
kind: 'exactReceive',
|
||||
marketAmountIn?: number,
|
||||
availableAmountOut?: number,
|
||||
}
|
||||
|
||||
export type SwapInfo = SwapInfoByAmountIn | SwapInfoByAmountOut;
|
||||
|
||||
export enum SupportedChainId {
|
||||
MAINNET = '0x1',
|
||||
ROPSTEN = '0x3',
|
||||
FANTOM_OPERA = '0xfa',
|
||||
|
||||
FANTOM_TESTNET = '0xfa2',
|
||||
BSC = '0x38',
|
||||
BSC_TESTNET = '0x61',
|
||||
|
||||
// For testing and debug purpose
|
||||
BROKEN = '0x0',
|
||||
}
|
||||
|
||||
const balanceTypes = ['exchange', 'wallet'] as const;
|
||||
|
||||
export type Source = typeof balanceTypes[number];
|
||||
export type Asset = {
|
||||
name: string;
|
||||
address: string;
|
||||
}
|
||||
export type BalanceRequirement = {
|
||||
readonly reason: string,
|
||||
readonly asset: Asset,
|
||||
readonly amount: string,
|
||||
readonly sources: Source[],
|
||||
readonly spenderAddress?: string;
|
||||
}
|
||||
|
||||
export type AggregatedBalanceRequirement = {
|
||||
readonly asset: Asset,
|
||||
readonly sources: Source[],
|
||||
readonly spenderAddress?: string;
|
||||
items: Partial<Record<string, string>>,
|
||||
}
|
||||
|
||||
export type Approve = {
|
||||
readonly targetAmount: BigNumber.Value,
|
||||
readonly spenderAddress: string
|
||||
}
|
||||
|
||||
export type BalanceIssue = {
|
||||
readonly asset: Asset,
|
||||
readonly message: string;
|
||||
readonly sources: Source[],
|
||||
readonly resetRequired?: boolean;
|
||||
readonly approves?: Approve[];
|
||||
}
|
||||
36
src/utils/calculateFeeInFeeAsset.ts
Normal file
36
src/utils/calculateFeeInFeeAsset.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import BigNumber from 'bignumber.js';
|
||||
import { FILL_ORDERS_GAS_LIMIT } from '../constants';
|
||||
import calculateNetworkFeeInFeeAsset from './calculateNetworkFeeInFeeAsset';
|
||||
import calculateOrionFeeInFeeAsset from './calculateOrionFeeInFeeAsset';
|
||||
|
||||
const calculateFeeInFeeAsset = (
|
||||
amount: BigNumber.Value,
|
||||
feeAssetPriceInOrn: BigNumber.Value,
|
||||
baseAssetPriceInOrn: BigNumber.Value,
|
||||
baseCurrencyPriceInOrn: BigNumber.Value,
|
||||
gasPriceGwei: BigNumber.Value,
|
||||
feePercent: BigNumber.Value,
|
||||
) => {
|
||||
const orionFeeInFeeAsset = calculateOrionFeeInFeeAsset(
|
||||
amount,
|
||||
feeAssetPriceInOrn,
|
||||
baseAssetPriceInOrn,
|
||||
feePercent,
|
||||
);
|
||||
const networkFeeInFeeAsset = calculateNetworkFeeInFeeAsset(
|
||||
gasPriceGwei,
|
||||
FILL_ORDERS_GAS_LIMIT,
|
||||
baseCurrencyPriceInOrn,
|
||||
feeAssetPriceInOrn,
|
||||
);
|
||||
|
||||
return {
|
||||
orionFeeInFeeAsset,
|
||||
networkFeeInFeeAsset,
|
||||
totalFeeInFeeAsset: new BigNumber(orionFeeInFeeAsset)
|
||||
.plus(networkFeeInFeeAsset)
|
||||
.toString(),
|
||||
};
|
||||
};
|
||||
|
||||
export default calculateFeeInFeeAsset;
|
||||
13
src/utils/calculateNetworkFee.ts
Normal file
13
src/utils/calculateNetworkFee.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import BigNumber from 'bignumber.js';
|
||||
import { ethers } from 'ethers';
|
||||
import { NATIVE_CURRENCY_PRECISION } from '../constants/precisions';
|
||||
|
||||
export default function calculateNetworkFee(
|
||||
gasPriceGwei: BigNumber.Value,
|
||||
gasLimit: BigNumber.Value,
|
||||
) {
|
||||
const networkFeeGwei = new BigNumber(gasPriceGwei).multipliedBy(gasLimit);
|
||||
|
||||
const bn = new BigNumber(ethers.utils.parseUnits(networkFeeGwei.toString(), 'gwei').toString());
|
||||
return bn.div(new BigNumber(10).pow(NATIVE_CURRENCY_PRECISION)).toString();
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user