diff --git a/scripts/binance-orderbook-trade.user.js b/scripts/binance-orderbook-trade.user.js index 64b47d3..c011722 100644 --- a/scripts/binance-orderbook-trade.user.js +++ b/scripts/binance-orderbook-trade.user.js @@ -3,7 +3,7 @@ // @namespace binance.orderbook.trade // @icon data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2064%2064%22%3E%3Crect%20width%3D%2264%22%20height%3D%2264%22%20rx%3D%2214%22%20fill%3D%22%23f0b90b%22%2F%3E%3Ctext%20x%3D%2232%22%20y%3D%2249%22%20text-anchor%3D%22middle%22%20font-family%3D%22Arial%2C%20sans-serif%22%20font-size%3D%2242%22%20font-weight%3D%22800%22%20fill%3D%22%23111827%22%3EJ%3C%2Ftext%3E%3C%2Fsvg%3E // @icon64 data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2064%2064%22%3E%3Crect%20width%3D%2264%22%20height%3D%2264%22%20rx%3D%2214%22%20fill%3D%22%23f0b90b%22%2F%3E%3Ctext%20x%3D%2232%22%20y%3D%2249%22%20text-anchor%3D%22middle%22%20font-family%3D%22Arial%2C%20sans-serif%22%20font-size%3D%2242%22%20font-weight%3D%22800%22%20fill%3D%22%23111827%22%3EJ%3C%2Ftext%3E%3C%2Fsvg%3E -// @version 2.7.137 +// @version 2.7.138 // @author jackhai9 // @description 单击订单簿价格,按当前开仓/平仓 tab 自动填数量并执行下单,内置数量倍率面板 // @match https://www.binance.com/*/futures/* @@ -3678,7 +3678,7 @@ const syncTimeoutMs = settleControlledForm ? LADDER_INPUT_SETTLE_TIMEOUT_MS : TRADE_INPUT_SYNC_TIMEOUT_MS; const stableMismatchFrames = settleControlledForm ? LADDER_INPUT_SETTLE_MISMATCH_FRAMES : TRADE_INPUT_SYNC_STABLE_FRAMES; const maxWriteAttempts = settleControlledForm ? LADDER_INPUT_SETTLE_MAX_WRITES : 2; - const isRecoveryWriteAllowed = settleControlledForm ? ({ rollbackValue }) => rollbackValue === "" : () => true; + const isRecoveryWriteAllowed = settleControlledForm ? ({ rollbackValue }) => rollbackValue === null : () => true; const writeTradeInputValue = settleControlledForm ? createBoundedInputWriter({ writeValue: setInputValueReact, maxWriteAttempts diff --git a/src/binance-orderbook-trade/index.user.js b/src/binance-orderbook-trade/index.user.js index b5815a0..87c3093 100644 --- a/src/binance-orderbook-trade/index.user.js +++ b/src/binance-orderbook-trade/index.user.js @@ -3,7 +3,7 @@ // @namespace binance.orderbook.trade // @icon data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2064%2064%22%3E%3Crect%20width%3D%2264%22%20height%3D%2264%22%20rx%3D%2214%22%20fill%3D%22%23f0b90b%22%2F%3E%3Ctext%20x%3D%2232%22%20y%3D%2249%22%20text-anchor%3D%22middle%22%20font-family%3D%22Arial%2C%20sans-serif%22%20font-size%3D%2242%22%20font-weight%3D%22800%22%20fill%3D%22%23111827%22%3EJ%3C%2Ftext%3E%3C%2Fsvg%3E // @icon64 data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2064%2064%22%3E%3Crect%20width%3D%2264%22%20height%3D%2264%22%20rx%3D%2214%22%20fill%3D%22%23f0b90b%22%2F%3E%3Ctext%20x%3D%2232%22%20y%3D%2249%22%20text-anchor%3D%22middle%22%20font-family%3D%22Arial%2C%20sans-serif%22%20font-size%3D%2242%22%20font-weight%3D%22800%22%20fill%3D%22%23111827%22%3EJ%3C%2Ftext%3E%3C%2Fsvg%3E -// @version 2.7.137 +// @version 2.7.138 // @author jackhai9 // @description 单击订单簿价格,按当前开仓/平仓 tab 自动填数量并执行下单,内置数量倍率面板 // @match https://www.binance.com/*/futures/* @@ -2248,7 +2248,7 @@ import { ? LADDER_INPUT_SETTLE_MAX_WRITES : 2; const isRecoveryWriteAllowed = settleControlledForm - ? ({ rollbackValue }) => rollbackValue === '' + ? ({ rollbackValue }) => rollbackValue === null : () => true; const writeTradeInputValue = settleControlledForm ? createBoundedInputWriter({ diff --git a/test/unit/binance-orderbook-trade/source-regressions.test.js b/test/unit/binance-orderbook-trade/source-regressions.test.js index 4c13176..153aedc 100644 --- a/test/unit/binance-orderbook-trade/source-regressions.test.js +++ b/test/unit/binance-orderbook-trade/source-regressions.test.js @@ -163,6 +163,11 @@ test('trade input synchronization confirms live controlled values instead of sle (syncBody.match(/recoverProvisionalMatchRollback:\s*settleControlledForm/g) || []).length, 2, ); + assert.match( + syncBody, + /\?\s*\(\{\s*rollbackValue\s*\}\)\s*=>\s*rollbackValue\s*===\s*null/, + ); + assert.doesNotMatch(syncBody, /rollbackValue\s*===\s*''/); assert.match(syncBody, /settleControlledForm[\s\S]*LADDER_INPUT_SETTLE_MISMATCH_FRAMES/); assert.match(syncBody, /waitForTradeFormFrameState/); assert.match(syncBody, /includePrice:\s*false/); diff --git a/test/unit/binance-orderbook-trade/trade-form.test.js b/test/unit/binance-orderbook-trade/trade-form.test.js index 71ba28e..7f8a452 100644 --- a/test/unit/binance-orderbook-trade/trade-form.test.js +++ b/test/unit/binance-orderbook-trade/trade-form.test.js @@ -17,6 +17,10 @@ import { waitForTradeFormFrameState, waitForTradeFormMutationState, } from '../../../src/binance-orderbook-trade/dom/trade-form.js'; +import { + compareDecimalStrings, + normalizeDecimalString, +} from '../../../src/binance-orderbook-trade/core/decimal.js'; import { loadFixtureDom } from '../../helpers/dom.js'; const fixture = await readFile( @@ -356,8 +360,8 @@ test('trade input synchronization performs one post-transition write after a sta expectedPrice: '81.9', expectedQty: '0.01', includePrice: true, - normalizeValue: String, - compareValues: (expected, actual) => expected === actual ? 0 : 1, + normalizeValue: normalizeDecimalString, + compareValues: compareDecimalStrings, writeValue: (input, value) => { writes.push({ input, value }); if (input === currentInputs.qtyInput) { @@ -395,8 +399,8 @@ test('trade input synchronization can settle a ladder input after repeated stabl resolveInputs: () => currentInputs, expectedQty: '0.02', includePrice: false, - normalizeValue: String, - compareValues: (expected, actual) => expected === actual ? 0 : 1, + normalizeValue: normalizeDecimalString, + compareValues: compareDecimalStrings, writeValue: (input, value) => { writes.push({ input, value }); qtyWrites += 1; @@ -405,7 +409,7 @@ test('trade input synchronization can settle a ladder input after repeated stabl requiredStableMismatchFrames: 2, maxWriteAttempts: 5, isRecoveryWriteAllowed: ({ currentInput, rollbackValue }) => ( - currentInput === currentInputs.qtyInput && rollbackValue === '' + currentInput === currentInputs.qtyInput && rollbackValue === null ), }); @@ -432,8 +436,8 @@ test('trade input synchronization recovers a provisional match rolled back befor resolveInputs: () => currentInputs, expectedQty: '0.07', includePrice: false, - normalizeValue: String, - compareValues: (expected, actual) => expected === actual ? 0 : 1, + normalizeValue: normalizeDecimalString, + compareValues: compareDecimalStrings, writeValue: (input, value) => { writes.push({ input, value }); input.value = value; @@ -442,7 +446,7 @@ test('trade input synchronization recovers a provisional match rolled back befor requiredStableMatchFrames: 2, maxWriteAttempts: 5, recoverProvisionalMatchRollback: true, - isRecoveryWriteAllowed: ({ rollbackValue }) => rollbackValue === '', + isRecoveryWriteAllowed: ({ rollbackValue }) => rollbackValue === null, }); assert.equal(readState(), null); @@ -468,8 +472,8 @@ test('trade input synchronization cancels provisional recovery for a different n resolveInputs: () => currentInputs, expectedQty: '0.07', includePrice: false, - normalizeValue: String, - compareValues: (expected, actual) => expected === actual ? 0 : 1, + normalizeValue: normalizeDecimalString, + compareValues: compareDecimalStrings, writeValue: (input, value) => { writes.push({ input, value }); input.value = value; @@ -478,7 +482,7 @@ test('trade input synchronization cancels provisional recovery for a different n requiredStableMatchFrames: 2, maxWriteAttempts: 5, recoverProvisionalMatchRollback: true, - isRecoveryWriteAllowed: ({ rollbackValue }) => rollbackValue === '', + isRecoveryWriteAllowed: ({ rollbackValue }) => rollbackValue === null, }); assert.equal(readState(), null); @@ -501,8 +505,8 @@ test('trade input synchronization rejects a provisionally accepted value that ro resolveInputs: () => currentInputs, expectedQty: '0.19', includePrice: false, - normalizeValue: String, - compareValues: (expected, actual) => expected === actual ? 0 : 1, + normalizeValue: normalizeDecimalString, + compareValues: compareDecimalStrings, writeValue: (input, value) => { writes.push({ input, value }); input.value = value; @@ -510,7 +514,7 @@ test('trade input synchronization rejects a provisionally accepted value that ro requiredStableMismatchFrames: 2, requiredStableMatchFrames: 3, maxWriteAttempts: 5, - isRecoveryWriteAllowed: ({ rollbackValue }) => rollbackValue === '', + isRecoveryWriteAllowed: ({ rollbackValue }) => rollbackValue === null, }); assert.equal(readState(), null); @@ -557,8 +561,8 @@ test('trade input synchronization remains fail-closed after the post-transition resolveInputs: () => currentInputs, expectedQty: '0.01', includePrice: false, - normalizeValue: String, - compareValues: (expected, actual) => expected === actual ? 0 : 1, + normalizeValue: normalizeDecimalString, + compareValues: compareDecimalStrings, writeValue: (input, value) => { writes.push({ input, value }); input.value = ''; @@ -584,15 +588,15 @@ test('trade input synchronization never exceeds an expanded write-attempt budget resolveInputs: () => currentInputs, expectedQty: '0.02', includePrice: false, - normalizeValue: String, - compareValues: (expected, actual) => expected === actual ? 0 : 1, + normalizeValue: normalizeDecimalString, + compareValues: compareDecimalStrings, writeValue: (input, value) => { writes.push({ input, value }); input.value = ''; }, requiredStableMismatchFrames: 1, maxWriteAttempts: 3, - isRecoveryWriteAllowed: ({ rollbackValue }) => rollbackValue === '', + isRecoveryWriteAllowed: ({ rollbackValue }) => rollbackValue === null, }); for (let frame = 0; frame < 10; frame += 1) {