diff --git a/package-lock.json b/package-lock.json index 0b4248b..a68cc53 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,18 +1,18 @@ { "name": "@orionprotocol/sdk", - "version": "0.22.0-rc7", + "version": "0.22.0-rc8", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@orionprotocol/sdk", - "version": "0.22.0-rc7", + "version": "0.22.0-rc8", "hasInstallScript": true, "license": "ISC", "dependencies": { "@babel/runtime": "^7.21.0", "@ethersproject/providers": "^5.7.2", - "@orionprotocol/contracts": "1.23.3", + "@orionprotocol/contracts": "1.23.4-rc", "@types/lodash.clonedeep": "^4.5.9", "bignumber.js": "^9.1.1", "bson-objectid": "^2.0.4", @@ -2421,9 +2421,9 @@ } }, "node_modules/@orionprotocol/contracts": { - "version": "1.23.3", - "resolved": "https://registry.npmjs.org/@orionprotocol/contracts/-/contracts-1.23.3.tgz", - "integrity": "sha512-3PBnuiUe//v7COArcm/dzFx71vxW+a9emU4PHi1zBdow+OUAa4WNb+NmNZ3AOjnx2AZKK+gWJY+zKo1zSfAOHQ==" + "version": "1.23.4-rc", + "resolved": "https://registry.npmjs.org/@orionprotocol/contracts/-/contracts-1.23.4-rc.tgz", + "integrity": "sha512-Cd5oMVZzMuQbOqbVBnwUbLXr6jpwOq4MtwoLo/l6T1BxWh/s1hKF8VuIvUJgGbzI0HEg3AGa1DCT4chwe9721Q==" }, "node_modules/@sinclair/typebox": { "version": "0.27.8", @@ -13488,9 +13488,9 @@ } }, "@orionprotocol/contracts": { - "version": "1.23.3", - "resolved": "https://registry.npmjs.org/@orionprotocol/contracts/-/contracts-1.23.3.tgz", - "integrity": "sha512-3PBnuiUe//v7COArcm/dzFx71vxW+a9emU4PHi1zBdow+OUAa4WNb+NmNZ3AOjnx2AZKK+gWJY+zKo1zSfAOHQ==" + "version": "1.23.4-rc", + "resolved": "https://registry.npmjs.org/@orionprotocol/contracts/-/contracts-1.23.4-rc.tgz", + "integrity": "sha512-Cd5oMVZzMuQbOqbVBnwUbLXr6jpwOq4MtwoLo/l6T1BxWh/s1hKF8VuIvUJgGbzI0HEg3AGa1DCT4chwe9721Q==" }, "@sinclair/typebox": { "version": "0.27.8", diff --git a/package.json b/package.json index a50d670..91ee7b2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@orionprotocol/sdk", - "version": "0.22.0-rc7", + "version": "0.22.0-rc8", "description": "Orion Protocol SDK", "main": "./lib/index.cjs", "module": "./lib/index.js", @@ -87,7 +87,7 @@ "dependencies": { "@babel/runtime": "^7.21.0", "@ethersproject/providers": "^5.7.2", - "@orionprotocol/contracts": "1.23.3", + "@orionprotocol/contracts": "1.23.4-rc", "@types/lodash.clonedeep": "^4.5.9", "bignumber.js": "^9.1.1", "bson-objectid": "^2.0.4", diff --git a/src/constants/orderTypes.ts b/src/constants/orderTypes.ts index a420be2..699190f 100644 --- a/src/constants/orderTypes.ts +++ b/src/constants/orderTypes.ts @@ -1,10 +1,4 @@ export const ORDER_TYPES = { - CrossChainOrder: [ - { name: 'limitOrder', type: 'Order' }, - { name: 'chainId', type: 'uint24' }, - { name: 'secretHash', type: 'bytes32' }, - { name: 'lockOrderExpiration', type: 'uint64' }, - ], Order: [ { name: 'senderAddress', type: 'address' }, { name: 'matcherAddress', type: 'address' }, @@ -17,6 +11,12 @@ export const ORDER_TYPES = { { 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' }, ] } diff --git a/src/crypt/hashOrder.ts b/src/crypt/hashOrder.ts index 5b3cd6e..98a1365 100644 --- a/src/crypt/hashOrder.ts +++ b/src/crypt/hashOrder.ts @@ -1,56 +1,59 @@ import { ethers, keccak256 } from 'ethers'; -import type { Order } from '../types.js'; -import generateSecret from '../utils/generateSecret'; -import getDomainData from './getDomainData'; -import type { SupportedChainId } from '../../lib'; +import type { SupportedChainId, SignedOrder } from '../types.js'; -const CROSS_CHAIN_ORDER_TYPEHASH = '0xcb145a2347f48eab4e3341a245f53da2e686e47ef421c89a6b40dde27a063c3f' -const EIP712_DOMAIN_TYPEHASH = '0xa604fff5a27d5951f334ccda7abff3286a8af29caeeb196a6f2b40a1dce7612b'; +const ORDER_TYPEHASH = + '0xb5132db62dfceb466f2f8aee7a039db36a99772e5a9771d28388a5f9baad7c54'; +const CROSS_CHAIN_ORDER_TYPEHASH = + '0xc4666edeecc42a94cf6b87f39e1ca967792e6d738224365e54d7d06ec632b05c'; -export default function getOrderHash(order: Order, chainId: SupportedChainId) { - const abiCoder = ethers.AbiCoder.defaultAbiCoder() - const secret = generateSecret(); - const secretHash = ethers.keccak256(secret); +export function getOrderHash(order: Omit, chainId: SupportedChainId) { + const abiCoder = ethers.AbiCoder.defaultAbiCoder(); // Generate the orderParamsHash - const orderParamsHash = keccak256((abiCoder.encode( - ['address', 'address', 'address', 'address', 'address', 'uint64', 'uint64', 'uint64', 'uint64', 'uint64', 'uint8'], - [ - order.senderAddress, - order.matcherAddress, - order.baseAsset, - order.quoteAsset, - order.matcherFeeAsset, - order.amount, - order.price, - order.matcherFee, - order.nonce, - order.expiration, - order.buySide - ] - ))); - - // Generate the full crossChainOrder hash - const orderHash = ethers.keccak256(ethers.AbiCoder.defaultAbiCoder().encode( - ['bytes32', 'bytes32', 'uint24', 'bytes32', 'uint64'], - [CROSS_CHAIN_ORDER_TYPEHASH, orderParamsHash, 97, '0x74a00e5cceb68d791486ddb9ea83bb8245eca22f67cb0ea81342f6eff8bf6e51', 1718955340461] - )); - - const domainData = getDomainData(chainId); - // Generate the full crossChainOrder hash - const domainSeparator = ethers.keccak256(ethers.AbiCoder.defaultAbiCoder().encode( - ['bytes32', 'bytes32', 'bytes32', 'uint256', 'bytes32'], - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - // eslint-disable-next-line @typescript-eslint/consistent-type-assertions - [EIP712_DOMAIN_TYPEHASH, ethers.keccak256(ethers.toUtf8Bytes(domainData?.name as string)), ethers.keccak256(ethers.toUtf8Bytes(domainData?.version as string)), Number(domainData.chainId), domainData.salt] - )); - - const digest = ethers.solidityPackedKeccak256( - ['bytes', 'bytes32', 'bytes32'], ['0x1901', domainSeparator, orderHash] + const limitOrderHash = keccak256( + abiCoder.encode( + [ + 'bytes32', + 'address', + 'address', + 'address', + 'address', + 'address', + 'uint64', + 'uint64', + 'uint64', + 'uint64', + 'uint64', + 'uint8', + ], + [ + ORDER_TYPEHASH, + order.senderAddress, + order.matcherAddress, + order.baseAsset, + order.quoteAsset, + order.matcherFeeAsset, + order.amount, + order.price, + order.matcherFee, + order.nonce, + order.expiration, + order.buySide, + ] + ) + ); + const orderHash = keccak256( + abiCoder.encode( + ['bytes32', 'bytes32', 'uint24', 'bytes32', 'uint64'], + [ + CROSS_CHAIN_ORDER_TYPEHASH, + limitOrderHash, + Number(chainId), + order.secretHash, + order.lockOrderExpiration, + ] + ) ); - console.log({ secretHash }, { orderParamsHash }, { orderHash }, { domainData }, { domainSeparator }, { digest }); - - return { secret, secretHash, orderHash }; + return orderHash } diff --git a/src/crypt/signOrder.ts b/src/crypt/signOrder.ts index fb40160..45ba6ed 100644 --- a/src/crypt/signOrder.ts +++ b/src/crypt/signOrder.ts @@ -6,6 +6,7 @@ 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'; const DEFAULT_EXPIRATION = 29 * 24 * 60 * 60 * 1000; // 29 days @@ -68,7 +69,7 @@ export const signOrder = async ({ expiration, ...(isCrossChain ? { - targetChainId + targetChainId: Number(targetChainId) } : {}), buySide: side === 'BUY' ? 1 : 0 @@ -77,26 +78,6 @@ export const signOrder = async ({ const secret = generateSecret(); const secretHash = keccak256(secret); - const abiCoder = ethers.AbiCoder.defaultAbiCoder(); - - // Generate the orderParamsHash - const limitOrderHash = keccak256((abiCoder.encode( - ['address', 'address', 'address', 'address', 'address', 'uint64', 'uint64', 'uint64', 'uint64', 'uint64', 'uint8'], - [ - order.senderAddress, - order.matcherAddress, - order.baseAsset, - order.quoteAsset, - order.matcherFeeAsset, - order.amount, - order.price, - order.matcherFee, - order.nonce, - order.expiration, - order.buySide - ] - ))); - const crossChainOrder = { limitOrder: order, chainId: Number(chainId), @@ -104,19 +85,11 @@ export const signOrder = async ({ lockOrderExpiration: expiration // TODO: change to fillAndLockAtomic data } - // Generate the full crossChainOrder hash - // const orderHash = ethers.keccak256(ethers.AbiCoder.defaultAbiCoder().encode( - // ['bytes32', 'bytes32', 'uint24', 'bytes32', 'uint64'], - // [CROSS_CHAIN_ORDER_TYPEHASH, orderParamsHash, 97, '0x74a00e5cceb68d791486ddb9ea83bb8245eca22f67cb0ea81342f6eff8bf6e51', 1718955340461] - // )); - // TODO: change what to show const signature = await signer.signTypedData( getDomainData(chainId), ORDER_TYPES, - { - crossChainOrder, - } + crossChainOrder ); // https://github.com/poap-xyz/poap-fun/pull/62#issue-928290265 @@ -124,20 +97,23 @@ export const signOrder = async ({ const fixedSignature = ethers.Signature.from(signature).serialized; // if (!fixedSignature) throw new Error("Can't sign order"); - // const { orderHash, secret, secretHash } = hashOrder(limitOrder, chainId); - - const signedOrder: SignedOrder = { + const signedOrderWithoutId: Omit = { ...order, - id: limitOrderHash, // TODO: change to orderHash signature: fixedSignature, + secret, + secretHash, ...(isCrossChain ? { - secret, - secretHash, - targetChainId: Number(targetChainId), - lockOrderExpiration: expiration + targetChainId: Number(targetChainId) } - : {}) + : {}), + lockOrderExpiration: expiration + } + const orderHash = getOrderHash(signedOrderWithoutId, chainId); + + const signedOrder: SignedOrder = { + ...signedOrderWithoutId, + id: orderHash }; return signedOrder; }; diff --git a/src/services/Aggregator/index.ts b/src/services/Aggregator/index.ts index 29edd71..8e1cf10 100644 --- a/src/services/Aggregator/index.ts +++ b/src/services/Aggregator/index.ts @@ -231,6 +231,14 @@ class Aggregator { const url = new URL(`${this.apiUrl}/api/v1/order/${isCreateInternalOrder ? 'internal' : ''}`); + const body = { + ...signedOrder, + lockExpiration: signedOrder.lockOrderExpiration, + rawExchangeRestrictions + } + + delete body.lockOrderExpiration; + return fetchWithValidation( url.toString(), z.object({ @@ -246,7 +254,7 @@ class Aggregator { { headers, method: 'POST', - body: JSON.stringify({ ...signedOrder, rawExchangeRestrictions }), + body: JSON.stringify(body), }, errorSchema, ); diff --git a/src/types.ts b/src/types.ts index 3f2445e..a47116d 100644 --- a/src/types.ts +++ b/src/types.ts @@ -70,6 +70,7 @@ type SignedOrderAdditionalProps = { secret?: string secretHash?: string // bytes32 needWithdraw?: boolean // bool (not supported yet by smart-contract) + lockOrderExpiration?: number } export type SignedOrder = SignedOrderAdditionalProps & (Order | CrossOrder) & {