massive refactor

This commit is contained in:
TheJuze
2024-05-30 16:59:39 +03:00
parent afb8049589
commit 761a9cc180
20 changed files with 249 additions and 98 deletions

View File

@@ -9,10 +9,10 @@ import {
INTERNAL_PROTOCOL_PRECISION,
NATIVE_CURRENCY_PRECISION,
SWAP_THROUGH_ORION_POOL_GAS_LIMIT
} from '../../constants/index.js';
} from '../../constants';
import getNativeCryptocurrencyName from '../../utils/getNativeCryptocurrencyName.js';
import { calculateFeeInFeeAsset, denormalizeNumber, normalizeNumber } from '../../utils/index.js';
import { signOrder } from '../../crypt/index.js';
import { signOrder } from '../../crypt';
import type orderSchema from '../../services/Aggregator/schemas/orderSchema.js';
import type { z } from 'zod';
import { simpleFetch } from 'simple-typed-fetch';

View File

@@ -11,7 +11,7 @@ import {
} from '../../constants';
import getNativeCryptocurrencyName from '../../utils/getNativeCryptocurrencyName.js';
import { calculateFeeInFeeAsset, denormalizeNumber, normalizeNumber } from '../../utils/index.js';
import { signOrder } from '../../crypt/index.js';
import { signOrder } from '../../crypt';
import type orderSchema from '../../services/Aggregator/schemas/orderSchema.js';
import type { z } from 'zod';
import type { SwapLimitParams } from './swapLimit.js';

View File

@@ -1,11 +1,11 @@
export { default as cancelOrderTypes } from './cancelOrderTypes.js';
export { default as orderStatuses } from './orderStatuses.js';
export { default as orderTypes } from './orderTypes.js';
export { default as subOrderStatuses } from './subOrderStatuses.js';
export { default as networkCodes } from './networkCodes.js';
export { default as exchanges } from './exchanges.js';
export { default as exchangesMap } from './exchangesMap.js';
export * from './orderTypes';
export * from './chains.js';
export * from './precisions.js';
export * from './gasLimits.js';

View File

@@ -1,23 +0,0 @@
export 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' },
],
CrossChainOrder: [
{ name: 'limitOrder', type: 'Order' },
{ name: 'chainId', type: 'uint24' },
{ name: 'secretHash', type: 'bytes32' },
{ name: 'lockOrderExpiration', type: 'uint64' },
]
}
export default ORDER_TYPES;

View File

@@ -0,0 +1,11 @@
import {ORDER_TYPE} from './orderTypes';
export const CROSS_CHAIN_ORDER_TYPES = {
Order: ORDER_TYPE,
CrossChainOrder: [
{name: 'limitOrder', type: 'Order'},
{name: 'chainId', type: 'uint24'},
{name: 'secretHash', type: 'bytes32'},
{name: 'lockOrderExpiration', type: 'uint64'},
]
}

View File

@@ -0,0 +1,3 @@
export * from './crossChainOrderTypes';
export * from './lockOrderTypes';
export { ORDER_TYPES } from './orderTypes';

View File

