dexbot 1.4.9 → 1.4.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/README.md +3 -3
  2. package/dist/dexbot.d.ts.map +1 -1
  3. package/dist/dexbot.js +43 -9
  4. package/dist/dexbot.js.map +1 -1
  5. package/dist/market_adapter/core/market_adapter_service.d.ts +2 -0
  6. package/dist/market_adapter/core/market_adapter_service.d.ts.map +1 -1
  7. package/dist/market_adapter/core/market_adapter_service.js +9 -0
  8. package/dist/market_adapter/core/market_adapter_service.js.map +1 -1
  9. package/dist/market_adapter/market_adapter.d.ts.map +1 -1
  10. package/dist/market_adapter/market_adapter.js +6 -1
  11. package/dist/market_adapter/market_adapter.js.map +1 -1
  12. package/dist/modules/broadcast_failure.d.ts +0 -1
  13. package/dist/modules/broadcast_failure.d.ts.map +1 -1
  14. package/dist/modules/broadcast_failure.js +0 -1
  15. package/dist/modules/broadcast_failure.js.map +1 -1
  16. package/dist/modules/chain_keys.d.ts.map +1 -1
  17. package/dist/modules/chain_keys.js +19 -1
  18. package/dist/modules/chain_keys.js.map +1 -1
  19. package/dist/modules/constants.d.ts +2 -5
  20. package/dist/modules/constants.d.ts.map +1 -1
  21. package/dist/modules/constants.js +8 -5
  22. package/dist/modules/constants.js.map +1 -1
  23. package/dist/modules/credential_policy.d.ts.map +1 -1
  24. package/dist/modules/credential_policy.js +135 -364
  25. package/dist/modules/credential_policy.js.map +1 -1
  26. package/dist/modules/daemon_node_health.d.ts +0 -1
  27. package/dist/modules/daemon_node_health.d.ts.map +1 -1
  28. package/dist/modules/daemon_node_health.js +0 -1
  29. package/dist/modules/daemon_node_health.js.map +1 -1
  30. package/dist/modules/dexbot_cow_runtime.d.ts.map +1 -1
  31. package/dist/modules/dexbot_cow_runtime.js +7 -1
  32. package/dist/modules/dexbot_cow_runtime.js.map +1 -1
  33. package/dist/modules/dexbot_fill_runtime.d.ts +14 -5
  34. package/dist/modules/dexbot_fill_runtime.d.ts.map +1 -1
  35. package/dist/modules/dexbot_fill_runtime.js +27 -27
  36. package/dist/modules/dexbot_fill_runtime.js.map +1 -1
  37. package/dist/modules/dexbot_maintenance_runtime.d.ts.map +1 -1
  38. package/dist/modules/dexbot_maintenance_runtime.js +32 -14
  39. package/dist/modules/dexbot_maintenance_runtime.js.map +1 -1
  40. package/dist/modules/dexbot_startup_runtime.d.ts.map +1 -1
  41. package/dist/modules/dexbot_startup_runtime.js +4 -11
  42. package/dist/modules/dexbot_startup_runtime.js.map +1 -1
  43. package/dist/modules/dexbot_state_recovery.d.ts.map +1 -1
  44. package/dist/modules/dexbot_state_recovery.js +7 -7
  45. package/dist/modules/dexbot_state_recovery.js.map +1 -1
  46. package/dist/modules/key_store.d.ts.map +1 -1
  47. package/dist/modules/key_store.js +42 -60
  48. package/dist/modules/key_store.js.map +1 -1
  49. package/dist/modules/launcher/bot_supervisor.d.ts +2 -2
  50. package/dist/modules/launcher/bot_supervisor.d.ts.map +1 -1
  51. package/dist/modules/launcher/bot_supervisor.js +6 -26
  52. package/dist/modules/launcher/bot_supervisor.js.map +1 -1
  53. package/dist/modules/launcher/foreign_cred_daemon.d.ts +17 -0
  54. package/dist/modules/launcher/foreign_cred_daemon.d.ts.map +1 -1
  55. package/dist/modules/launcher/foreign_cred_daemon.js +5 -14
  56. package/dist/modules/launcher/foreign_cred_daemon.js.map +1 -1
  57. package/dist/modules/launcher/monolithic_runtime.d.ts +2 -1
  58. package/dist/modules/launcher/monolithic_runtime.d.ts.map +1 -1
  59. package/dist/modules/launcher/monolithic_runtime.js +34 -16
  60. package/dist/modules/launcher/monolithic_runtime.js.map +1 -1
  61. package/dist/modules/launcher/status_reporting.d.ts.map +1 -1
  62. package/dist/modules/launcher/status_reporting.js +1 -11
  63. package/dist/modules/launcher/status_reporting.js.map +1 -1
  64. package/dist/modules/node_failure_ledger.d.ts +0 -1
  65. package/dist/modules/node_failure_ledger.d.ts.map +1 -1
  66. package/dist/modules/node_failure_ledger.js +0 -1
  67. package/dist/modules/node_failure_ledger.js.map +1 -1
  68. package/dist/modules/order/accounting.d.ts.map +1 -1
  69. package/dist/modules/order/accounting.js +5 -1
  70. package/dist/modules/order/accounting.js.map +1 -1
  71. package/dist/modules/order/grid.d.ts +5 -5
  72. package/dist/modules/order/grid.d.ts.map +1 -1
  73. package/dist/modules/order/grid.js +236 -27
  74. package/dist/modules/order/grid.js.map +1 -1
  75. package/dist/modules/order/grid_reconcile_internal.d.ts.map +1 -1
  76. package/dist/modules/order/grid_reconcile_internal.js +147 -35
  77. package/dist/modules/order/grid_reconcile_internal.js.map +1 -1
  78. package/dist/modules/order/logger.d.ts +0 -8
  79. package/dist/modules/order/logger.d.ts.map +1 -1
  80. package/dist/modules/order/logger.js +1 -73
  81. package/dist/modules/order/logger.js.map +1 -1
  82. package/dist/modules/order/manager.d.ts +1 -80
  83. package/dist/modules/order/manager.d.ts.map +1 -1
  84. package/dist/modules/order/manager.js +3 -116
  85. package/dist/modules/order/manager.js.map +1 -1
  86. package/dist/modules/order/strategy.js +2 -2
  87. package/dist/modules/order/strategy.js.map +1 -1
  88. package/dist/modules/order/sync_engine.js +4 -4
  89. package/dist/modules/order/sync_engine.js.map +1 -1
  90. package/dist/modules/order/utils/math.d.ts +38 -1
  91. package/dist/modules/order/utils/math.d.ts.map +1 -1
  92. package/dist/modules/order/utils/math.js +60 -0
  93. package/dist/modules/order/utils/math.js.map +1 -1
  94. package/dist/modules/order/utils/order.d.ts +45 -1
  95. package/dist/modules/order/utils/order.d.ts.map +1 -1
  96. package/dist/modules/order/utils/order.js +84 -0
  97. package/dist/modules/order/utils/order.js.map +1 -1
  98. package/dist/modules/order/utils/system.d.ts.map +1 -1
  99. package/dist/modules/order/utils/system.js +5 -2
  100. package/dist/modules/order/utils/system.js.map +1 -1
  101. package/dist/modules/process_discovery.d.ts +1 -1
  102. package/dist/modules/process_discovery.d.ts.map +1 -1
  103. package/dist/modules/process_discovery.js +17 -17
  104. package/dist/modules/process_discovery.js.map +1 -1
  105. package/dist/modules/socket_json_client.d.ts +0 -1
  106. package/dist/modules/socket_json_client.d.ts.map +1 -1
  107. package/dist/modules/socket_json_client.js +0 -1
  108. package/dist/modules/socket_json_client.js.map +1 -1
  109. package/dist/modules/types.d.ts +0 -600
  110. package/dist/modules/types.d.ts.map +1 -1
  111. package/dist/modules/types.js +15 -0
  112. package/dist/modules/types.js.map +1 -1
  113. package/dist/scripts/run-tests.js +185 -18
  114. package/dist/scripts/run-tests.js.map +1 -1
  115. package/dist/scripts/update.js +27 -17
  116. package/dist/scripts/update.js.map +1 -1
  117. package/dist/unlock.d.ts.map +1 -1
  118. package/dist/unlock.js +170 -86
  119. package/dist/unlock.js.map +1 -1
  120. package/package.json +1 -1
