From 1d90b1fb37d5a2a359372300c9e4c9a9b29b4459 Mon Sep 17 00:00:00 2001 From: phroi <90913182+phroi@users.noreply.github.com> Date: Thu, 17 Oct 2024 23:01:41 +0700 Subject: [PATCH] Patch Confusion Attack on LO --- package.json | 8 +- pnpm-lock.yaml | 300 +++++++++++++++-------------- src/limit_order.ts | 461 ++++++++++++++++++++++++++++++++------------- 3 files changed, 492 insertions(+), 277 deletions(-) diff --git a/package.json b/package.json index b4e7ae9..f2635be 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@ickb/v1-core", - "version": "1.4.1", + "version": "1.4.2", "description": "iCKB scripts and utilities for interacting with them", "main": "dist/cjs/src/index.js", "module": "dist/esm/src/index.js", @@ -25,14 +25,14 @@ "@ckb-lumos/config-manager": "^0.23.0", "@ckb-lumos/helpers": "^0.23.0", "@ckb-lumos/rpc": "^0.23.0", - "@ickb/lumos-utils": "1.4.1" + "@ickb/lumos-utils": "1.4.2" }, "devDependencies": { "typescript": "next", - "eslint": "^9.10.0", + "eslint": "^9.12.0", "@typescript-eslint/eslint-plugin": "canary", "@typescript-eslint/parser": "canary", "prettier": "^3.3.3" }, - "packageManager": "pnpm@9.10.0+sha256.355a8ab8dbb6ad41befbef39bc4fd6b5df85e12761d2724bd01f13e878de4b13" + "packageManager": "pnpm@9.12.2+sha256.2ef6e547b0b07d841d605240dce4d635677831148cd30f6d564b8f4f928f73d2" } \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7f06e60..c15eea8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -30,24 +30,24 @@ importers: specifier: ^0.23.0 version: 0.23.0 '@ickb/lumos-utils': - specifier: 1.4.1 - version: 1.4.1 + specifier: 1.4.2 + version: 1.4.2 devDependencies: '@typescript-eslint/eslint-plugin': specifier: canary - version: 8.5.1-alpha.8(@typescript-eslint/parser@8.5.1-alpha.8(eslint@9.10.0)(typescript@5.7.0-dev.20240914))(eslint@9.10.0)(typescript@5.7.0-dev.20240914) + version: 8.9.1-alpha.9(@typescript-eslint/parser@8.9.1-alpha.9(eslint@9.12.0)(typescript@5.7.0-dev.20241017))(eslint@9.12.0)(typescript@5.7.0-dev.20241017) '@typescript-eslint/parser': specifier: canary - version: 8.5.1-alpha.8(eslint@9.10.0)(typescript@5.7.0-dev.20240914) + version: 8.9.1-alpha.9(eslint@9.12.0)(typescript@5.7.0-dev.20241017) eslint: - specifier: ^9.10.0 - version: 9.10.0 + specifier: ^9.12.0 + version: 9.12.0 prettier: specifier: ^3.3.3 version: 3.3.3 typescript: specifier: next - version: 5.7.0-dev.20240914 + version: 5.7.0-dev.20241017 packages: @@ -97,40 +97,52 @@ packages: peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - '@eslint-community/regexpp@4.11.0': - resolution: {integrity: sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==} + '@eslint-community/regexpp@4.11.1': + resolution: {integrity: sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} '@eslint/config-array@0.18.0': resolution: {integrity: sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/core@0.6.0': + resolution: {integrity: sha512-8I2Q8ykA4J0x0o7cg67FPVnehcqWTBehu/lmY+bolPFHGjh49YzGBMXTvpqVgEbBdvNCSxj6iFgiIyHzf03lzg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/eslintrc@3.1.0': resolution: {integrity: sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.10.0': - resolution: {integrity: sha512-fuXtbiP5GWIn8Fz+LWoOMVf/Jxm+aajZYkhi6CuEm4SxymFM+eUWzbO9qXT+L0iCkL5+KGYMCSGxo686H19S1g==} + '@eslint/js@9.12.0': + resolution: {integrity: sha512-eohesHH8WFRUprDNyEREgqP6beG6htMeUYeCpkEgBCieCMme5r9zFWjzAJp//9S+Kub4rqE+jXe9Cp1a7IYIIA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/object-schema@2.1.4': resolution: {integrity: sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/plugin-kit@0.1.0': - resolution: {integrity: sha512-autAXT203ixhqei9xt+qkYOvY8l6LAFIdT2UXc/RPNeUVfqRF1BV94GTJyVPFKT8nFM6MyVJhjLj9E8JWvf5zQ==} + '@eslint/plugin-kit@0.2.0': + resolution: {integrity: sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@humanfs/core@0.19.0': + resolution: {integrity: sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.5': + resolution: {integrity: sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg==} + engines: {node: '>=18.18.0'} + '@humanwhocodes/module-importer@1.0.1': resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} engines: {node: '>=12.22'} - '@humanwhocodes/retry@0.3.0': - resolution: {integrity: sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==} + '@humanwhocodes/retry@0.3.1': + resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} engines: {node: '>=18.18'} - '@ickb/lumos-utils@1.4.1': - resolution: {integrity: sha512-GAjZSsPyKrIljufZJK8axrZQrwd1ruNkiZg3YjlkUOxW1NT+DumULv4mQxoVmphX2lmR96dXcfEBOOfE5QMi4w==} + '@ickb/lumos-utils@1.4.2': + resolution: {integrity: sha512-sN9wZ5U9sUhK/hvLkRH7TpTgbweszLKNSOSJ6Ber9EKVqyQ0eD7qnJlGzDudmHt1Z/uEPlWBvD0cYOi61sK8Dg==} '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} @@ -150,14 +162,20 @@ packages: '@types/deep-freeze-strict@1.1.2': resolution: {integrity: sha512-VvMETBojHvhX4f+ocYTySQlXMZfxKV3Jyb7iCWlWaC+exbedkv6Iv2bZZqI736qXjVguH6IH7bzwMBMfTT+zuQ==} + '@types/estree@1.0.6': + resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + '@types/lodash.isequal@4.5.8': resolution: {integrity: sha512-uput6pg4E/tj2LGxCZo9+y27JNyB2OZuuI/T5F+ylVDYuqICLG2/ktjxx0v6GvVntAf8TvEzeQLcV0ffRirXuA==} - '@types/lodash@4.17.7': - resolution: {integrity: sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA==} + '@types/lodash@4.17.10': + resolution: {integrity: sha512-YpS0zzoduEhuOWjAotS6A5AVCva7X4lVlYLF0FYHAY9sdraBfnatttHItlWeZdGhuEkf+OzMNg2ZYAx8t+52uQ==} - '@typescript-eslint/eslint-plugin@8.5.1-alpha.8': - resolution: {integrity: sha512-jktLQlFAF7Q42Oyz1TmEhqpuHPIUgv2HXj5Qh3vbgYNkEHYwfmRqn522RKEXFpoqYIeQ2dwptN4SsJl9XY0KQw==} + '@typescript-eslint/eslint-plugin@8.9.1-alpha.9': + resolution: {integrity: sha512-0i1wqf3IBjM+6+B/d+XbfQk/Q305mgTonHkrzFHXKRs+Ov82zZ9mdV2v5sD0m/ShMBLL6oDs+lxJz3gUt+WBhw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 @@ -167,8 +185,8 @@ packages: typescript: optional: true - '@typescript-eslint/parser@8.5.1-alpha.8': - resolution: {integrity: sha512-+cH8MduZzyhsl0tNeI75RVLS9TDV1atnFYs/0OnI6waUZ3FJqcaNJecnI6Mb+7tOxEqs9qWBRaL+/mdmxNSC3A==} + '@typescript-eslint/parser@8.9.1-alpha.9': + resolution: {integrity: sha512-bMErXC0vdZ5n4unOKdRbd1wGh7DldLHGr5OJbphQCKxCHhy+GvZD1fXnCvB9DaV4s+qWfjdwvYMHjIAStrTpAQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -177,12 +195,12 @@ packages: typescript: optional: true - '@typescript-eslint/scope-manager@8.5.1-alpha.8': - resolution: {integrity: sha512-AbjKWuXcTNKuoVyflZZLOw+LloiA78IrTeP7Uco4nvogia3imIOI5lHbGJOCeuUbePwb04zdRAdWekjgve8cIQ==} + '@typescript-eslint/scope-manager@8.9.1-alpha.9': + resolution: {integrity: sha512-8BZA/qe55qs27olqfbdZ78xgHPbzYP9KF+fNFd7FU+mvAP8gRvW0djKTkAsQ230Tzg3hZf5JnwRrjBuaAYTMHA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/type-utils@8.5.1-alpha.8': - resolution: {integrity: sha512-AMT/MT4acNiM5RqEFkwuytG64vUyG7aCX93vTdHLANQzpP71jlJMxTBBiRKwwBAYAxSK3InrYJicTQ6vOorcPA==} + '@typescript-eslint/type-utils@8.9.1-alpha.9': + resolution: {integrity: sha512-7PJ+pP2vLhWbjFVe2xk9RENDYm1IcKTeezh7b+rZsGENwvSMzS817mPHBZQw3sKF/PRntGXHsv4OsPhtT8oJOg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '*' @@ -190,12 +208,12 @@ packages: typescript: optional: true - '@typescript-eslint/types@8.5.1-alpha.8': - resolution: {integrity: sha512-kUzWaPdI62Us3hbqdN0LjvnxfrlxwKLjkRT+YAxF1ME7YmZQ96z9gCWzF+QLDnpD5uwQe0OkfFu+Wzml6+Cr4g==} + '@typescript-eslint/types@8.9.1-alpha.9': + resolution: {integrity: sha512-w3Ih/iy/9AENWUfW4AgSjgVq4tKGJD1cjXY3fss/9VjGzL0m9/OSbeEpZsPahnPmOI38h3sqJbdmmxnecavQaQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.5.1-alpha.8': - resolution: {integrity: sha512-ZB+UgXZgp72ngSrPS3vkvqKrn3HkvNqUAgpz6N0OoVqKbibUcymUfWZ0wtgtxVrHMawaTaccpb3nK7BjPX54vg==} + '@typescript-eslint/typescript-estree@8.9.1-alpha.9': + resolution: {integrity: sha512-fMHzd1E5EVE7ttQDAGeslPgf9g3yYsDhwYhORLba3XKsFdUQu+z+k28rizdGPD2XVWdwN4v8P4r3nk4cpfq/Ag==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '*' @@ -203,14 +221,14 @@ packages: typescript: optional: true - '@typescript-eslint/utils@8.5.1-alpha.8': - resolution: {integrity: sha512-QrywxQKfq6v0MsYiu9K2TQos4PynrSfTd57mACRFEw/ZHE3tLJ3pJOf49Nys056A/CqToTvATmpc5wpCQy+EuA==} + '@typescript-eslint/utils@8.9.1-alpha.9': + resolution: {integrity: sha512-TTDopFuzIAn01/badOI0FtKSwD/sm+14Vfo5SgvYMxws6xHHAWfZULy8BVIZI8jAoFsMiXVZV4ZgZFnySQ3FCQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - '@typescript-eslint/visitor-keys@8.5.1-alpha.8': - resolution: {integrity: sha512-/lv4ri4xRJWfVcvvie3IZCDFxO0vJiAv+7MAddUc+K6iPk3DWCrWZ7/5qdKc17ajhcfNvdAqjPXlmukvnRK8cQ==} + '@typescript-eslint/visitor-keys@8.9.1-alpha.9': + resolution: {integrity: sha512-2sjA6Iqu6om4o6O0tDeyoZXGOhSgiwHBdT4oWrnlBIiJQg1yEjgtHTIOjps2V8v+PFJrZAE40CIqAwsvH4YS7A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} abort-controller@3.0.0: @@ -222,18 +240,14 @@ packages: peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - acorn@8.12.1: - resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==} + acorn@8.13.0: + resolution: {integrity: sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==} engines: {node: '>=0.4.0'} hasBin: true ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} @@ -241,8 +255,8 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - b4a@1.6.6: - resolution: {integrity: sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==} + b4a@1.6.7: + resolution: {integrity: sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==} balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} @@ -316,20 +330,20 @@ packages: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} - eslint-scope@8.0.2: - resolution: {integrity: sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==} + eslint-scope@8.1.0: + resolution: {integrity: sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} eslint-visitor-keys@3.4.3: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - eslint-visitor-keys@4.0.0: - resolution: {integrity: sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==} + eslint-visitor-keys@4.1.0: + resolution: {integrity: sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@9.10.0: - resolution: {integrity: sha512-Y4D0IgtBZfOcOUAIQTSXBKoNGfY0REGqHJG6+Q81vNippW5YlKjHFj4soMxamKK1NXHUWuBZTLdU3Km+L/pcHw==} + eslint@9.12.0: + resolution: {integrity: sha512-UVIOlTEWxwIopRL1wgSQYdnVDcEvs2wyaO6DGo5mXqe3r16IoCNWkR29iHhyaP4cICWjbgbmFUGAhh0GJRuGZw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: @@ -338,8 +352,8 @@ packages: jiti: optional: true - espree@10.1.0: - resolution: {integrity: sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==} + espree@10.2.0: + resolution: {integrity: sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} esquery@1.6.0: @@ -447,10 +461,6 @@ packages: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} - is-path-inside@3.0.3: - resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} - engines: {node: '>=8'} - isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} @@ -592,10 +602,6 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} - strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} @@ -624,8 +630,8 @@ packages: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} - typescript@5.7.0-dev.20240914: - resolution: {integrity: sha512-FFOqgbzyxpBRq2YcKTQTAuurIKiU5A0VoWwDDnSjHPDHDbs3eriLiMIj8BExs2Soz7Wr+HxMJkbAZ0RCgvoIZg==} + typescript@5.7.0-dev.20241017: + resolution: {integrity: sha512-ZxR14EdfbJK3JjGJ0dm6SjmHbOkJ86QM7k2ARlQzRyzNJV23E2bkdLW24fjVk5UyLyuTtIH9OMgpP++Q0G/Glg==} engines: {node: '>=14.17'} hasBin: true @@ -745,12 +751,12 @@ snapshots: dependencies: '@ckb-lumos/bi': 0.23.0 - '@eslint-community/eslint-utils@4.4.0(eslint@9.10.0)': + '@eslint-community/eslint-utils@4.4.0(eslint@9.12.0)': dependencies: - eslint: 9.10.0 + eslint: 9.12.0 eslint-visitor-keys: 3.4.3 - '@eslint-community/regexpp@4.11.0': {} + '@eslint-community/regexpp@4.11.1': {} '@eslint/config-array@0.18.0': dependencies: @@ -760,11 +766,13 @@ snapshots: transitivePeerDependencies: - supports-color + '@eslint/core@0.6.0': {} + '@eslint/eslintrc@3.1.0': dependencies: ajv: 6.12.6 debug: 4.3.7 - espree: 10.1.0 + espree: 10.2.0 globals: 14.0.0 ignore: 5.3.2 import-fresh: 3.3.0 @@ -774,19 +782,26 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@9.10.0': {} + '@eslint/js@9.12.0': {} '@eslint/object-schema@2.1.4': {} - '@eslint/plugin-kit@0.1.0': + '@eslint/plugin-kit@0.2.0': dependencies: levn: 0.4.1 + '@humanfs/core@0.19.0': {} + + '@humanfs/node@0.16.5': + dependencies: + '@humanfs/core': 0.19.0 + '@humanwhocodes/retry': 0.3.1 + '@humanwhocodes/module-importer@1.0.1': {} - '@humanwhocodes/retry@0.3.0': {} + '@humanwhocodes/retry@0.3.1': {} - '@ickb/lumos-utils@1.4.1': + '@ickb/lumos-utils@1.4.2': dependencies: '@ckb-lumos/base': 0.23.0 '@ckb-lumos/ckb-indexer': 0.23.0 @@ -816,102 +831,106 @@ snapshots: '@types/deep-freeze-strict@1.1.2': {} + '@types/estree@1.0.6': {} + + '@types/json-schema@7.0.15': {} + '@types/lodash.isequal@4.5.8': dependencies: - '@types/lodash': 4.17.7 + '@types/lodash': 4.17.10 - '@types/lodash@4.17.7': {} + '@types/lodash@4.17.10': {} - '@typescript-eslint/eslint-plugin@8.5.1-alpha.8(@typescript-eslint/parser@8.5.1-alpha.8(eslint@9.10.0)(typescript@5.7.0-dev.20240914))(eslint@9.10.0)(typescript@5.7.0-dev.20240914)': + '@typescript-eslint/eslint-plugin@8.9.1-alpha.9(@typescript-eslint/parser@8.9.1-alpha.9(eslint@9.12.0)(typescript@5.7.0-dev.20241017))(eslint@9.12.0)(typescript@5.7.0-dev.20241017)': dependencies: - '@eslint-community/regexpp': 4.11.0 - '@typescript-eslint/parser': 8.5.1-alpha.8(eslint@9.10.0)(typescript@5.7.0-dev.20240914) - '@typescript-eslint/scope-manager': 8.5.1-alpha.8 - '@typescript-eslint/type-utils': 8.5.1-alpha.8(eslint@9.10.0)(typescript@5.7.0-dev.20240914) - '@typescript-eslint/utils': 8.5.1-alpha.8(eslint@9.10.0)(typescript@5.7.0-dev.20240914) - '@typescript-eslint/visitor-keys': 8.5.1-alpha.8 - eslint: 9.10.0 + '@eslint-community/regexpp': 4.11.1 + '@typescript-eslint/parser': 8.9.1-alpha.9(eslint@9.12.0)(typescript@5.7.0-dev.20241017) + '@typescript-eslint/scope-manager': 8.9.1-alpha.9 + '@typescript-eslint/type-utils': 8.9.1-alpha.9(eslint@9.12.0)(typescript@5.7.0-dev.20241017) + '@typescript-eslint/utils': 8.9.1-alpha.9(eslint@9.12.0)(typescript@5.7.0-dev.20241017) + '@typescript-eslint/visitor-keys': 8.9.1-alpha.9 + eslint: 9.12.0 graphemer: 1.4.0 ignore: 5.3.2 natural-compare: 1.4.0 - ts-api-utils: 1.3.0(typescript@5.7.0-dev.20240914) + ts-api-utils: 1.3.0(typescript@5.7.0-dev.20241017) optionalDependencies: - typescript: 5.7.0-dev.20240914 + typescript: 5.7.0-dev.20241017 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.5.1-alpha.8(eslint@9.10.0)(typescript@5.7.0-dev.20240914)': + '@typescript-eslint/parser@8.9.1-alpha.9(eslint@9.12.0)(typescript@5.7.0-dev.20241017)': dependencies: - '@typescript-eslint/scope-manager': 8.5.1-alpha.8 - '@typescript-eslint/types': 8.5.1-alpha.8 - '@typescript-eslint/typescript-estree': 8.5.1-alpha.8(typescript@5.7.0-dev.20240914) - '@typescript-eslint/visitor-keys': 8.5.1-alpha.8 + '@typescript-eslint/scope-manager': 8.9.1-alpha.9 + '@typescript-eslint/types': 8.9.1-alpha.9 + '@typescript-eslint/typescript-estree': 8.9.1-alpha.9(typescript@5.7.0-dev.20241017) + '@typescript-eslint/visitor-keys': 8.9.1-alpha.9 debug: 4.3.7 - eslint: 9.10.0 + eslint: 9.12.0 optionalDependencies: - typescript: 5.7.0-dev.20240914 + typescript: 5.7.0-dev.20241017 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.5.1-alpha.8': + '@typescript-eslint/scope-manager@8.9.1-alpha.9': dependencies: - '@typescript-eslint/types': 8.5.1-alpha.8 - '@typescript-eslint/visitor-keys': 8.5.1-alpha.8 + '@typescript-eslint/types': 8.9.1-alpha.9 + '@typescript-eslint/visitor-keys': 8.9.1-alpha.9 - '@typescript-eslint/type-utils@8.5.1-alpha.8(eslint@9.10.0)(typescript@5.7.0-dev.20240914)': + '@typescript-eslint/type-utils@8.9.1-alpha.9(eslint@9.12.0)(typescript@5.7.0-dev.20241017)': dependencies: - '@typescript-eslint/typescript-estree': 8.5.1-alpha.8(typescript@5.7.0-dev.20240914) - '@typescript-eslint/utils': 8.5.1-alpha.8(eslint@9.10.0)(typescript@5.7.0-dev.20240914) + '@typescript-eslint/typescript-estree': 8.9.1-alpha.9(typescript@5.7.0-dev.20241017) + '@typescript-eslint/utils': 8.9.1-alpha.9(eslint@9.12.0)(typescript@5.7.0-dev.20241017) debug: 4.3.7 - ts-api-utils: 1.3.0(typescript@5.7.0-dev.20240914) + ts-api-utils: 1.3.0(typescript@5.7.0-dev.20241017) optionalDependencies: - typescript: 5.7.0-dev.20240914 + typescript: 5.7.0-dev.20241017 transitivePeerDependencies: - eslint - supports-color - '@typescript-eslint/types@8.5.1-alpha.8': {} + '@typescript-eslint/types@8.9.1-alpha.9': {} - '@typescript-eslint/typescript-estree@8.5.1-alpha.8(typescript@5.7.0-dev.20240914)': + '@typescript-eslint/typescript-estree@8.9.1-alpha.9(typescript@5.7.0-dev.20241017)': dependencies: - '@typescript-eslint/types': 8.5.1-alpha.8 - '@typescript-eslint/visitor-keys': 8.5.1-alpha.8 + '@typescript-eslint/types': 8.9.1-alpha.9 + '@typescript-eslint/visitor-keys': 8.9.1-alpha.9 debug: 4.3.7 fast-glob: 3.3.2 is-glob: 4.0.3 minimatch: 9.0.5 semver: 7.6.3 - ts-api-utils: 1.3.0(typescript@5.7.0-dev.20240914) + ts-api-utils: 1.3.0(typescript@5.7.0-dev.20241017) optionalDependencies: - typescript: 5.7.0-dev.20240914 + typescript: 5.7.0-dev.20241017 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.5.1-alpha.8(eslint@9.10.0)(typescript@5.7.0-dev.20240914)': + '@typescript-eslint/utils@8.9.1-alpha.9(eslint@9.12.0)(typescript@5.7.0-dev.20241017)': dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.10.0) - '@typescript-eslint/scope-manager': 8.5.1-alpha.8 - '@typescript-eslint/types': 8.5.1-alpha.8 - '@typescript-eslint/typescript-estree': 8.5.1-alpha.8(typescript@5.7.0-dev.20240914) - eslint: 9.10.0 + '@eslint-community/eslint-utils': 4.4.0(eslint@9.12.0) + '@typescript-eslint/scope-manager': 8.9.1-alpha.9 + '@typescript-eslint/types': 8.9.1-alpha.9 + '@typescript-eslint/typescript-estree': 8.9.1-alpha.9(typescript@5.7.0-dev.20241017) + eslint: 9.12.0 transitivePeerDependencies: - supports-color - typescript - '@typescript-eslint/visitor-keys@8.5.1-alpha.8': + '@typescript-eslint/visitor-keys@8.9.1-alpha.9': dependencies: - '@typescript-eslint/types': 8.5.1-alpha.8 + '@typescript-eslint/types': 8.9.1-alpha.9 eslint-visitor-keys: 3.4.3 abort-controller@3.0.0: dependencies: event-target-shim: 5.0.1 - acorn-jsx@5.3.2(acorn@8.12.1): + acorn-jsx@5.3.2(acorn@8.13.0): dependencies: - acorn: 8.12.1 + acorn: 8.13.0 - acorn@8.12.1: {} + acorn@8.13.0: {} ajv@6.12.6: dependencies: @@ -920,15 +939,13 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 - ansi-regex@5.0.1: {} - ansi-styles@4.3.0: dependencies: color-convert: 2.0.1 argparse@2.0.1: {} - b4a@1.6.6: {} + b4a@1.6.7: {} balanced-match@1.0.2: {} @@ -938,7 +955,7 @@ snapshots: blake2b-wasm@2.4.0: dependencies: - b4a: 1.6.6 + b4a: 1.6.7 nanoassert: 2.0.0 blake2b@2.1.4: @@ -1000,34 +1017,37 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-scope@8.0.2: + eslint-scope@8.1.0: dependencies: esrecurse: 4.3.0 estraverse: 5.3.0 eslint-visitor-keys@3.4.3: {} - eslint-visitor-keys@4.0.0: {} + eslint-visitor-keys@4.1.0: {} - eslint@9.10.0: + eslint@9.12.0: dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.10.0) - '@eslint-community/regexpp': 4.11.0 + '@eslint-community/eslint-utils': 4.4.0(eslint@9.12.0) + '@eslint-community/regexpp': 4.11.1 '@eslint/config-array': 0.18.0 + '@eslint/core': 0.6.0 '@eslint/eslintrc': 3.1.0 - '@eslint/js': 9.10.0 - '@eslint/plugin-kit': 0.1.0 + '@eslint/js': 9.12.0 + '@eslint/plugin-kit': 0.2.0 + '@humanfs/node': 0.16.5 '@humanwhocodes/module-importer': 1.0.1 - '@humanwhocodes/retry': 0.3.0 - '@nodelib/fs.walk': 1.2.8 + '@humanwhocodes/retry': 0.3.1 + '@types/estree': 1.0.6 + '@types/json-schema': 7.0.15 ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 debug: 4.3.7 escape-string-regexp: 4.0.0 - eslint-scope: 8.0.2 - eslint-visitor-keys: 4.0.0 - espree: 10.1.0 + eslint-scope: 8.1.0 + eslint-visitor-keys: 4.1.0 + espree: 10.2.0 esquery: 1.6.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 @@ -1037,22 +1057,20 @@ snapshots: ignore: 5.3.2 imurmurhash: 0.1.4 is-glob: 4.0.3 - is-path-inside: 3.0.3 json-stable-stringify-without-jsonify: 1.0.1 lodash.merge: 4.6.2 minimatch: 3.1.2 natural-compare: 1.4.0 optionator: 0.9.4 - strip-ansi: 6.0.1 text-table: 0.2.0 transitivePeerDependencies: - supports-color - espree@10.1.0: + espree@10.2.0: dependencies: - acorn: 8.12.1 - acorn-jsx: 5.3.2(acorn@8.12.1) - eslint-visitor-keys: 4.0.0 + acorn: 8.13.0 + acorn-jsx: 5.3.2(acorn@8.13.0) + eslint-visitor-keys: 4.1.0 esquery@1.6.0: dependencies: @@ -1141,8 +1159,6 @@ snapshots: is-number@7.0.0: {} - is-path-inside@3.0.3: {} - isexe@2.0.0: {} js-xxhash@1.0.4: {} @@ -1252,10 +1268,6 @@ snapshots: shebang-regex@3.0.0: {} - strip-ansi@6.0.1: - dependencies: - ansi-regex: 5.0.1 - strip-json-comments@3.1.1: {} supports-color@7.2.0: @@ -1270,15 +1282,15 @@ snapshots: tr46@0.0.3: {} - ts-api-utils@1.3.0(typescript@5.7.0-dev.20240914): + ts-api-utils@1.3.0(typescript@5.7.0-dev.20241017): dependencies: - typescript: 5.7.0-dev.20240914 + typescript: 5.7.0-dev.20241017 type-check@0.4.0: dependencies: prelude-ls: 1.2.1 - typescript@5.7.0-dev.20240914: {} + typescript@5.7.0-dev.20241017: {} uri-js@4.4.1: dependencies: diff --git a/src/limit_order.ts b/src/limit_order.ts index 322df19..3cf7e1a 100644 --- a/src/limit_order.ts +++ b/src/limit_order.ts @@ -5,11 +5,12 @@ import { I8Cell, I8Script, addCells, - typeSifter, - lockExpanderFrom, I8OutPoint, hex, type ConfigAdapter, + i8ScriptPadding, + scriptEq, + CKB, } from "@ickb/lumos-utils"; import { ickbUdtType } from "./ickb_logic.js"; import { OrderData } from "./codec.js"; @@ -21,14 +22,22 @@ export type MyOrder = Order & { export type Order = { cell: I8Cell; - master: { outPoint: I8OutPoint }; info: Required & { + isMint: boolean; + masterOutpoint: Readonly; // Computed properties + ckbOccupied: bigint; + ckbUnoccupied: bigint; + isCkb2Udt: boolean; // It can also be dual ratio + isUdt2Ckb: boolean; // It can also be dual ratio + isDualRatio: boolean; ckbMinMatch: bigint; isCkb2UdtMatchable: boolean; isUdt2CkbMatchable: boolean; isMatchable: boolean; - isDualRatio: boolean; + // A competition progress, relProgress= 100*Number(absProgress)/Number(absTotal) + absProgress: bigint; + absTotal: bigint; }; }; @@ -45,128 +54,123 @@ export type OrderRatio = { udtMultiplier: bigint; }; -const padding = - "0x0000000000000000000000000000000000000000000000000000000000000000"; +function ratioEq(r0: OrderRatio, r1: OrderRatio) { + return ( + r0.ckbMultiplier === r1.ckbMultiplier && + r0.udtMultiplier === r1.udtMultiplier + ); +} + +function OrderInfoEq(i0: BaseOrderInfo, i1: BaseOrderInfo) { + return ( + ratioEq(i0.ckbToUdt, i1.ckbToUdt) && + ratioEq(i0.udtToCkb, i1.udtToCkb) && + i0.ckbMinMatchLog === i1.ckbMinMatchLog + ); +} export function orderSifter( inputs: readonly Cell[], accountLockExpander: (c: Cell) => I8Script | undefined, + getTxOutputs: (txHash: string) => Readonly, config: ConfigAdapter, udtType = ickbUdtType(config), ) { const orderScript = limitOrderScript(config); - let { types, notTypes: unknowns } = typeSifter( + + // Sift and group matching orders and master cells of udtType + const { groups, unknowns } = rawSifter( inputs, + accountLockExpander, + orderScript, udtType, - lockExpanderFrom(orderScript), ); - let masters: I8Cell[] = []; - ({ types: masters, notTypes: unknowns } = typeSifter( - unknowns, + + // Fetch the original mint transactions of the orders found + const mints = mintsOf( + [...groups.values()].map( + (g) => g.master?.outPoint ?? g.orders[0].info.masterOutpoint, + ), + getTxOutputs, orderScript, - accountLockExpander, - )); - const key = (o: OutPoint) => o.txHash + o.index; - const outPoint2Master = new Map( - masters.map((c) => [key(c.outPoint!), c as MyOrder["master"]]), + udtType, ); - const ckbOccupiedMax = ckbOrderOccupiedMax(orderScript, udtType); - + // Validate that orders are in line with the mints and not forged const orders: Order[] = []; const myOrders: MyOrder[] = []; - for (const cell of types) { - let o: UnpackedOrder; - try { - o = OrderData.unpack(cell.data); - } catch (e: unknown) { - unknowns.push(cell); + for (const [k, group] of groups) { + const mint = mints.get(k); + if (mint === undefined) { + // No mint group found, all orders in this group are forged, so discard them + const m = group.master === undefined ? [] : [group.master]; + unknowns.push(...m, ...group.orders.map((o) => o.cell)); continue; } - const { - ckbToUdt: c2u, - udtToCkb: u2c, - ckbMinMatchLog: cmml, - } = o.value.orderInfo; - const ckbToUdt = normalizeRatio(c2u); - const udtToCkb = normalizeRatio(u2c); - const ckbMinMatchLog = normalizeCkbMinMatchLog(cmml); + // Find the order that has the best value, while keeping the mint parameters + let iBest = -1; + let best: Order = mint; + for (let i = 0; i < group.orders.length; i++) { + const o = group.orders[i]; + + // Check that parameters are the the mint parameters + if ( + !OrderInfoEq(mint.info, o.info) || + !scriptEq(mint.cell.cellOutput.type, o.cell.cellOutput.type) || + o.info.absTotal < mint.info.absTotal + ) { + // Discard current forged order + unknowns.push(o.cell); + continue; + } + + // Pick order with best absProgress + if (o.info.absProgress < best.info.absProgress) { + // Discard current forged order + unknowns.push(o.cell); + continue; + } + + // At equality of absProgress, give preference to newly minted orders + if (o.info.absProgress === best.info.absProgress && !o.info.isMint) { + // Discard current forged order + unknowns.push(o.cell); + continue; + } + + // Discard the old Best order + if (iBest >= 0) { + unknowns.push(best.cell); + } + + iBest = i; + best = o; + } - // Check that the order is valid - if ( - ckbToUdt.ckbMultiplier !== c2u.ckbMultiplier || - ckbToUdt.udtMultiplier !== c2u.udtMultiplier || - udtToCkb.ckbMultiplier !== u2c.ckbMultiplier || - udtToCkb.udtMultiplier !== u2c.udtMultiplier || - ckbMinMatchLog !== cmml || - (o.type === "MintOrderData" && o.value.padding !== padding) - ) { - unknowns.push(cell); + // Discard master cell if group doesn't contain a valid match + if (iBest === -1) { + if (group.master !== undefined) { + unknowns.push(group.master); + } continue; } - const ckbMinMatch = 1n << BigInt(ckbMinMatchLog); - const udtAmount = o.udtAmount; - const ckbAmount = BigInt(cell.cellOutput.capacity); - const ckbUnused = ckbAmount - ckbOccupiedMax; - const isCkb2UdtMatchable = - ckbToUdt !== normalizedInvalidRatio && ckbUnused > 0n; - const isUdt2CkbMatchable = - udtToCkb !== normalizedInvalidRatio && udtAmount > 0n; - const isMatchable = isCkb2UdtMatchable || isUdt2CkbMatchable; - const isDualRatio = - ckbToUdt !== normalizedInvalidRatio && - udtToCkb !== normalizedInvalidRatio; - - let info: Order["info"] = Object.freeze({ - ckbToUdt, - udtToCkb, - ckbMinMatchLog, - ckbMinMatch, - udtAmount, - ckbAmount, - isCkb2UdtMatchable, - isUdt2CkbMatchable, - isMatchable, - isDualRatio, - }); - - const masterOutPoint = I8OutPoint.from( - o.type === "MintOrderData" - ? { - txHash: cell.outPoint!.txHash, - index: hex(Number(cell.outPoint!.index) + o.value.masterDistance), - } - : o.value.masterOutpoint, - ); - const k = key(masterOutPoint); - const master = outPoint2Master.get(k); - if (master) { - // Order owned by the Account - outPoint2Master.delete(k); + // Add the current best order and maybe master to the results + if (group.master !== undefined) { + // Order owned by Account myOrders.push( Object.freeze({ - cell, - master, - info, + ...best, + master: group.master, }), ); } else { - orders.push( - Object.freeze({ - cell, - master: Object.freeze({ outPoint: masterOutPoint }), - info, - }), - ); + // Order not owned by Account + orders.push(Object.freeze(best)); } } - for (const c of outPoint2Master.values()) { - unknowns.push(c); - } - return { myOrders, orders, @@ -174,6 +178,210 @@ export function orderSifter( }; } +function mintsOf( + masterOutpoints: readonly I8OutPoint[], + getTxOutputs: (txHash: string) => Readonly, + orderScript: I8Script, + udtType: I8Script, +) { + const mints = new Map(); + const dummyAccountLockExpander = (c: Cell) => + I8Script.from({ ...i8ScriptPadding, ...c.cellOutput.lock }); + for (const txHash of new Set(masterOutpoints.map((v) => v.txHash))) { + // Fetch the original mint transactions of the masterOutpoints + for (const [k, g] of rawSifter( + getTxOutputs(txHash), + dummyAccountLockExpander, + orderScript, + udtType, + ).groups) { + // Keep only valid mint transactions + if ( + g.master === undefined || + g.orders.length !== 1 || + !g.orders[0].info.isMint + ) { + continue; + } + + mints.set(k, { + ...g.orders[0], + master: g.master, + }); + } + } + + return mints; +} + +function rawSifter( + inputs: readonly Cell[], + accountLockExpander: (c: Cell) => I8Script | undefined, + orderScript: I8Script, + udtType: I8Script, +) { + const groups = new Map< + string, + { + master: I8Cell | undefined; + orders: Order[]; + } + >(); + + // Utility for creating and/or getting group entries of the groups map + const groupOf = (o: OutPoint) => { + const key = o.txHash + o.index; + let group = groups.get(key); + if (group === undefined) { + group = { + master: undefined, + orders: [], + }; + groups.set(key, group); + } + return group; + }; + + const unknowns: Cell[] = []; + for (const c of inputs) { + const { lock, type } = c.cellOutput; + if (scriptEq(type, orderScript)) { + // Master cell + const lock = accountLockExpander(c); + if (lock) { + groupOf(c.outPoint!).master = I8Cell.from({ + ...c, + cellOutput: { + lock, + type: orderScript, + capacity: c.cellOutput.capacity, + }, + }); + continue; + } + } else if (scriptEq(lock, orderScript) && scriptEq(type, udtType)) { + const info = extractOrderInfo(c); + if (info !== undefined) { + // Limit Order + groupOf(info.masterOutpoint).orders.push({ + cell: I8Cell.from({ + ...c, + cellOutput: { + lock: orderScript, + type: udtType, + capacity: c.cellOutput.capacity, + }, + }), + info, + }); + continue; + } + } + + // Discard unknown cell + unknowns.push(c); + } + + return { groups, unknowns }; +} + +function extractOrderInfo(cell: Cell) { + let o: UnpackedOrder; + try { + o = OrderData.unpack(cell.data); + } catch { + return; + } + + const orderInfo = o.value.orderInfo; + const ckbToUdt = normalizeRatio(orderInfo.ckbToUdt); + const udtToCkb = normalizeRatio(orderInfo.udtToCkb); + const ckbMinMatchLog = normalizeCkbMinMatchLog(orderInfo.ckbMinMatchLog); + + // Check that the order is valid + if ( + !OrderInfoEq({ ckbToUdt, udtToCkb, ckbMinMatchLog }, orderInfo) || + (o.type === "MintOrderData" && o.value.padding !== padding) || + cell.cellOutput.type === undefined || + cell.cellOutput.type.args.length < 2 // args must at least contain "0x" + ) { + return; + } + + const isMint = o.type === "MintOrderData"; + + const masterOutpoint = I8OutPoint.from( + o.type === "MintOrderData" + ? { + txHash: cell.outPoint!.txHash, + index: hex(Number(cell.outPoint!.index) + o.value.masterDistance), + } + : o.value.masterOutpoint, + ); + + const ckbMinMatch = 1n << BigInt(ckbMinMatchLog); + const udtAmount = o.udtAmount; + const ckbAmount = BigInt(cell.cellOutput.capacity); + const ckbOccupied = + orderMinCkb + BigInt((cell.cellOutput.type.args.length - 2) / 2) * CKB; + const ckbUnoccupied = ckbAmount - ckbOccupied; + + const isCkb2Udt = ckbToUdt !== zeroRatio; + const isUdt2Ckb = udtToCkb !== zeroRatio; + const isDualRatio = isCkb2Udt && isUdt2Ckb; + + const ckb2UdtValue = isCkb2Udt + ? ckbUnoccupied * ckbToUdt.ckbMultiplier + + udtAmount * ckbToUdt.udtMultiplier + : 0n; + + const udt2CkbValue = isUdt2Ckb + ? ckbUnoccupied * udtToCkb.ckbMultiplier + + udtAmount * udtToCkb.udtMultiplier + : 0n; + + const absTotal = + ckb2UdtValue === 0n + ? udt2CkbValue + : udt2CkbValue === 0n + ? ckb2UdtValue + : // Take the average of the two values for dual ratio orders + (ckb2UdtValue * udtToCkb.ckbMultiplier * udtToCkb.udtMultiplier + + udt2CkbValue * ckbToUdt.ckbMultiplier * ckbToUdt.udtMultiplier) >> + 1n; + + const absProgress = isDualRatio + ? absTotal + : isCkb2Udt + ? udtAmount * ckbToUdt.udtMultiplier + : ckbUnoccupied * udtToCkb.ckbMultiplier; + + const isCkb2UdtMatchable = isCkb2Udt && ckbUnoccupied > 0n; + const isUdt2CkbMatchable = isUdt2Ckb && udtAmount > 0n; + const isMatchable = isCkb2UdtMatchable || isUdt2CkbMatchable; + + return Object.freeze({ + isMint, + masterOutpoint, + ckbToUdt, + udtToCkb, + ckbMinMatchLog, + ckbMinMatch, + udtAmount, + ckbAmount, + ckbOccupied, + ckbUnoccupied, + absTotal, + absProgress, + isCkb2Udt, + isUdt2Ckb, + isDualRatio, + isCkb2UdtMatchable, + isUdt2CkbMatchable, + isMatchable, + }); +} + export const defaultCkbMinMatchLog = 33; // ~ 86 CKB export function orderMint( @@ -190,18 +398,15 @@ export function orderFrom( config: ConfigAdapter, ckbAmount = 0n, //it will use way more CKB than expressed in ckbAmount udtAmount = 0n, - ckbToUdt = normalizedInvalidRatio, - udtToCkb = normalizedInvalidRatio, + ckbToUdt = zeroRatio, + udtToCkb = zeroRatio, ckbMinMatchLog = defaultCkbMinMatchLog, udtType = ickbUdtType(config), ) { ckbToUdt = normalizeRatio(ckbToUdt); udtToCkb = normalizeRatio(udtToCkb); ckbMinMatchLog = normalizeCkbMinMatchLog(ckbMinMatchLog); - if ( - ckbToUdt === normalizedInvalidRatio && - udtToCkb === normalizedInvalidRatio - ) { + if (ckbToUdt === zeroRatio && udtToCkb === zeroRatio) { throw Error(errorInvalidRatio); } @@ -293,7 +498,7 @@ export function orderSatisfy( udtAmount: udtOut, type: "MatchOrderData", value: { - masterOutpoint: o.master.outPoint, + masterOutpoint: o.info.masterOutpoint, orderInfo: o.info, }, }), @@ -399,40 +604,38 @@ function normalizeCkbMinMatchLog(n: number) { function normalizeRatio(r: OrderRatio): OrderRatio { if (r.ckbMultiplier === 0n || r!.udtMultiplier === 0n) { - return normalizedInvalidRatio; + return zeroRatio; } else { return Object.freeze({ ...r }); } } -const normalizedInvalidRatio: OrderRatio = Object.freeze({ +const zeroRatio: OrderRatio = Object.freeze({ ckbMultiplier: 0n, udtMultiplier: 0n, }); -function ckbOrderOccupiedMax(orderScript: I8Script, udtType: I8Script) { - return BigInt( - I8Cell.from({ - lock: orderScript, - type: udtType, - data: hexify( - OrderData.pack({ - udtAmount: 0n, - type: "MatchOrderData", - value: { - masterOutpoint: { - txHash: - "0x0000000000000000000000000000000000000000000000000000000000000000", - index: "0x0", - }, - orderInfo: { - ckbToUdt: normalizedInvalidRatio, - udtToCkb: normalizedInvalidRatio, - ckbMinMatchLog: 0, - }, +const padding = + "0x0000000000000000000000000000000000000000000000000000000000000000"; + +const orderMinCkb = BigInt( + I8Cell.from({ + lock: i8ScriptPadding, + type: i8ScriptPadding, + data: hexify( + OrderData.pack({ + udtAmount: 0n, + type: "MintOrderData", + value: { + masterDistance: 0, + padding, + orderInfo: { + ckbToUdt: zeroRatio, + udtToCkb: zeroRatio, + ckbMinMatchLog: 0, }, - }), - ), - }).cellOutput.capacity, - ); -} + }, + }), + ), + }).cellOutput.capacity, +);