@@ -0,0 +1,27 @@
export const ORDER_TYPE = [
{ 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 const ORDER_TYPES = {
Order: ORDER_TYPE
}
export const CROSS_CHAIN_ORDER_TYPES = {
Order: ORDER_TYPE,
CrossChainOrder: [
{ name: 'limitOrder', type: 'Order' },
{ name: 'chainId', type: 'uint24' },
{ name: 'secretHash', type: 'bytes32' },
{ name: 'lockOrderExpiration', type: 'uint64' },
]
}

View File

@@ -1,5 +1,5 @@
import type { SupportedChainId } from '../types.js';
import eip712DomainData from '../config/eip712DomainData.json' assert { type: 'json' };
import eip712DomainData from '../config/eip712DomainData.json' assert {type: 'json'};
import eip712DomainSchema from '../config/schemas/eip712DomainSchema.js';
const EIP712Domain = eip712DomainSchema.parse(eip712DomainData);
@@ -19,7 +19,7 @@ function removeUndefined<T>(obj: Record<string, T | undefined>) {
*/
const getDomainData = (chainId: SupportedChainId) => ({
...removeUndefined(EIP712Domain),
chainId: Number(chainId), // check if it broke
chainId: Number(chainId),
});
export default getDomainData;

View File

@@ -1,12 +1,12 @@
import { ethers, keccak256 } from 'ethers';
import type { SupportedChainId, SignedOrder } from '../types.js';
import type { SupportedChainId, CrossChainOrder } from '../../types';
const ORDER_TYPEHASH =
'0xb5132db62dfceb466f2f8aee7a039db36a99772e5a9771d28388a5f9baad7c54';
const CROSS_CHAIN_ORDER_TYPEHASH =
'0xc4666edeecc42a94cf6b87f39e1ca967792e6d738224365e54d7d06ec632b05c';
export function getOrderHash(order: Omit<SignedOrder, 'id'>, chainId: SupportedChainId) {
export function getOrderHash(order: CrossChainOrder, chainId: SupportedChainId) {
const abiCoder = ethers.AbiCoder.defaultAbiCoder();
// Generate the orderParamsHash

View File

@@ -1,5 +1,5 @@
import { ethers } from 'ethers';
import type { LockOrder } from '../types.js';
import type { LockOrder } from '../../types';
export const hashLockOrder = (order: LockOrder) => ethers.solidityPackedKeccak256(
[
@@ -10,11 +10,9 @@ export const hashLockOrder = (order: LockOrder) => ethers.solidityPackedKeccak25
'uint64',
'uint64',
'uint64',
'string'
],
[
'0x03',
order.user,
order.sender,
order.expiration,
order.asset,

View File

@@ -0,0 +1,54 @@
import { ethers, keccak256 } from 'ethers';
import type { Order } from '../../types';
const ORDER_TYPEHASH = '0xb5132db62dfceb466f2f8aee7a039db36a99772e5a9771d28388a5f9baad7c54'
export default function getOrderHash(order: Order) {
const abiCoder = ethers.AbiCoder.defaultAbiCoder()
const {
senderAddress,
matcherAddress,
baseAsset,
quoteAsset,
matcherFeeAsset,
amount,
price,
matcherFee,
nonce,
expiration,
buySide
} = order
const orderBytes = abiCoder.encode(
[
'bytes32',
'address',
'address',
'address',
'address',
'address',
'uint64',
'uint64',
'uint64',
'uint64',
'uint64',
'uint8'
],
[
ORDER_TYPEHASH,
senderAddress,
matcherAddress,
baseAsset,
quoteAsset,
matcherFeeAsset,
amount,
price,
matcherFee,
nonce,
expiration,
buySide
]
)
return keccak256(orderBytes)
}

View File

@@ -0,0 +1,3 @@
export * from './hashCrossChainOrder';
export * from './hashOrder';
export * from './hashLockOrder';

View File

@@ -1,3 +1,4 @@
export { default as signCancelOrder } from './signCancelOrder.js';
export { signOrder, type SignOrderProps } from './signOrder.js';
export { signCrossChainOrder, type SignCrossChainOrderProps } from './signCrossChainOrder.js';
export { signLockOrder, type SignLockOrderProps } from './signLockOrder.js';

View File

@@ -0,0 +1,111 @@
import { BigNumber } from 'bignumber.js';
import { ethers, keccak256 } from 'ethers';
import { INTERNAL_PROTOCOL_PRECISION } from '../constants';
import { CROSS_CHAIN_ORDER_TYPES } from '../constants/orderTypes/orderTypes';
import type { Order, SignedCrossChainOrder, SupportedChainId } from '../types.js';
import normalizeNumber from '../utils/normalizeNumber.js';
import getDomainData from './getDomainData.js';
import generateSecret from '../utils/generateSecret';
import { getOrderHash } from './hashOrders';
const DAY = 24 * 60 * 60 * 1000;
const LOCK_ORDER_EXPIRATION = 4 * DAY;
const DEFAULT_EXPIRATION = 29 * DAY;
export type SignCrossChainOrderProps = {
baseAssetAddress: string
quoteAssetAddress: string
side: 'BUY' | 'SELL'
price: BigNumber.Value
amount: BigNumber.Value
matcherFee: BigNumber.Value
senderAddress: string
matcherAddress: string
serviceFeeAssetAddress: string
signer: ethers.Signer
chainId: SupportedChainId
targetChainId?: SupportedChainId
}
export const signCrossChainOrder = async ({
amount,
signer,
side,
baseAssetAddress,
quoteAssetAddress,
serviceFeeAssetAddress,
matcherFee,
matcherAddress,
senderAddress,
targetChainId,
chainId,
price
}: SignCrossChainOrderProps): Promise<SignedCrossChainOrder> => {
const nonce = Date.now();
const expiration = nonce + DEFAULT_EXPIRATION;
const lockOrderExpiration = nonce + LOCK_ORDER_EXPIRATION;
const order: Order = {
senderAddress,
matcherAddress,
baseAsset: baseAssetAddress,
quoteAsset: quoteAssetAddress,
matcherFeeAsset: serviceFeeAssetAddress,
amount: Number(normalizeNumber(
amount,
INTERNAL_PROTOCOL_PRECISION,
BigNumber.ROUND_FLOOR,
)),
price: Number(normalizeNumber(
price,
INTERNAL_PROTOCOL_PRECISION,
BigNumber.ROUND_FLOOR,
)),
matcherFee: Number(normalizeNumber(
matcherFee,
INTERNAL_PROTOCOL_PRECISION,
BigNumber.ROUND_CEIL, // ROUND_CEIL because we don't want get "not enough fee" error
)),
nonce,
expiration,
buySide: side === 'BUY' ? 1 : 0
};
const secret = generateSecret();
const secretHash = keccak256(secret);
const crossChainOrder = {
limitOrder: order,
chainId: Number(chainId),
secretHash,
lockOrderExpiration
}
const signature = await signer.signTypedData(
getDomainData(chainId),
CROSS_CHAIN_ORDER_TYPES,
crossChainOrder
);
// 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 = ethers.Signature.from(signature).serialized;
// if (!fixedSignature) throw new Error("Can't sign order");
const signedOrderWithoutId: Omit<SignedCrossChainOrder, 'id'> = {
...order,
signature: fixedSignature,
secret,
secretHash,
targetChainId: Number(targetChainId),
lockOrderExpiration
}
const orderHash = getOrderHash(signedOrderWithoutId, chainId);
const signedCrossChainOrder: SignedCrossChainOrder = {
...signedOrderWithoutId,
id: orderHash
};
return signedCrossChainOrder;
};

View File

@@ -4,8 +4,7 @@ import getDomainData from './getDomainData.js';
import generateSecret from '../utils/generateSecret';
import { BigNumber } from 'bignumber.js';
import normalizeNumber from '../utils/normalizeNumber';
import { INTERNAL_PROTOCOL_PRECISION } from '../constants';
import { LOCK_ORDER_TYPES } from '../constants/lockOrderTypes';
import { INTERNAL_PROTOCOL_PRECISION, LOCK_ORDER_TYPES } from '../constants';
const DEFAULT_EXPIRATION = 29 * 24 * 60 * 60 * 1000; // 29 days
@@ -41,6 +40,7 @@ export const signLockOrder = async ({
BigNumber.ROUND_FLOOR,
)),
targetChainId: Number(targetChainId),
secret,
secretHash
};

View File

@@ -1,16 +1,12 @@
import { BigNumber } from 'bignumber.js';
import { ethers, keccak256 } from 'ethers';
import { INTERNAL_PROTOCOL_PRECISION } from '../constants';
import ORDER_TYPES from '../constants/orderTypes.js';
import { ethers } from 'ethers';
import { INTERNAL_PROTOCOL_PRECISION, ORDER_TYPES } from '../constants';
import type { Order, SignedOrder, SupportedChainId } from '../types.js';
import normalizeNumber from '../utils/normalizeNumber.js';
import getDomainData from './getDomainData.js';
import generateSecret from '../utils/generateSecret';
import { getOrderHash } from './hashOrder';
import hashOrder from './hashOrders/hashOrder';
const DAY = 24 * 60 * 60 * 1000;
const LOCK_ORDER_EXPIRATION = 4 * DAY;
const DEFAULT_EXPIRATION = 29 * DAY;
const DEFAULT_EXPIRATION = 29 * 24 * 60 * 60 * 1000; // 29 days
export type SignOrderProps = {
baseAssetAddress: string
@@ -24,28 +20,23 @@ export type SignOrderProps = {
serviceFeeAssetAddress: string
signer: ethers.Signer
chainId: SupportedChainId
targetChainId?: SupportedChainId
}
export const signOrder = async ({
amount,
signer,
side,
senderAddress,
serviceFeeAssetAddress,
baseAssetAddress,
quoteAssetAddress,
serviceFeeAssetAddress,
matcherFee,
matcherAddress,
senderAddress,
targetChainId,
chainId,
signer,
side,
amount,
price
}: SignOrderProps): Promise<SignedOrder> => {
}: SignOrderProps) => {
const nonce = Date.now();
const expiration = nonce + DEFAULT_EXPIRATION;
const lockOrderExpiration = nonce + LOCK_ORDER_EXPIRATION;
const isCrossChain = targetChainId === undefined || targetChainId !== chainId;
const order: Order = {
senderAddress,
@@ -70,29 +61,13 @@ export const signOrder = async ({
)),
nonce,
expiration,
...(isCrossChain
? {
targetChainId: Number(targetChainId)
}
: {}),
buySide: side === 'BUY' ? 1 : 0
buySide: side === 'BUY' ? 1 : 0,
};
const secret = generateSecret();
const secretHash = keccak256(secret);
const crossChainOrder = {
limitOrder: order,
chainId: Number(chainId),
secretHash,
lockOrderExpiration
}
// TODO: change what to show
const signature = await signer.signTypedData(
getDomainData(chainId),
ORDER_TYPES,
crossChainOrder
order,
);
// https://github.com/poap-xyz/poap-fun/pull/62#issue-928290265
@@ -100,25 +75,11 @@ export const signOrder = async ({
const fixedSignature = ethers.Signature.from(signature).serialized;
// if (!fixedSignature) throw new Error("Can't sign order");
const signedOrderWithoutId: Omit<SignedOrder, 'id'> = {
...order,
signature: fixedSignature,
secret,
secretHash,
...(isCrossChain
? {
targetChainId: Number(targetChainId)
}
: {}),
lockOrderExpiration
}
const orderHash = getOrderHash(signedOrderWithoutId, chainId);
const signedOrder: SignedOrder = {
...signedOrderWithoutId,
id: orderHash
...order,
id: hashOrder(order),
signature: fixedSignature,
};
return signedOrder;
};
export default signOrder;

View File

@@ -14,7 +14,8 @@ import type {
NetworkShortName,
SignedLockOrder,
SignedCancelOrderRequest,
SignedOrder
SignedOrder,
SignedCrossChainOrder
} from '../../types.js';
import {
pairConfigSchema, aggregatedOrderbookSchema,
@@ -211,7 +212,7 @@ class Aggregator {
);
placeOrder = (
signedOrder: SignedOrder,
signedOrder: SignedOrder | SignedCrossChainOrder,
isCreateInternalOrder: boolean,
isReversedOrder?: boolean,
partnerId?: string,

View File

@@ -50,7 +50,9 @@ export type Order = {
expiration: number // uint64
buySide: 0 | 1 // uint8, 1=buy, 0=sell
}
export type CrossOrder = Order & {
export type CrossChainOrder = Order & {
secret: string
secretHash: string // bytes32
targetChainId: number // uint24
lockOrderExpiration: number // uint64
@@ -62,18 +64,20 @@ export type LockOrder = {
asset: string // address(?)
amount: number // uint64
targetChainId: number // uint64
secret: string // bytes32
secretHash: string // bytes32
}
type SignedOrderAdditionalProps = {
signature: string // bytes
secret?: string
secretHash?: string // bytes32
needWithdraw?: boolean // bool (not supported yet by smart-contract)
lockOrderExpiration?: number
}
export type SignedOrder = SignedOrderAdditionalProps & (Order | CrossOrder) & {
export type SignedOrder = SignedOrderAdditionalProps & Order & {
id: string // hash of Order (it's not part of order structure in smart-contract)
}
export type SignedCrossChainOrder = SignedOrderAdditionalProps & CrossChainOrder & {
id: string // hash of Order (it's not part of order structure in smart-contract)
}