@@ -694,411 +694,182 @@ function buildPolicyContext(request) {
694
694
  * Evaluate per-operation parameter constraints.
695
695
  * Returns { allow: boolean, reason: string|null, policyId: string }
696
696
  */
697
+ function asDeny(reason) {
698
+ return { allow: false, reason, policyId: 'opParams' };
699
+ }
700
+ function denyNotInList(opName, word, id, listName, list, requirePresent) {
701
+ if (!Array.isArray(list) || list.length === 0)
702
+ return null;
703
+ if (requirePresent) {
704
+ if (!list.includes(String(id))) {
705
+ return asDeny(`${opName}: ${word} "${id}" not in ${listName}`);
706
+ }
707
+ }
708
+ else if (id != null && !list.includes(String(id))) {
709
+ return asDeny(`${opName}: ${word} "${id}" not in ${listName}`);
710
+ }
711
+ return null;
712
+ }
713
+ function denyBoundExceeded(opName, label, compareValue, shownValue, boundLabel, bound, opts = {}) {
714
+ if (bound == null)
715
+ return null;
716
+ if (compareValue == null || !Number.isFinite(compareValue))
717
+ return null;
718
+ const over = opts.lower ? compareValue < bound : compareValue > bound;
719
+ if (!over)
720
+ return null;
721
+ const verb = opts.verb ?? (opts.lower ? 'below' : 'exceeds');
722
+ return asDeny(`${opName}: ${label} ${shownValue} ${verb} ${boundLabel} ${bound}`);
723
+ }
724
+ async function denyAssetRefMismatch(opName, word, assetId, refs, refLabel, opts = {}) {
725
+ if (!opts.active)
726
+ return null;
727
+ const resolved = await resolveConfiguredAssetRefs(refs, refLabel);
728
+ if (!resolved.ok)
729
+ return asDeny(`${opName}: ${resolved.reason}`);
730
+ if (assetId && resolved.values && !resolved.values.includes(String(assetId))) {
731
+ const phrase = opts.matchOnly ? 'does not match' : 'not in';
732
+ return asDeny(`${opName}: ${word} "${assetId}" ${phrase} ${refLabel}`);
733
+ }
734
+ return null;
735
+ }
697
736
  async function evaluateOpConstraints(opName, opData, constraints) {
698
737
  if (!constraints)
699
738
  return { allow: true, reason: null, policyId: null };
700
739
  const d = opData || {};
701
740
  if (opName === 'transfer') {
702
741
  // allowedToAccounts
703
- if (Array.isArray(constraints.allowedToAccounts) && constraints.allowedToAccounts.length > 0) {
704
- if (!constraints.allowedToAccounts.includes(d.to)) {
705
- return {
706
- allow: false,
707
- reason: `transfer: recipient "${d.to}" not in allowedToAccounts`,
708
- policyId: 'opParams',
709
- };
710
- }
711
- }
742
+ const recipientDenied = denyNotInList('transfer', 'recipient', d.to, 'allowedToAccounts', constraints.allowedToAccounts, true);
743
+ if (recipientDenied)
744
+ return recipientDenied;
712
745
  // allowedAssets
713
- if (Array.isArray(constraints.allowedAssets) && constraints.allowedAssets.length > 0) {
714
- const id = d.amount && d.amount.asset_id;
715
- if (id && !constraints.allowedAssets.includes(id)) {
716
- return {
717
- allow: false,
718
- reason: `transfer: asset "${id}" not in allowedAssets`,
719
- policyId: 'opParams',
720
- };
721
- }
722
- }
746
+ const assetDenied = denyNotInList('transfer', 'asset', d.amount && d.amount.asset_id, 'allowedAssets', constraints.allowedAssets);
747
+ if (assetDenied)
748
+ return assetDenied;
723
749
  // maxAmount
724
- if (constraints.maxAmount != null) {
725
- const amt = d.amount && d.amount.amount;
726
- if (typeof amt === 'number' && amt > constraints.maxAmount) {
727
- return {
728
- allow: false,
729
- reason: `transfer: amount ${amt} exceeds maxAmount ${constraints.maxAmount}`,
730
- policyId: 'opParams',
731
- };
732
- }
733
- }
750
+ const maxAmountDenied = denyBoundExceeded('transfer', 'amount', d.amount && d.amount.amount, d.amount && d.amount.amount, 'maxAmount', constraints.maxAmount);
751
+ if (maxAmountDenied)
752
+ return maxAmountDenied;
734
753
  }
735
754
  if (opName === 'limit_order_create') {
736
755
  // allowedSellAssets
737
- if (Array.isArray(constraints.allowedSellAssets) && constraints.allowedSellAssets.length > 0) {
738
- const id = d.amount_to_sell && d.amount_to_sell.asset_id;
739
- if (id && !constraints.allowedSellAssets.includes(id)) {
740
- return {
741
- allow: false,
742
- reason: `limit_order_create: sell asset "${id}" not in allowedSellAssets`,
743
- policyId: 'opParams',
744
- };
745
- }
746
- }
756
+ const sellDenied = denyNotInList('limit_order_create', 'sell asset', d.amount_to_sell && d.amount_to_sell.asset_id, 'allowedSellAssets', constraints.allowedSellAssets);
757
+ if (sellDenied)
758
+ return sellDenied;
747
759
  // allowedReceiveAssets
748
- if (Array.isArray(constraints.allowedReceiveAssets) && constraints.allowedReceiveAssets.length > 0) {
749
- const id = d.min_to_receive && d.min_to_receive.asset_id;
750
- if (id && !constraints.allowedReceiveAssets.includes(id)) {
751
- return {
752
- allow: false,
753
- reason: `limit_order_create: receive asset "${id}" not in allowedReceiveAssets`,
754
- policyId: 'opParams',
755
- };
756
- }
757
- }
760
+ const receiveDenied = denyNotInList('limit_order_create', 'receive asset', d.min_to_receive && d.min_to_receive.asset_id, 'allowedReceiveAssets', constraints.allowedReceiveAssets);
761
+ if (receiveDenied)
762
+ return receiveDenied;
758
763
  // maxSellAmount
759
- if (constraints.maxSellAmount != null) {
760
- const amt = d.amount_to_sell && d.amount_to_sell.amount;
761
- if (typeof amt === 'number' && amt > constraints.maxSellAmount) {
762
- return {
763
- allow: false,
764
- reason: `limit_order_create: sell amount ${amt} exceeds maxSellAmount ${constraints.maxSellAmount}`,
765
- policyId: 'opParams',
766
- };
767
- }
768
- }
764
+ const maxSellDenied = denyBoundExceeded('limit_order_create', 'sell amount', d.amount_to_sell && d.amount_to_sell.amount, d.amount_to_sell && d.amount_to_sell.amount, 'maxSellAmount', constraints.maxSellAmount);
765
+ if (maxSellDenied)
766
+ return maxSellDenied;
769
767
  // maxReceiveAmount
770
- if (constraints.maxReceiveAmount != null) {
771
- const amt = d.min_to_receive && d.min_to_receive.amount;
772
- if (typeof amt === 'number' && amt > constraints.maxReceiveAmount) {
773
- return {
774
- allow: false,
775
- reason: `limit_order_create: receive amount ${amt} exceeds maxReceiveAmount ${constraints.maxReceiveAmount}`,
776
- policyId: 'opParams',
777
- };
778
- }
779
- }
768
+ const maxReceiveDenied = denyBoundExceeded('limit_order_create', 'receive amount', d.min_to_receive && d.min_to_receive.amount, d.min_to_receive && d.min_to_receive.amount, 'maxReceiveAmount', constraints.maxReceiveAmount);
769
+ if (maxReceiveDenied)
770
+ return maxReceiveDenied;
780
771
  // allowFillOrKill
781
772
  if (constraints.allowFillOrKill === false && d.fill_or_kill === true) {
782
- return {
783
- allow: false,
784
- reason: 'limit_order_create: fill_or_kill=true not permitted',
785
- policyId: 'opParams',
786
- };
773
+ return asDeny('limit_order_create: fill_or_kill=true not permitted');
787
774
  }
788
775
  }
789
776
  if (opName === 'limit_order_update') {
790
777
  // allowedSellAssets via new_price.base
791
- if (Array.isArray(constraints.allowedSellAssets) && constraints.allowedSellAssets.length > 0) {
792
- const id = d.new_price && d.new_price.base && d.new_price.base.asset_id;
793
- if (id && !constraints.allowedSellAssets.includes(id)) {
794
- return {
795
- allow: false,
796
- reason: `limit_order_update: base asset "${id}" not in allowedSellAssets`,
797
- policyId: 'opParams',
798
- };
799
- }
800
- }
778
+ const sellDenied = denyNotInList('limit_order_update', 'base asset', d.new_price && d.new_price.base && d.new_price.base.asset_id, 'allowedSellAssets', constraints.allowedSellAssets);
779
+ if (sellDenied)
780
+ return sellDenied;
801
781
  // allowedReceiveAssets via new_price.quote
802
- if (Array.isArray(constraints.allowedReceiveAssets) && constraints.allowedReceiveAssets.length > 0) {
803
- const id = d.new_price && d.new_price.quote && d.new_price.quote.asset_id;
804
- if (id && !constraints.allowedReceiveAssets.includes(id)) {
805
- return {
806
- allow: false,
807
- reason: `limit_order_update: quote asset "${id}" not in allowedReceiveAssets`,
808
- policyId: 'opParams',
809
- };
810
- }
811
- }
782
+ const receiveDenied = denyNotInList('limit_order_update', 'quote asset', d.new_price && d.new_price.quote && d.new_price.quote.asset_id, 'allowedReceiveAssets', constraints.allowedReceiveAssets);
783
+ if (receiveDenied)
784
+ return receiveDenied;
812
785
  // maxDeltaSellAmount (abs value)
813
- if (constraints.maxDeltaSellAmount != null) {
814
- const delta = d.delta_amount_to_sell && d.delta_amount_to_sell.amount;
815
- if (typeof delta === 'number' && Math.abs(delta) > constraints.maxDeltaSellAmount) {
816
- return {
817
- allow: false,
818
- reason: `limit_order_update: |delta| ${Math.abs(delta)} exceeds maxDeltaSellAmount ${constraints.maxDeltaSellAmount}`,
819
- policyId: 'opParams',
820
- };
821
- }
822
- }
786
+ const maxDeltaSellDenied = denyBoundExceeded('limit_order_update', '|delta|', Math.abs(d.delta_amount_to_sell && d.delta_amount_to_sell.amount), Math.abs(d.delta_amount_to_sell && d.delta_amount_to_sell.amount), 'maxDeltaSellAmount', constraints.maxDeltaSellAmount);
787
+ if (maxDeltaSellDenied)
788
+ return maxDeltaSellDenied;
823
789
  }
824
790
  if (opName === 'call_order_update') {
825
791
  // allowedAssets
826
- if (Array.isArray(constraints.allowedAssets) && constraints.allowedAssets.length > 0) {
827
- const collId = d.delta_collateral && d.delta_collateral.asset_id;
828
- const debtId = d.delta_debt && d.delta_debt.asset_id;
829
- if (collId && !constraints.allowedAssets.includes(collId)) {
830
- return {
831
- allow: false,
832
- reason: `call_order_update: collateral asset "${collId}" not in allowedAssets`,
833
- policyId: 'opParams',
834
- };
835
- }
836
- if (debtId && !constraints.allowedAssets.includes(debtId)) {
837
- return {
838
- allow: false,
839
- reason: `call_order_update: debt asset "${debtId}" not in allowedAssets`,
840
- policyId: 'opParams',
841
- };
842
- }
843
- }
844
- if (constraints.collateralAsset) {
845
- const collId = d.delta_collateral && d.delta_collateral.asset_id;
846
- const resolved = await resolveConfiguredAssetRefs([constraints.collateralAsset], 'collateralAsset');
847
- if (!resolved.ok) {
848
- return {
849
- allow: false,
850
- reason: `call_order_update: ${resolved.reason}`,
851
- policyId: 'opParams',
852
- };
853
- }
854
- if (collId && resolved.values && !resolved.values.includes(String(collId))) {
855
- return {
856
- allow: false,
857
- reason: `call_order_update: collateral asset "${collId}" does not match collateralAsset`,
858
- policyId: 'opParams',
859
- };
860
- }
861
- }
862
- if (Array.isArray(constraints.allowedCollateralAssets) && constraints.allowedCollateralAssets.length > 0) {
863
- const collId = d.delta_collateral && d.delta_collateral.asset_id;
864
- const resolved = await resolveConfiguredAssetRefs(constraints.allowedCollateralAssets, 'allowedCollateralAssets');
865
- if (!resolved.ok) {
866
- return {
867
- allow: false,
868
- reason: `call_order_update: ${resolved.reason}`,
869
- policyId: 'opParams',
870
- };
871
- }
872
- if (collId && resolved.values && !resolved.values.includes(String(collId))) {
873
- return {
874
- allow: false,
875
- reason: `call_order_update: collateral asset "${collId}" not in allowedCollateralAssets`,
876
- policyId: 'opParams',
877
- };
878
- }
879
- }
792
+ const collDenied = denyNotInList('call_order_update', 'collateral asset', d.delta_collateral && d.delta_collateral.asset_id, 'allowedAssets', constraints.allowedAssets);
793
+ if (collDenied)
794
+ return collDenied;
795
+ const debtDenied = denyNotInList('call_order_update', 'debt asset', d.delta_debt && d.delta_debt.asset_id, 'allowedAssets', constraints.allowedAssets);
796
+ if (debtDenied)
797
+ return debtDenied;
798
+ const collateralMatchDenied = await denyAssetRefMismatch('call_order_update', 'collateral asset', d.delta_collateral && d.delta_collateral.asset_id, [constraints.collateralAsset], 'collateralAsset', { active: !!constraints.collateralAsset, matchOnly: true });
799
+ if (collateralMatchDenied)
800
+ return collateralMatchDenied;
801
+ const allowedCollateralDenied = await denyAssetRefMismatch('call_order_update', 'collateral asset', d.delta_collateral && d.delta_collateral.asset_id, constraints.allowedCollateralAssets, 'allowedCollateralAssets', { active: Array.isArray(constraints.allowedCollateralAssets) && constraints.allowedCollateralAssets.length > 0 });
802
+ if (allowedCollateralDenied)
803
+ return allowedCollateralDenied;
880
804
  // maxDeltaCollateral
881
- if (constraints.maxDeltaCollateral != null) {
882
- const amt = d.delta_collateral && d.delta_collateral.amount;
883
- if (typeof amt === 'number' && Math.abs(amt) > constraints.maxDeltaCollateral) {
884
- return {
885
- allow: false,
886
- reason: `call_order_update: |delta_collateral| ${Math.abs(amt)} exceeds maxDeltaCollateral ${constraints.maxDeltaCollateral}`,
887
- policyId: 'opParams',
888
- };
889
- }
890
- }
805
+ const maxDeltaCollateralDenied = denyBoundExceeded('call_order_update', '|delta_collateral|', Math.abs(d.delta_collateral && d.delta_collateral.amount), Math.abs(d.delta_collateral && d.delta_collateral.amount), 'maxDeltaCollateral', constraints.maxDeltaCollateral);
806
+ if (maxDeltaCollateralDenied)
807
+ return maxDeltaCollateralDenied;
891
808
  // maxDeltaDebt
892
- if (constraints.maxDeltaDebt != null) {
893
- const amt = d.delta_debt && d.delta_debt.amount;
894
- if (typeof amt === 'number' && Math.abs(amt) > constraints.maxDeltaDebt) {
895
- return {
896
- allow: false,
897
- reason: `call_order_update: |delta_debt| ${Math.abs(amt)} exceeds maxDeltaDebt ${constraints.maxDeltaDebt}`,
898
- policyId: 'opParams',
899
- };
900
- }
901
- }
902
- if (constraints.minCollateralRatio != null && d.extensions && d.extensions.target_collateral_ratio != null) {
903
- const target = normalizeGrapheneCollateralRatio(d.extensions.target_collateral_ratio);
904
- if (Number.isFinite(target) && target != null && target < constraints.minCollateralRatio) {
905
- return {
906
- allow: false,
907
- reason: `call_order_update: target_collateral_ratio ${target} below minCollateralRatio ${constraints.minCollateralRatio}`,
908
- policyId: 'opParams',
909
- };
910
- }
911
- }
912
- if (constraints.maxCollateralRatio != null && d.extensions && d.extensions.target_collateral_ratio != null) {
913
- const target = normalizeGrapheneCollateralRatio(d.extensions.target_collateral_ratio);
914
- if (Number.isFinite(target) && target != null && target > constraints.maxCollateralRatio) {
915
- return {
916
- allow: false,
917
- reason: `call_order_update: target_collateral_ratio ${target} above maxCollateralRatio ${constraints.maxCollateralRatio}`,
918
- policyId: 'opParams',
919
- };
920
- }
921
- }
809
+ const maxDeltaDebtDenied = denyBoundExceeded('call_order_update', '|delta_debt|', Math.abs(d.delta_debt && d.delta_debt.amount), Math.abs(d.delta_debt && d.delta_debt.amount), 'maxDeltaDebt', constraints.maxDeltaDebt);
810
+ if (maxDeltaDebtDenied)
811
+ return maxDeltaDebtDenied;
812
+ const targetCollateralRatio = d.extensions && d.extensions.target_collateral_ratio != null ? normalizeGrapheneCollateralRatio(d.extensions.target_collateral_ratio) : NaN;
813
+ const minRatioDenied = denyBoundExceeded('call_order_update', 'target_collateral_ratio', targetCollateralRatio, targetCollateralRatio, 'minCollateralRatio', constraints.minCollateralRatio, { lower: true });
814
+ if (minRatioDenied)
815
+ return minRatioDenied;
816
+ const maxRatioDenied = denyBoundExceeded('call_order_update', 'target_collateral_ratio', targetCollateralRatio, targetCollateralRatio, 'maxCollateralRatio', constraints.maxCollateralRatio, { verb: 'above' });
817
+ if (maxRatioDenied)
818
+ return maxRatioDenied;
922
819
  }
923
820
  if (opName === 'credit_offer_accept') {
924
- if (Array.isArray(constraints.allowedOfferIds) && constraints.allowedOfferIds.length > 0) {
925
- const offerId = d.offer_id;
926
- if (offerId && !constraints.allowedOfferIds.includes(String(offerId))) {
927
- return {
928
- allow: false,
929
- reason: `credit_offer_accept: offer "${offerId}" not in allowedOfferIds`,
930
- policyId: 'opParams',
931
- };
932
- }
933
- }
934
- if (constraints.collateralAsset) {
935
- const assetId = d.collateral && d.collateral.asset_id;
936
- const resolved = await resolveConfiguredAssetRefs([constraints.collateralAsset], 'collateralAsset');
937
- if (!resolved.ok) {
938
- return {
939
- allow: false,
940
- reason: `credit_offer_accept: ${resolved.reason}`,
941
- policyId: 'opParams',
942
- };
943
- }
944
- if (assetId && resolved.values && !resolved.values.includes(String(assetId))) {
945
- return {
946
- allow: false,
947
- reason: `credit_offer_accept: collateral asset "${assetId}" does not match collateralAsset`,
948
- policyId: 'opParams',
949
- };
950
- }
951
- }
952
- if (Array.isArray(constraints.allowedCollateralAssets) && constraints.allowedCollateralAssets.length > 0) {
953
- const assetId = d.collateral && d.collateral.asset_id;
954
- const resolved = await resolveConfiguredAssetRefs(constraints.allowedCollateralAssets, 'allowedCollateralAssets');
955
- if (!resolved.ok) {
956
- return {
957
- allow: false,
958
- reason: `credit_offer_accept: ${resolved.reason}`,
959
- policyId: 'opParams',
960
- };
961
- }
962
- if (assetId && resolved.values && !resolved.values.includes(String(assetId))) {
963
- return {
964
- allow: false,
965
- reason: `credit_offer_accept: collateral asset "${assetId}" not in allowedCollateralAssets`,
966
- policyId: 'opParams',
967
- };
968
- }
969
- }
970
- if (Array.isArray(constraints.allowedDebtAssets) && constraints.allowedDebtAssets.length > 0) {
971
- const assetId = d.borrow_amount && d.borrow_amount.asset_id;
972
- const resolved = await resolveConfiguredAssetRefs(constraints.allowedDebtAssets, 'allowedDebtAssets');
973
- if (!resolved.ok) {
974
- return {
975
- allow: false,
976
- reason: `credit_offer_accept: ${resolved.reason}`,
977
- policyId: 'opParams',
978
- };
979
- }
980
- if (assetId && resolved.values && !resolved.values.includes(String(assetId))) {
981
- return {
982
- allow: false,
983
- reason: `credit_offer_accept: debt asset "${assetId}" not in allowedDebtAssets`,
984
- policyId: 'opParams',
985
- };
986
- }
987
- }
988
- if (constraints.maxFeeRate != null) {
989
- const maxFeeRate = Number(d.max_fee_rate);
990
- if (Number.isFinite(maxFeeRate) && maxFeeRate > constraints.maxFeeRate) {
991
- return {
992
- allow: false,
993
- reason: `credit_offer_accept: max_fee_rate ${maxFeeRate} exceeds maxFeeRate ${constraints.maxFeeRate}`,
994
- policyId: 'opParams',
995
- };
996
- }
997
- }
998
- if (constraints.minDurationSeconds != null) {
999
- const minDurationSeconds = Number(d.min_duration_seconds);
1000
- if (Number.isFinite(minDurationSeconds) && minDurationSeconds < constraints.minDurationSeconds) {
1001
- return {
1002
- allow: false,
1003
- reason: `credit_offer_accept: min_duration_seconds ${minDurationSeconds} below minDurationSeconds ${constraints.minDurationSeconds}`,
1004
- policyId: 'opParams',
1005
- };
1006
- }
1007
- }
821
+ const offerDenied = denyNotInList('credit_offer_accept', 'offer', d.offer_id, 'allowedOfferIds', constraints.allowedOfferIds);
822
+ if (offerDenied)
823
+ return offerDenied;
824
+ const collateralMatchDenied = await denyAssetRefMismatch('credit_offer_accept', 'collateral asset', d.collateral && d.collateral.asset_id, [constraints.collateralAsset], 'collateralAsset', { active: !!constraints.collateralAsset, matchOnly: true });
825
+ if (collateralMatchDenied)
826
+ return collateralMatchDenied;
827
+ const allowedCollateralDenied = await denyAssetRefMismatch('credit_offer_accept', 'collateral asset', d.collateral && d.collateral.asset_id, constraints.allowedCollateralAssets, 'allowedCollateralAssets', { active: Array.isArray(constraints.allowedCollateralAssets) && constraints.allowedCollateralAssets.length > 0 });
828
+ if (allowedCollateralDenied)
829
+ return allowedCollateralDenied;
830
+ const allowedDebtDenied = await denyAssetRefMismatch('credit_offer_accept', 'debt asset', d.borrow_amount && d.borrow_amount.asset_id, constraints.allowedDebtAssets, 'allowedDebtAssets', { active: Array.isArray(constraints.allowedDebtAssets) && constraints.allowedDebtAssets.length > 0 });
831
+ if (allowedDebtDenied)
832
+ return allowedDebtDenied;
833
+ const maxFeeDenied = denyBoundExceeded('credit_offer_accept', 'max_fee_rate', Number(d.max_fee_rate), Number(d.max_fee_rate), 'maxFeeRate', constraints.maxFeeRate);
834
+ if (maxFeeDenied)
835
+ return maxFeeDenied;
836
+ const minDurationDenied = denyBoundExceeded('credit_offer_accept', 'min_duration_seconds', Number(d.min_duration_seconds), Number(d.min_duration_seconds), 'minDurationSeconds', constraints.minDurationSeconds, { lower: true });
837
+ if (minDurationDenied)
838
+ return minDurationDenied;
1008
839
  }
1009
840
  if (opName === 'credit_deal_repay') {
1010
- if (Array.isArray(constraints.allowedDebtAssets) && constraints.allowedDebtAssets.length > 0) {
1011
- const assetId = d.repay_amount && d.repay_amount.asset_id;
1012
- const resolved = await resolveConfiguredAssetRefs(constraints.allowedDebtAssets, 'allowedDebtAssets');
1013
- if (!resolved.ok) {
1014
- return {
1015
- allow: false,
1016
- reason: `credit_deal_repay: ${resolved.reason}`,
1017
- policyId: 'opParams',
1018
- };
1019
- }
1020
- if (assetId && resolved.values && !resolved.values.includes(String(assetId))) {
1021
- return {
1022
- allow: false,
1023
- reason: `credit_deal_repay: debt asset "${assetId}" not in allowedDebtAssets`,
1024
- policyId: 'opParams',
1025
- };
1026
- }
1027
- }
1028
- if (constraints.maxRepayAmount != null) {
1029
- const amt = d.repay_amount && d.repay_amount.amount;
1030
- if (typeof amt === 'number' && amt > constraints.maxRepayAmount) {
1031
- return {
1032
- allow: false,
1033
- reason: `credit_deal_repay: repay amount ${amt} exceeds maxRepayAmount ${constraints.maxRepayAmount}`,
1034
- policyId: 'opParams',
1035
- };
1036
- }
1037
- }
1038
- if (constraints.maxCreditFee != null) {
1039
- const fee = d.credit_fee && d.credit_fee.amount;
1040
- if (typeof fee === 'number' && fee > constraints.maxCreditFee) {
1041
- return {
1042
- allow: false,
1043
- reason: `credit_deal_repay: credit fee ${fee} exceeds maxCreditFee ${constraints.maxCreditFee}`,
1044
- policyId: 'opParams',
1045
- };
1046
- }
1047
- }
841
+ const allowedDebtDenied = await denyAssetRefMismatch('credit_deal_repay', 'debt asset', d.repay_amount && d.repay_amount.asset_id, constraints.allowedDebtAssets, 'allowedDebtAssets', { active: Array.isArray(constraints.allowedDebtAssets) && constraints.allowedDebtAssets.length > 0 });
842
+ if (allowedDebtDenied)
843
+ return allowedDebtDenied;
844
+ const maxRepayDenied = denyBoundExceeded('credit_deal_repay', 'repay amount', d.repay_amount && d.repay_amount.amount, d.repay_amount && d.repay_amount.amount, 'maxRepayAmount', constraints.maxRepayAmount);
845
+ if (maxRepayDenied)
846
+ return maxRepayDenied;
847
+ const maxCreditFeeDenied = denyBoundExceeded('credit_deal_repay', 'credit fee', d.credit_fee && d.credit_fee.amount, d.credit_fee && d.credit_fee.amount, 'maxCreditFee', constraints.maxCreditFee);
848
+ if (maxCreditFeeDenied)
849
+ return maxCreditFeeDenied;
1048
850
  }
1049
851
  if (opName === 'credit_deal_update') {
1050
852
  if (constraints.allowAutoRepay === false && d.auto_repay) {
1051
- return {
1052
- allow: false,
1053
- reason: 'credit_deal_update: auto_repay change not permitted',
1054
- policyId: 'opParams',
1055
- };
853
+ return asDeny('credit_deal_update: auto_repay change not permitted');
1056
854
  }
1057
855
  }
1058
856
  if (opName === 'liquidity_pool_exchange') {
1059
857
  // allowedPools
1060
- if (Array.isArray(constraints.allowedPools) && constraints.allowedPools.length > 0) {
1061
- if (!constraints.allowedPools.includes(d.pool)) {
1062
- return {
1063
- allow: false,
1064
- reason: `liquidity_pool_exchange: pool "${d.pool}" not in allowedPools`,
1065
- policyId: 'opParams',
1066
- };
1067
- }
1068
- }
858
+ const poolDenied = denyNotInList('liquidity_pool_exchange', 'pool', d.pool, 'allowedPools', constraints.allowedPools, true);
859
+ if (poolDenied)
860
+ return poolDenied;
1069
861
  // allowedSellAssets
1070
- if (Array.isArray(constraints.allowedSellAssets) && constraints.allowedSellAssets.length > 0) {
1071
- const id = d.amount_to_sell && d.amount_to_sell.asset_id;
1072
- if (id && !constraints.allowedSellAssets.includes(id)) {
1073
- return {
1074
- allow: false,
1075
- reason: `liquidity_pool_exchange: sell asset "${id}" not in allowedSellAssets`,
1076
- policyId: 'opParams',
1077
- };
1078
- }
1079
- }
862
+ const sellDenied = denyNotInList('liquidity_pool_exchange', 'sell asset', d.amount_to_sell && d.amount_to_sell.asset_id, 'allowedSellAssets', constraints.allowedSellAssets);
863
+ if (sellDenied)
864
+ return sellDenied;
1080
865
  // allowedReceiveAssets
1081
- if (Array.isArray(constraints.allowedReceiveAssets) && constraints.allowedReceiveAssets.length > 0) {
1082
- const id = d.min_to_receive && d.min_to_receive.asset_id;
1083
- if (id && !constraints.allowedReceiveAssets.includes(id)) {
1084
- return {
1085
- allow: false,
1086
- reason: `liquidity_pool_exchange: receive asset "${id}" not in allowedReceiveAssets`,
1087
- policyId: 'opParams',
1088
- };
1089
- }
1090
- }
866
+ const receiveDenied = denyNotInList('liquidity_pool_exchange', 'receive asset', d.min_to_receive && d.min_to_receive.asset_id, 'allowedReceiveAssets', constraints.allowedReceiveAssets);
867
+ if (receiveDenied)
868
+ return receiveDenied;
1091
869
  // maxSellAmount
1092
- if (constraints.maxSellAmount != null) {
1093
- const amt = d.amount_to_sell && d.amount_to_sell.amount;
1094
- if (typeof amt === 'number' && amt > constraints.maxSellAmount) {
1095
- return {
1096
- allow: false,
1097
- reason: `liquidity_pool_exchange: sell amount ${amt} exceeds maxSellAmount ${constraints.maxSellAmount}`,
1098
- policyId: 'opParams',
1099
- };
1100
- }
1101
- }
870
+ const maxSellDenied = denyBoundExceeded('liquidity_pool_exchange', 'sell amount', d.amount_to_sell && d.amount_to_sell.amount, d.amount_to_sell && d.amount_to_sell.amount, 'maxSellAmount', constraints.maxSellAmount);
871
+ if (maxSellDenied)
872
+ return maxSellDenied;
1102
873
  }
1103
874
  // limit_order_cancel — no constraints
1104
875
  return { allow: true, reason: null, policyId: null };