@tradelayerprotocol/tradelayer 1.9.1
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.
- package/.claude/settings.local.json +13 -0
- package/.claude/skills/tl-algo/SKILL.md +255 -0
- package/.gitattributes +2 -0
- package/.github/workflows/publish.yaml +26 -0
- package/4mm.js +163 -0
- package/LICENSE +21 -0
- package/NPMSwapRefactor.zip +0 -0
- package/README.md +217 -0
- package/address.sh +26 -0
- package/algoAPI.js +581 -0
- package/analyzepsbt.js +92 -0
- package/apiEx.js +99 -0
- package/bb_hyperscalper.js +290 -0
- package/bbo_demo.js +111 -0
- package/buyer.js +622 -0
- package/client.js +50 -0
- package/createTxTest.js +26 -0
- package/createWallet.js +75 -0
- package/daytrader.js +531 -0
- package/decodeTest.js +69 -0
- package/fundingManager.js +144 -0
- package/index.js +4 -0
- package/listener.js +27 -0
- package/litecoreTxBuilder.js +1128 -0
- package/mmEx.js +356 -0
- package/networks.js +51 -0
- package/orderbook.js +200 -0
- package/package.json +34 -0
- package/perTradeQueue.js +36 -0
- package/projectsTLNPMTLNPM/package-lock.json +162 -0
- package/projectsTLNPMTLNPM/package.json +5 -0
- package/quick.js +32 -0
- package/quickFut.js +37 -0
- package/quickSell.js +37 -0
- package/relayerClient.js +117 -0
- package/run4mm.js +80 -0
- package/run_bbo_tracker.js +241 -0
- package/seller.js +443 -0
- package/session.js +45 -0
- package/setup-lin-ltc.sh +139 -0
- package/setup-lin.sh +203 -0
- package/setup-win-ltc.bat +108 -0
- package/setup-win.bat +167 -0
- package/spam_screamer_futures.js +222 -0
- package/tradelayer.js/.gitattributes +2 -0
- package/tradelayer.js/README.md +2 -0
- package/tradelayer.js/oldTests/activationTest.js +6 -0
- package/tradelayer.js/oldTests/base58.test.js +23 -0
- package/tradelayer.js/oldTests/base64Decode.test.js +16 -0
- package/tradelayer.js/oldTests/blocksRefactor.js +140 -0
- package/tradelayer.js/oldTests/checkVestBalance.js +25 -0
- package/tradelayer.js/oldTests/consensusHashProto.js +151 -0
- package/tradelayer.js/oldTests/contractOrderbook.js +243 -0
- package/tradelayer.js/oldTests/createPayload.js +0 -0
- package/tradelayer.js/oldTests/createTestnetAddr.js +43 -0
- package/tradelayer.js/oldTests/decode.js +205 -0
- package/tradelayer.js/oldTests/decodeTest.js +50 -0
- package/tradelayer.js/oldTests/displayTallyMap.js +19 -0
- package/tradelayer.js/oldTests/encodeDecode.js +340 -0
- package/tradelayer.js/oldTests/expressTest.js +29 -0
- package/tradelayer.js/oldTests/extractBlocksVanilla.js +214 -0
- package/tradelayer.js/oldTests/extractBlocksVanillaa.js +179 -0
- package/tradelayer.js/oldTests/extractPubkeyTest.js +60 -0
- package/tradelayer.js/oldTests/fillInputCacheProto.js +111 -0
- package/tradelayer.js/oldTests/getRawTxTest.js +22 -0
- package/tradelayer.js/oldTests/indexTest.js +26 -0
- package/tradelayer.js/oldTests/initTokensTest.js +32 -0
- package/tradelayer.js/oldTests/interfaceChild.js +129 -0
- package/tradelayer.js/oldTests/listenerChild.js +112 -0
- package/tradelayer.js/oldTests/opdecode.js +26 -0
- package/tradelayer.js/oldTests/options.js +79 -0
- package/tradelayer.js/oldTests/optxtest.js +116 -0
- package/tradelayer.js/oldTests/optxtest1.js +64 -0
- package/tradelayer.js/oldTests/oracle.test.js +32 -0
- package/tradelayer.js/oldTests/orderbook.test.js +36 -0
- package/tradelayer.js/oldTests/parsing.js +93 -0
- package/tradelayer.js/oldTests/payload.js +13 -0
- package/tradelayer.js/oldTests/persistenceUnitTest.js +23 -0
- package/tradelayer.js/oldTests/property.test.js +53 -0
- package/tradelayer.js/oldTests/propertyLevel.js +75 -0
- package/tradelayer.js/oldTests/propertyTest.js +32 -0
- package/tradelayer.js/oldTests/queryAddressTest.js +17 -0
- package/tradelayer.js/oldTests/salter.js +14 -0
- package/tradelayer.js/oldTests/tally.js +81 -0
- package/tradelayer.js/oldTests/tally.test.js +48 -0
- package/tradelayer.js/oldTests/tally2.js +124 -0
- package/tradelayer.js/oldTests/tally3.js +142 -0
- package/tradelayer.js/oldTests/tallyDiag.js +38 -0
- package/tradelayer.js/oldTests/testGetRaw.js +40 -0
- package/tradelayer.js/oldTests/testHexConvert.js +47 -0
- package/tradelayer.js/oldTests/testNewEncoding.js +96 -0
- package/tradelayer.js/oldTests/testNewEncoding2.js +113 -0
- package/tradelayer.js/oldTests/testNewEncoding3 +112 -0
- package/tradelayer.js/oldTests/testNewEncoding3.js +168 -0
- package/tradelayer.js/oldTests/testOPReturn.js +102 -0
- package/tradelayer.js/oldTests/testPayload.js +23 -0
- package/tradelayer.js/oldTests/testRaw.js +50 -0
- package/tradelayer.js/oldTests/testSendTooMuch.js +20 -0
- package/tradelayer.js/oldTests/testTxBuild +28 -0
- package/tradelayer.js/oldTests/testTxBuild.js +42 -0
- package/tradelayer.js/oldTests/tokenOrderbook.js +243 -0
- package/tradelayer.js/oldTests/txUtilsA.js +515 -0
- package/tradelayer.js/oldTests/validityUnitTest.js +53 -0
- package/tradelayer.js/oldTests/vaults.js +72 -0
- package/tradelayer.js/oldTests/volumeIndex.js +117 -0
- package/tradelayer.js/oldTests/volumeIndex2.js +88 -0
- package/tradelayer.js/output_base64.txt +1 -0
- package/tradelayer.js/package-lock.json +9967 -0
- package/tradelayer.js/package.json +61 -0
- package/tradelayer.js/server/index.js +88 -0
- package/tradelayer.js/server/litecoind.exe +0 -0
- package/tradelayer.js/src/activation.js +303 -0
- package/tradelayer.js/src/adjuster.js +77 -0
- package/tradelayer.js/src/amm.js +400 -0
- package/tradelayer.js/src/base256.js +55 -0
- package/tradelayer.js/src/base94.js +79 -0
- package/tradelayer.js/src/channels.js +1163 -0
- package/tradelayer.js/src/clearing.js +3109 -0
- package/tradelayer.js/src/clearlist.js +364 -0
- package/tradelayer.js/src/client.js +295 -0
- package/tradelayer.js/src/consensus.js +613 -0
- package/tradelayer.js/src/contractRegistry.js +964 -0
- package/tradelayer.js/src/db.js +89 -0
- package/tradelayer.js/src/init.js +24 -0
- package/tradelayer.js/src/insurance.js +347 -0
- package/tradelayer.js/src/interface.js +218 -0
- package/tradelayer.js/src/interfaceExpress.js +178 -0
- package/tradelayer.js/src/iou.js +509 -0
- package/tradelayer.js/src/listener.js +226 -0
- package/tradelayer.js/src/logic.js +1702 -0
- package/tradelayer.js/src/main.js +927 -0
- package/tradelayer.js/src/marginMap.js +2165 -0
- package/tradelayer.js/src/options.js +126 -0
- package/tradelayer.js/src/oracle.js +394 -0
- package/tradelayer.js/src/orderbook.js +4123 -0
- package/tradelayer.js/src/persistence.js +554 -0
- package/tradelayer.js/src/property.js +411 -0
- package/tradelayer.js/src/reOrg.js +41 -0
- package/tradelayer.js/src/scaling.js +145 -0
- package/tradelayer.js/src/tally.js +1275 -0
- package/tradelayer.js/src/tradeHistoryManager.js +552 -0
- package/tradelayer.js/src/txDecoder.js +584 -0
- package/tradelayer.js/src/txEncoder.js +610 -0
- package/tradelayer.js/src/txIndex.js +502 -0
- package/tradelayer.js/src/txUtils.js +1392 -0
- package/tradelayer.js/src/types.js +429 -0
- package/tradelayer.js/src/validity.js +3077 -0
- package/tradelayer.js/src/vaults.js +430 -0
- package/tradelayer.js/src/vesting.js +491 -0
- package/tradelayer.js/src/volumeIndex.js +618 -0
- package/tradelayer.js/src/walletInterface.js +220 -0
- package/tradelayer.js/src/walletListener.js +665 -0
- package/tradelayer.js/tests/256decode.js +82 -0
- package/tradelayer.js/tests/UTXOracle.js +205 -0
- package/tradelayer.js/tests/base94test.js +23 -0
- package/tradelayer.js/tests/cancelTxTest.js +62 -0
- package/tradelayer.js/tests/contractInterfaceTest.js +48 -0
- package/tradelayer.js/tests/decimalTest.js +65 -0
- package/tradelayer.js/tests/decoderTest.js +100 -0
- package/tradelayer.js/tests/deltaCount.js +47 -0
- package/tradelayer.js/tests/deltaCount2.js +60 -0
- package/tradelayer.js/tests/interfaceTest.js +37 -0
- package/tradelayer.js/tests/mainTest.js +53 -0
- package/tradelayer.js/tests/makeActivationTest.js +24 -0
- package/tradelayer.js/tests/maxHeightTest.js +49 -0
- package/tradelayer.js/tests/reverseHash.js +72 -0
- package/tradelayer.js/tests/sensitiveConsoleOutput.txt +267 -0
- package/tradelayer.js/tests/tallyTest.js +40 -0
- package/tradelayer.js/tests/testBuybacks.js +46 -0
- package/tradelayer.js/tests/testCodeHash.js +49 -0
- package/tradelayer.js/tests/testConsensusHash.js +91 -0
- package/tradelayer.js/tests/testDecode.js +30 -0
- package/tradelayer.js/tests/testEncodingLengths.js +129 -0
- package/tradelayer.js/tests/testGetTx +32 -0
- package/tradelayer.js/tests/testGetTx.js +32 -0
- package/tradelayer.js/tests/testHexHash.js +32 -0
- package/tradelayer.js/tests/testIndexHash.js +35 -0
- package/tradelayer.js/tests/testInitContracts.js +38 -0
- package/tradelayer.js/tests/testMaxConsensus.js +12 -0
- package/tradelayer.js/tests/testMaxSynth.js +44 -0
- package/tradelayer.js/tests/testMint.js +21 -0
- package/tradelayer.js/tests/testNetwork.js +33 -0
- package/tradelayer.js/tests/testOrderbookLoad.js +62 -0
- package/tradelayer.js/tests/testRebates.js +32 -0
- package/tradelayer.js/tests/testRedeem.js +22 -0
- package/tradelayer.js/tests/testTokenTrade.js +39 -0
- package/tradelayer.js/tests/testTxBuild.js +42 -0
- package/tradelayer.js/tests/testUTXOTrade.js +27 -0
- package/tradelayer.js/tests/tokenTradeHistory.js +27 -0
- package/tradelayer.js/tests/tradeFutures.js +40 -0
- package/tradelayer.js/tests/tradeHistoryExample.js +35 -0
- package/tradelayer.js/tests/tradeHistoryLoad.js +15 -0
- package/tradelayer.js/tests/txScanTest.js +134 -0
- package/tradelayer.js/tests/validateTest.js +136 -0
- package/tradelayer.js/tests/vestingTest.js +37 -0
- package/tradelayer.js/utils/activateMainnet.js +59 -0
- package/tradelayer.js/utils/activateMainnetDoge.js +63 -0
- package/tradelayer.js/utils/autocompactdb.js +23 -0
- package/tradelayer.js/utils/base64toHex.js +32 -0
- package/tradelayer.js/utils/broadcastDoge.js +38 -0
- package/tradelayer.js/utils/calcRedeem.js +19 -0
- package/tradelayer.js/utils/checkNetwork.js +27 -0
- package/tradelayer.js/utils/createAddress.js +48 -0
- package/tradelayer.js/utils/createAttestation.js +133 -0
- package/tradelayer.js/utils/createContract.js +118 -0
- package/tradelayer.js/utils/createOracle.js +94 -0
- package/tradelayer.js/utils/createwallet.js +20 -0
- package/tradelayer.js/utils/crossFuturesTrades.js +57 -0
- package/tradelayer.js/utils/crossTokenTrades.js +62 -0
- package/tradelayer.js/utils/dumpPriv.js +29 -0
- package/tradelayer.js/utils/generateChannel.js +34 -0
- package/tradelayer.js/utils/getInfo.js +21 -0
- package/tradelayer.js/utils/hardWipe.js +20 -0
- package/tradelayer.js/utils/hexTo64.js +16 -0
- package/tradelayer.js/utils/importAddress.js +28 -0
- package/tradelayer.js/utils/importpriv.js +20 -0
- package/tradelayer.js/utils/issueOracleContract.js +67 -0
- package/tradelayer.js/utils/issueTokens.js +41 -0
- package/tradelayer.js/utils/listunspent.js +66 -0
- package/tradelayer.js/utils/litecoinClient.js +30 -0
- package/tradelayer.js/utils/loadwallet.js +20 -0
- package/tradelayer.js/utils/publishOracle.js +113 -0
- package/tradelayer.js/utils/sendActivation.js +21 -0
- package/tradelayer.js/utils/sendChannelContractTrade.js +34 -0
- package/tradelayer.js/utils/sendChannelTokenTrade.js +34 -0
- package/tradelayer.js/utils/sendCommit.js +24 -0
- package/tradelayer.js/utils/sendDoge.js +62 -0
- package/tradelayer.js/utils/sendDogeMain.js +67 -0
- package/tradelayer.js/utils/sendDogeTx.js +46 -0
- package/tradelayer.js/utils/sendLTC.js +63 -0
- package/tradelayer.js/utils/sendMainnet.js +62 -0
- package/tradelayer.js/utils/sendTransfer.js +19 -0
- package/tradelayer.js/utils/sendVestTest.js +88 -0
- package/tradelayer.js/utils/sendWithdrawal.js +26 -0
- package/tradelayer.js/utils/simpleStart.js +8 -0
- package/tradelayer.js/utils/startStop.js +27 -0
- package/tradelayer.js/utils/structuredTrades.js +136 -0
- package/tradelayer.js/utils/verifySignature.js +90 -0
- package/tradelayer.js/utils/verifyWitnessAndScriptPubkey.js +41 -0
- package/tradelayer.js/utils/walletCache.js +172 -0
- package/tradelayer.js/utils/walletContractInterface.js +48 -0
- package/tradelayer.js/utils/walletFetchTxs.js +66 -0
- package/tradelayer.js/utils/walletUtils.js +97 -0
- package/tradelayer.js/utils/wipeDB.js +55 -0
- package/tradelayer.js/utils/wipeDBNotTx.js +50 -0
- package/txEncoder.js +529 -0
- package/utility.js +28 -0
- package/verifymessage.js +38 -0
- package/ws-transport.js +311 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(node:*)",
|
|
5
|
+
"Bash(npm list:*)",
|
|
6
|
+
"Bash(dir C:projectsTLNPMTLNPMnode_modules)",
|
|
7
|
+
"Bash(cmd /c \"dir C:\\\\projects\\\\TLNPM\\\\TLNPM\\\\node_modules /b\")",
|
|
8
|
+
"Bash(npm install:*)",
|
|
9
|
+
"Bash(ls:*)",
|
|
10
|
+
"WebFetch(domain:docs.tradelayer.org)"
|
|
11
|
+
]
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tl-algo
|
|
3
|
+
description: Scaffold and develop trading algorithms using the TradeLayer NPM package (tradelayer). Use when the user wants to create a new algo, strategy, or bot that trades on TradeLayer.
|
|
4
|
+
argument-hint: [strategy-description]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# TradeLayer Algorithm Creation
|
|
8
|
+
|
|
9
|
+
You are building a trading algorithm using the `tradelayer` NPM package. The user will describe a strategy and you will produce a working script.
|
|
10
|
+
|
|
11
|
+
## Package API Reference
|
|
12
|
+
|
|
13
|
+
### Initialization
|
|
14
|
+
|
|
15
|
+
```javascript
|
|
16
|
+
const ApiWrapper = require('tradelayer');
|
|
17
|
+
|
|
18
|
+
const api = new ApiWrapper(
|
|
19
|
+
baseURL, // 'http://127.0.0.1' or 'ws://...'
|
|
20
|
+
port, // 3001 (typical)
|
|
21
|
+
test, // true for testnet
|
|
22
|
+
tlAlreadyOn, // true if TL node already running
|
|
23
|
+
address, // LTC address string
|
|
24
|
+
pubkey, // hex pubkey string
|
|
25
|
+
network, // 'LTCTEST' | 'LTC' | 'BTCTEST' | 'BTC'
|
|
26
|
+
relayerOpts // optional { host, port } for fallback relay
|
|
27
|
+
);
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Market Data
|
|
31
|
+
|
|
32
|
+
- `api.getSpotMarkets()` — returns `[{ markets: [{id1, id2, ...}] }]`
|
|
33
|
+
- `api.getFuturesMarkets()` — returns available contract markets
|
|
34
|
+
- `api.getOrderbookData({ type: 'SPOT', first_token, second_token })` — returns `{ bids, asks }` (each level is `{ price, amount, count }`)
|
|
35
|
+
- `api.getOrderbookData({ type: 'FUTURES', contract_id })` — futures book (perp in the orderbook server; see wire format below)
|
|
36
|
+
- `api.getOnChainSpotOrderbook(id1, id2)` — on-chain spot book
|
|
37
|
+
- `api.getOnChainContractOrderbook(contractId)` — on-chain futures book
|
|
38
|
+
|
|
39
|
+
#### Orderbook server wire format (WebSocket)
|
|
40
|
+
|
|
41
|
+
If you are talking to the orderbook server directly (not through a wrapper), expect the following:
|
|
42
|
+
|
|
43
|
+
**Snapshot request (client → server)**
|
|
44
|
+
|
|
45
|
+
Send one of these payload shapes:
|
|
46
|
+
|
|
47
|
+
- By key:
|
|
48
|
+
- `{ "marketKey": "0-5", "depth": 50, "network": "LTCTEST" }`
|
|
49
|
+
- `{ "symbol": "0-5", "depth": 50, "network": "LTCTEST" }`
|
|
50
|
+
- By identifiers (server derives `marketKey`):
|
|
51
|
+
- Spot: `{ "type": "SPOT", "first_token": 0, "second_token": 5, "depth": 50, "network": "LTCTEST" }`
|
|
52
|
+
- Spot `marketKey` is normalized to `min(idA,idB)-max(idA,idB)`.
|
|
53
|
+
- Futures: `{ "type": "FUTURES", "contract_id": 3, "depth": 50, "network": "LTCTEST" }`
|
|
54
|
+
- Futures `marketKey` is `${contract_id}-perp` in this server (no expiry dimension here).
|
|
55
|
+
|
|
56
|
+
**Snapshot response (server → client)**
|
|
57
|
+
|
|
58
|
+
The server emits an `ORDERBOOK_DATA` event with this shape:
|
|
59
|
+
|
|
60
|
+
```json
|
|
61
|
+
{
|
|
62
|
+
"event": "ORDERBOOK_DATA",
|
|
63
|
+
"marketKey": "0-5",
|
|
64
|
+
"orders": {
|
|
65
|
+
"symbol": "0-5",
|
|
66
|
+
"timestamp": 1700000000000,
|
|
67
|
+
"bids": [{ "price": 1.23, "amount": 10.5, "count": 3 }],
|
|
68
|
+
"asks": [{ "price": 1.24, "amount": 9.0, "count": 2 }],
|
|
69
|
+
"checksum": ""
|
|
70
|
+
},
|
|
71
|
+
"isDelta": false,
|
|
72
|
+
"openedOrders": [],
|
|
73
|
+
"history": []
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**Level encoding rules (important for algos)**
|
|
78
|
+
|
|
79
|
+
- Levels are **objects**, not `[price, amount]` tuples: `{ price, amount, count }`.
|
|
80
|
+
- Prices are scaled from engine units as: `price = enginePrice / 100`.
|
|
81
|
+
- Quantities are scaled from engine units as: `amount = abs(engineVisibleQty) / 1e8`.
|
|
82
|
+
- `count` is the number of orders at that level (may be `0` if unavailable).
|
|
83
|
+
|
|
84
|
+
> Note: The `tradelayer` wrapper may return just `{ bids, asks }`; if so, treat those arrays as already-normalized `{ price, amount, count }` in human units.
|
|
85
|
+
|
|
86
|
+
### Balances & Positions
|
|
87
|
+
|
|
88
|
+
- `api.getAllTokenBalancesForAddress(address)` — all token holdings
|
|
89
|
+
- `api.getUTXOBalances(address)` — confirmed LTC balance
|
|
90
|
+
- `api.listUnspent(minConf, maxConf, [addresses])` — raw UTXOs
|
|
91
|
+
- `api.getPosition(address, contractId)` — contract position
|
|
92
|
+
- `api.getFundingHistory(contractId)` — perpetual funding rates
|
|
93
|
+
|
|
94
|
+
### Order Placement
|
|
95
|
+
|
|
96
|
+
```javascript
|
|
97
|
+
// Spot order
|
|
98
|
+
const uuid = await api.sendOrder({
|
|
99
|
+
type: 'SPOT',
|
|
100
|
+
action: 'BUY' | 'SELL',
|
|
101
|
+
isLimitOrder: true,
|
|
102
|
+
keypair: { address, pubkey },
|
|
103
|
+
props: {
|
|
104
|
+
id_for_sale: Number, // property ID being sold
|
|
105
|
+
id_desired: Number, // property ID being bought
|
|
106
|
+
price: Number, // price per unit
|
|
107
|
+
amount: Number, // quantity
|
|
108
|
+
transfer: false // immediate settlement flag
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// Futures order
|
|
113
|
+
const uuid = await api.sendOrder({
|
|
114
|
+
type: 'FUTURES',
|
|
115
|
+
action: 'BUY' | 'SELL',
|
|
116
|
+
isLimitOrder: true,
|
|
117
|
+
keypair: { address, pubkey },
|
|
118
|
+
props: {
|
|
119
|
+
contract_id: Number,
|
|
120
|
+
price: Number,
|
|
121
|
+
amount: Number, // whole integer contracts
|
|
122
|
+
expiry: Number | 'perp' // block height or 'perp'
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
- `api.sendManyOrders([orderDetailsArray])` — batch placement
|
|
128
|
+
- `api.cancelOrder(uuid)` — cancel by UUID
|
|
129
|
+
|
|
130
|
+
### Funding Manager
|
|
131
|
+
|
|
132
|
+
```javascript
|
|
133
|
+
api.funding.canAfford({ ltc: 0.01, contracts: { 5: 100 } });
|
|
134
|
+
const lockId = api.funding.reserve({ ltc: 0.01 });
|
|
135
|
+
api.funding.commit(lockId); // on fill
|
|
136
|
+
api.funding.release(lockId); // on cancel/fail
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Utilities
|
|
140
|
+
|
|
141
|
+
- `api.delay(ms)` — async sleep
|
|
142
|
+
- `api.checkSync()` — blockchain sync status
|
|
143
|
+
- `api.getBlockCount()` — current block height
|
|
144
|
+
- `api.getMyInfo()` — returns `{ address, pubkey }`
|
|
145
|
+
|
|
146
|
+
### WebSocket Events (automatic via sendOrder)
|
|
147
|
+
|
|
148
|
+
- `'new-channel'` — order matched, swap coordination begins automatically
|
|
149
|
+
- `'order:saved'` — order confirmed in orderbook
|
|
150
|
+
- `'order:error'` — order rejected
|
|
151
|
+
- `'order:canceled'` — cancel acknowledged
|
|
152
|
+
|
|
153
|
+
## Property IDs
|
|
154
|
+
|
|
155
|
+
- `0` = LTC (native coin, used in UTXO trades)
|
|
156
|
+
- `1` = TL (TradeLayer native token)
|
|
157
|
+
- `2` = VEST (vesting token — cannot be traded on spot)
|
|
158
|
+
- `3` = LIQ (liquidity reward token)
|
|
159
|
+
- Other IDs = user-issued tokens or synthetic tokens (`s-{propId}-{contractId}`)
|
|
160
|
+
|
|
161
|
+
## Rules & Constraints
|
|
162
|
+
|
|
163
|
+
1. **Contract amounts must be whole integers** — no fractional contracts
|
|
164
|
+
2. **Spot amounts use 8 decimal precision** — use `bignumber.js` for arithmetic
|
|
165
|
+
3. **UTXO trades** (propertyId 0) use a different flow than token-to-token
|
|
166
|
+
4. **Vesting tokens (id 2, 3)** cannot be traded on spot markets
|
|
167
|
+
5. **Order settlement is automatic** — after `sendOrder()`, the package handles multisig swap coordination via WebSocket events
|
|
168
|
+
6. **Testnet** — always develop with `test: true` and `network: 'LTCTEST'` first
|
|
169
|
+
7. **Block confirmation** — trades settle on-chain, expect ~2.5 min per LTC block
|
|
170
|
+
|
|
171
|
+
## Channel Concepts (for advanced algos)
|
|
172
|
+
|
|
173
|
+
- Tokens are committed to multisig channels for off-chain trading
|
|
174
|
+
- Channel trades (type 19 contracts, type 20 tokens) execute within a channel
|
|
175
|
+
- `clearLists` on channels restrict counterparties — at least one side must be attested
|
|
176
|
+
- `payEnabled` allows instant-pay (type 21) within channels
|
|
177
|
+
|
|
178
|
+
## Algorithm Structure Template
|
|
179
|
+
|
|
180
|
+
Every algo should follow this skeleton:
|
|
181
|
+
|
|
182
|
+
```javascript
|
|
183
|
+
require('dotenv').config();
|
|
184
|
+
const ApiWrapper = require('tradelayer');
|
|
185
|
+
const BigNumber = require('bignumber.js');
|
|
186
|
+
|
|
187
|
+
// --- Config ---
|
|
188
|
+
const CONFIG = {
|
|
189
|
+
base: process.env.TL_BASE_URL || 'http://127.0.0.1',
|
|
190
|
+
port: Number(process.env.TL_PORT) || 3001,
|
|
191
|
+
test: process.env.TL_TEST === 'true',
|
|
192
|
+
address: process.env.TL_ADDRESS,
|
|
193
|
+
pubkey: process.env.TL_PUBKEY,
|
|
194
|
+
network: process.env.TL_NETWORK || 'LTCTEST',
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
// --- Strategy parameters (user-defined) ---
|
|
198
|
+
const PARAMS = {
|
|
199
|
+
// Fill in based on strategy description
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
async function main() {
|
|
203
|
+
const api = new ApiWrapper(
|
|
204
|
+
CONFIG.base, CONFIG.port, CONFIG.test, true,
|
|
205
|
+
CONFIG.address, CONFIG.pubkey, CONFIG.network
|
|
206
|
+
);
|
|
207
|
+
|
|
208
|
+
// 1. Wait for sync
|
|
209
|
+
await api.delay(3000);
|
|
210
|
+
|
|
211
|
+
// 2. Fetch initial state
|
|
212
|
+
const balances = await api.getAllTokenBalancesForAddress(CONFIG.address);
|
|
213
|
+
console.log('Balances:', JSON.stringify(balances));
|
|
214
|
+
|
|
215
|
+
// 3. Main loop
|
|
216
|
+
while (true) {
|
|
217
|
+
try {
|
|
218
|
+
// a. Fetch market data
|
|
219
|
+
// b. Compute signal
|
|
220
|
+
// c. Size position / check risk
|
|
221
|
+
// d. Place or cancel orders
|
|
222
|
+
// e. Log state
|
|
223
|
+
|
|
224
|
+
await api.delay(PARAMS.interval || 5000);
|
|
225
|
+
} catch (err) {
|
|
226
|
+
console.error('Loop error:', err.message);
|
|
227
|
+
await api.delay(10000);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
main().catch(console.error);
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## When generating an algo:
|
|
236
|
+
|
|
237
|
+
1. Start from the template above
|
|
238
|
+
2. Fill in PARAMS based on the user's strategy description
|
|
239
|
+
3. Implement signal logic in the main loop
|
|
240
|
+
4. Use `api.funding.canAfford()` before placing orders
|
|
241
|
+
5. Handle errors gracefully — network issues are common
|
|
242
|
+
6. Log all order UUIDs for debugging
|
|
243
|
+
7. Include a graceful shutdown handler (`process.on('SIGINT', ...)`)
|
|
244
|
+
8. If the strategy involves external price feeds (Binance, etc.), use `ccxt` or direct WebSocket — the package has `ccxt` as a dependency
|
|
245
|
+
9. For market making, use `sendManyOrders()` for atomic bid/ask placement
|
|
246
|
+
10. Read existing examples in the project for patterns: `mmEx.js` (market making), `bb_hyperscalper.js` (Bollinger scalper), `daytrader.js` (Fibonacci SMA)
|
|
247
|
+
|
|
248
|
+
## Files to reference for patterns
|
|
249
|
+
|
|
250
|
+
When creating an algo, read these files for real-world examples:
|
|
251
|
+
- `C:\projects\TLNPM\TLNPM\mmEx.js` — dual-layer market maker with Binance hedge
|
|
252
|
+
- `C:\projects\TLNPM\TLNPM\bb_hyperscalper.js` — Bollinger band scalper
|
|
253
|
+
- `C:\projects\TLNPM\TLNPM\daytrader.js` — SMA ladder signals
|
|
254
|
+
- `C:\projects\TLNPM\TLNPM\quick.js` — minimal order example
|
|
255
|
+
- `C:\projects\TLNPM\TLNPM\algoAPI.js` — full API source (read when unsure about a method)
|
package/.gitattributes
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
name: Publish to npm
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- 'v*'
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
id-token: write
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
publish:
|
|
14
|
+
environment: production
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- uses: actions/setup-node@v4
|
|
20
|
+
with:
|
|
21
|
+
node-version: 20
|
|
22
|
+
registry-url: 'https://registry.npmjs.org/'
|
|
23
|
+
|
|
24
|
+
- run: npm ci
|
|
25
|
+
|
|
26
|
+
- run: npm publish --provenance
|
package/4mm.js
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* FourQuoteMM (basic)
|
|
5
|
+
* - Keeps 2 BUY + 2 SELL live at all times
|
|
6
|
+
* - Places immediately using a configured mid
|
|
7
|
+
* - Cancels/replaces if drift from target > replaceTolTicks
|
|
8
|
+
* - No dependency on external BBO; you can update mid via setMid(px)
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const DEFAULTS = {
|
|
12
|
+
id_for_sale: 5, // TLTC
|
|
13
|
+
id_desired: 0, // USDTt
|
|
14
|
+
baseAmount: 0.10,
|
|
15
|
+
tickSize: 0.0001,
|
|
16
|
+
edgeTicks: 12,
|
|
17
|
+
stepTicks: 6,
|
|
18
|
+
replaceTolTicks: 3,
|
|
19
|
+
debounceMs: 180,
|
|
20
|
+
cancelTimeoutMs: 1500,
|
|
21
|
+
placeTimeoutMs: 1500,
|
|
22
|
+
opsPerSecond: 6,
|
|
23
|
+
startPx: 116.70
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
function sleep(ms){ return new Promise(r=>setTimeout(r, ms)); }
|
|
27
|
+
function withTimeout(p, ms, tag){
|
|
28
|
+
let t; const killer = new Promise((_,rej)=>t=setTimeout(()=>rej(new Error(`${tag} timeout ${ms}ms`)), ms));
|
|
29
|
+
return Promise.race([p, killer]).finally(()=>clearTimeout(t));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
class FourQuoteMM {
|
|
33
|
+
constructor(api, cfg = {}) {
|
|
34
|
+
this.api = api;
|
|
35
|
+
this.cfg = { ...DEFAULTS, ...cfg };
|
|
36
|
+
this.mid = this.cfg.startPx;
|
|
37
|
+
|
|
38
|
+
this.live = { BUY: [], SELL: [] }; // [{uuid, px, sz}]
|
|
39
|
+
this.lastTouch = { BUY: 0, SELL: 0 };
|
|
40
|
+
|
|
41
|
+
// simple token bucket to avoid races
|
|
42
|
+
this.bucketCap = this.cfg.opsPerSecond;
|
|
43
|
+
this.bucket = this.bucketCap;
|
|
44
|
+
setInterval(()=>{ this.bucket = this.bucketCap; }, 1000);
|
|
45
|
+
|
|
46
|
+
this._runner = null;
|
|
47
|
+
this._started = false;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
setMid(px){
|
|
51
|
+
if (Number.isFinite(px) && px > 0) this.mid = px;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
start(){
|
|
55
|
+
if (this._started) return;
|
|
56
|
+
this._started = true;
|
|
57
|
+
// fire quickly so we place right away
|
|
58
|
+
this._runner = setInterval(()=>this._tick().catch(()=>{}), 120);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
stop(){
|
|
62
|
+
if (!this._started) return;
|
|
63
|
+
clearInterval(this._runner);
|
|
64
|
+
this._runner = null;
|
|
65
|
+
this._started = false;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
_now(){ return Date.now(); }
|
|
69
|
+
_tooSoon(side, ms){ return this._now() - this.lastTouch[side] < ms; }
|
|
70
|
+
_touch(side){ this.lastTouch[side] = this._now(); }
|
|
71
|
+
_allowOp(){ if (this.bucket <= 0) return false; this.bucket--; return true; }
|
|
72
|
+
|
|
73
|
+
_targets(mid){
|
|
74
|
+
const { tickSize, edgeTicks, stepTicks, baseAmount } = this.cfg;
|
|
75
|
+
const edge = edgeTicks * tickSize;
|
|
76
|
+
const step = stepTicks * tickSize;
|
|
77
|
+
|
|
78
|
+
const BUY = [
|
|
79
|
+
{ px: +(mid - edge).toFixed(8), sz: baseAmount },
|
|
80
|
+
{ px: +(mid - edge - step).toFixed(8), sz: baseAmount },
|
|
81
|
+
];
|
|
82
|
+
const SELL = [
|
|
83
|
+
{ px: +(mid + edge).toFixed(8), sz: baseAmount },
|
|
84
|
+
{ px: +(mid + edge + step).toFixed(8), sz: baseAmount },
|
|
85
|
+
];
|
|
86
|
+
return { BUY, SELL };
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async _place(side, px, sz){
|
|
90
|
+
if (!this._allowOp()) return false;
|
|
91
|
+
const det = (side === 'BUY')
|
|
92
|
+
? { type:'SPOT', action:'BUY', props:{ id_for_sale:this.cfg.id_desired, id_desired:this.cfg.id_for_sale, price:px, amount:sz, transfer:false } }
|
|
93
|
+
: { type:'SPOT', action:'SELL', props:{ id_for_sale:this.cfg.id_for_sale, id_desired:this.cfg.id_desired, price:px, amount:sz, transfer:false } };
|
|
94
|
+
try {
|
|
95
|
+
const res = await withTimeout(this.api.sendOrder(det), this.cfg.placeTimeoutMs, 'place');
|
|
96
|
+
const uuid = res?.orderUuid || res?.uuid || res;
|
|
97
|
+
if (!uuid) throw new Error('no uuid');
|
|
98
|
+
this.live[side].push({ uuid, px, sz });
|
|
99
|
+
console.log('PLACED', side, px, 'uuid=', uuid);
|
|
100
|
+
return true;
|
|
101
|
+
} catch(e) {
|
|
102
|
+
console.log('PLACE FAIL', side, px, e.message || e);
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async _cancel(side, idx, reason){
|
|
108
|
+
if (idx < 0 || idx >= this.live[side].length) return;
|
|
109
|
+
const item = this.live[side][idx];
|
|
110
|
+
if (!item) return;
|
|
111
|
+
if (!this._allowOp()) return;
|
|
112
|
+
try {
|
|
113
|
+
await withTimeout(this.api.cancelOrder(item.uuid), this.cfg.cancelTimeoutMs, 'cancel');
|
|
114
|
+
console.log('CANCELED', side, item.px, 'uuid=', item.uuid, 'reason=', reason);
|
|
115
|
+
} catch(e) {
|
|
116
|
+
console.log('CANCEL FAIL', side, item.uuid, e.message || e);
|
|
117
|
+
} finally {
|
|
118
|
+
this.live[side].splice(idx, 1);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
_needReplacePx(curPx, tgtPx){
|
|
123
|
+
const tol = this.cfg.replaceTolTicks * this.cfg.tickSize;
|
|
124
|
+
return Math.abs(curPx - tgtPx) > tol;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
async _ensureSide(side, targets){
|
|
128
|
+
if (this._tooSoon(side, this.cfg.debounceMs)) return;
|
|
129
|
+
this._touch(side);
|
|
130
|
+
|
|
131
|
+
// trim any excess
|
|
132
|
+
while (this.live[side].length > 2) {
|
|
133
|
+
await this._cancel(side, this.live[side].length - 1, 'excess');
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// replace where drifted
|
|
137
|
+
for (let i = 0; i < Math.min(2, this.live[side].length); i++) {
|
|
138
|
+
const live = this.live[side][i];
|
|
139
|
+
const tgt = targets[i];
|
|
140
|
+
if (!live || !tgt) continue;
|
|
141
|
+
if (this._needReplacePx(live.px, tgt.px)) {
|
|
142
|
+
await this._cancel(side, i, 'reprice');
|
|
143
|
+
await this._place(side, tgt.px, tgt.sz);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// place missing
|
|
148
|
+
for (let i = this.live[side].length; i < 2; i++) {
|
|
149
|
+
const tgt = targets[i];
|
|
150
|
+
if (!tgt) break;
|
|
151
|
+
await this._place(side, tgt.px, tgt.sz);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
async _tick(){
|
|
156
|
+
// targets from current mid (always defined)
|
|
157
|
+
const t = this._targets(this.mid);
|
|
158
|
+
await this._ensureSide('BUY', t.BUY);
|
|
159
|
+
await this._ensureSide('SELL', t.SELL);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
module.exports = FourQuoteMM;
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Patrick Dugan
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
Binary file
|