@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,411 @@
|
|
|
1
|
+
const db = require('./db.js');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const BigNumber = require('bignumber.js')
|
|
4
|
+
|
|
5
|
+
class PropertyManager {
|
|
6
|
+
static instance = null;
|
|
7
|
+
|
|
8
|
+
constructor() {
|
|
9
|
+
if (PropertyManager.instance) {
|
|
10
|
+
return PropertyManager.instance;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
this.propertyIndex = new Map();
|
|
14
|
+
this.ammIndex = new Map(); // Initialize AMM index
|
|
15
|
+
//this.synthIndex= new Map()
|
|
16
|
+
PropertyManager.instance = this;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
static getInstance() {
|
|
20
|
+
if (!PropertyManager.instance) {
|
|
21
|
+
PropertyManager.instance = new PropertyManager();
|
|
22
|
+
}
|
|
23
|
+
return PropertyManager.instance;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
static async load() {
|
|
27
|
+
//console.log('loading property list');
|
|
28
|
+
try {
|
|
29
|
+
const instance = PropertyManager.getInstance();
|
|
30
|
+
const base = await db.getDatabase('propertyList')
|
|
31
|
+
const propertyIndexEntry = await base.findOneAsync({ _id: 'propertyIndex' });
|
|
32
|
+
if (propertyIndexEntry && propertyIndexEntry.value) {
|
|
33
|
+
// Check if the value is a string and parse it as JSON
|
|
34
|
+
const data = typeof propertyIndexEntry.value === 'string' ? JSON.parse(propertyIndexEntry.value) : propertyIndexEntry.value;
|
|
35
|
+
|
|
36
|
+
// Ensure the data is an array of arrays before converting it to a Map
|
|
37
|
+
if (Array.isArray(data) && data.every(item => Array.isArray(item) && item.length === 2)) {
|
|
38
|
+
instance.propertyIndex = new Map(data);
|
|
39
|
+
} else {
|
|
40
|
+
console.error('Invalid data format for propertyIndex:', data);
|
|
41
|
+
instance.propertyIndex = new Map();
|
|
42
|
+
}
|
|
43
|
+
} else {
|
|
44
|
+
instance.propertyIndex = new Map(); // Initialize with an empty Map if no data is found
|
|
45
|
+
}
|
|
46
|
+
} catch (error) {
|
|
47
|
+
console.error('Error loading data from NeDB:', error);
|
|
48
|
+
//instance.propertyIndex = new Map(); // Use an empty Map in case of an error
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
async getNextPropertyId() {
|
|
54
|
+
await PropertyManager.load();
|
|
55
|
+
let maxId = 0;
|
|
56
|
+
for (let key of this.propertyIndex.keys()) {
|
|
57
|
+
maxId = Math.max(maxId, key);
|
|
58
|
+
}
|
|
59
|
+
return maxId + 1;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async createToken(ticker, totalInCirculation, type, whitelistId, issuer, backupAddress) {
|
|
63
|
+
// Check if the ticker already exists
|
|
64
|
+
|
|
65
|
+
if (this.propertyIndex.has(ticker)) {
|
|
66
|
+
return new (`Error: Ticker "${ticker}" already exists.`);
|
|
67
|
+
}
|
|
68
|
+
for (let [key, value] of this.propertyIndex.entries()) {
|
|
69
|
+
if (value.ticker === ticker) {
|
|
70
|
+
return Error(`Ticker "${ticker}" already exists.`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const propertyId = await this.getNextPropertyId();
|
|
75
|
+
await this.addProperty(propertyId, ticker, totalInCirculation, type, whitelistId, issuer, backupAddress);
|
|
76
|
+
console.log(`Token created: ID = ${propertyId}, Ticker = ${ticker}, Type = ${type}`);
|
|
77
|
+
return propertyId;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async addProperty(propertyId, ticker, totalInCirculation, type, whitelistId, issuer, backupAddress) {
|
|
81
|
+
|
|
82
|
+
const propertyTypeIndexes = {
|
|
83
|
+
'Fixed': 1,
|
|
84
|
+
'Managed': 2,
|
|
85
|
+
'Native': 3,
|
|
86
|
+
'Vesting': 4,
|
|
87
|
+
'Synthetic': 5,
|
|
88
|
+
'Non-Fungible': 6,
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
if (!propertyTypeIndexes[type]) {
|
|
92
|
+
throw new Error('Invalid property type.');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
let existingProperty = this.propertyIndex.get(propertyId);
|
|
96
|
+
|
|
97
|
+
if(type=="Synthetic"){
|
|
98
|
+
console.log('creating synth property '+propertyId+' '+totalInCirculation+' '+existingProperty)
|
|
99
|
+
// Retrieve existing property entry if it exists
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (existingProperty) {
|
|
103
|
+
// If property exists, update totalInCirculation and other fields if necessary
|
|
104
|
+
existingProperty.totalInCirculation = BigNumber(existingProperty.totalInCirculation).plus(totalInCirculation).toNumber();
|
|
105
|
+
existingProperty.ticker = ticker || existingProperty.ticker;
|
|
106
|
+
existingProperty.type = propertyTypeIndexes[type];
|
|
107
|
+
existingProperty.whitelistId = whitelistId || existingProperty.whitelistId;
|
|
108
|
+
existingProperty.issuer = issuer || existingProperty.issuer;
|
|
109
|
+
existingProperty.backupAddress = backupAddress || existingProperty.backupAddress;
|
|
110
|
+
} else {
|
|
111
|
+
// If property does not exist, create a new one
|
|
112
|
+
existingProperty = {
|
|
113
|
+
ticker,
|
|
114
|
+
totalInCirculation,
|
|
115
|
+
type: propertyTypeIndexes[type],
|
|
116
|
+
whitelistId: whitelistId,
|
|
117
|
+
issuer: issuer,
|
|
118
|
+
backupAddress: backupAddress
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
let blob = {
|
|
123
|
+
ticker,
|
|
124
|
+
totalInCirculation,
|
|
125
|
+
type: propertyTypeIndexes[type],
|
|
126
|
+
whitelistId: whitelistId,
|
|
127
|
+
issuer: issuer,
|
|
128
|
+
backupAddress: backupAddress
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
this.propertyIndex.set(propertyId,existingProperty);
|
|
132
|
+
await this.save();
|
|
133
|
+
return console.log('updated Property Index '+this.propertyIndex)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
async inspectPropertyIndex() {
|
|
137
|
+
const propertyManager = PropertyManager.getInstance();
|
|
138
|
+
|
|
139
|
+
// Load the properties
|
|
140
|
+
await PropertyManager.load();
|
|
141
|
+
|
|
142
|
+
// Convert the Map into an array of key-value pairs
|
|
143
|
+
const propertiesArray = Array.from(propertyManager.propertyIndex.entries());
|
|
144
|
+
|
|
145
|
+
// Alternatively, convert the Map into an object for easier visualization
|
|
146
|
+
const propertiesObject = Object.fromEntries(propertyManager.propertyIndex);
|
|
147
|
+
|
|
148
|
+
console.log('Properties as Array:', propertiesArray);
|
|
149
|
+
console.log('Properties as Object:', propertiesObject);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
static async getAMM(propertyId1, propertyId2) {
|
|
153
|
+
const pairKey = `${propertyId1}-${propertyId2}`;
|
|
154
|
+
const ammInstance = PropertyRegistry.getInstance().ammIndex.get(pairKey);
|
|
155
|
+
|
|
156
|
+
if (ammInstance) {
|
|
157
|
+
return ammInstance;
|
|
158
|
+
} else {
|
|
159
|
+
// If AMM instance doesn't exist, initialize it
|
|
160
|
+
const newAMM = await initializeAMM(propertyId1, propertyId2); // You need to define the initialization logic
|
|
161
|
+
PropertyRegistry.getInstance().ammIndex.set(pairKey, newAMM);
|
|
162
|
+
return newAMM;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
static async isManagedAndAdmin(propertyId,address) {
|
|
167
|
+
try {
|
|
168
|
+
// Load the property index from the database
|
|
169
|
+
const base = await db.getDatabase('propertyList');
|
|
170
|
+
const propertyIndex = await base.findOneAsync({ _id: 'propertyIndex' });
|
|
171
|
+
|
|
172
|
+
if (!propertyIndex || !propertyIndex.value) {
|
|
173
|
+
throw new Error('Property index not found.');
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Parse the JSON string to get the array of arrays
|
|
177
|
+
const parsedIndex = JSON.parse(propertyIndex.value);
|
|
178
|
+
|
|
179
|
+
// Find the property entry by propertyId
|
|
180
|
+
const propertyEntry = parsedIndex.find(entry => entry[0] === propertyId);
|
|
181
|
+
|
|
182
|
+
if (!propertyEntry) {
|
|
183
|
+
throw new Error(`Property with ID ${propertyId} not found.`);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Check if the property type is 2 (Managed)
|
|
187
|
+
const propertyData = propertyEntry[1];
|
|
188
|
+
return propertyData.type === 2&&propertyData.issuer===address;
|
|
189
|
+
} catch (error) {
|
|
190
|
+
console.error(`Error checking if property ID ${propertyId} is managed:`, error);
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
static async updateTotalInCirculation(propertyId, amountChange) {
|
|
199
|
+
const propertyData = await PropertyManager.getPropertyData(propertyId);
|
|
200
|
+
|
|
201
|
+
if (!propertyData) {
|
|
202
|
+
throw new Error('Property not found');
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
propertyData.totalInCirculation = BigNumber(propertyData.totalInCirculation).plus(amountChange).toNumber();
|
|
206
|
+
|
|
207
|
+
// Update the property data in the database
|
|
208
|
+
const base= await db.getDatabase('propertyList')
|
|
209
|
+
const propertyIndex = await base.findOneAsync({ _id: 'propertyIndex' });
|
|
210
|
+
const parsedData = JSON.parse(propertyIndex.value);
|
|
211
|
+
|
|
212
|
+
const propertyEntry = parsedData.find(entry => entry[0] === propertyId);
|
|
213
|
+
if (propertyEntry) {
|
|
214
|
+
propertyEntry[1] = propertyData;
|
|
215
|
+
const base = db.getDatabase('propertyList')
|
|
216
|
+
await base.updateAsync({ _id: 'propertyIndex' }, { $set: { value: JSON.stringify(parsedData) } });
|
|
217
|
+
} else {
|
|
218
|
+
throw new Error('Failed to update totalInCirculation, property not found in index');
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
async save() {
|
|
224
|
+
const propertyIndexJSON = JSON.stringify([...this.propertyIndex.entries()]);
|
|
225
|
+
const propertyIndexData = { _id: 'propertyIndex', value: propertyIndexJSON };
|
|
226
|
+
|
|
227
|
+
try {
|
|
228
|
+
const propertyListDB = await db.getDatabase('propertyList');
|
|
229
|
+
await propertyListDB.updateAsync({ _id: 'propertyIndex' }, propertyIndexData, { upsert: true });
|
|
230
|
+
} catch (err) {
|
|
231
|
+
console.error('Error saving property index:', err);
|
|
232
|
+
throw err;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
static async getPropertyIndex() {
|
|
239
|
+
const instance = PropertyManager.getInstance();
|
|
240
|
+
|
|
241
|
+
// If the propertyIndex is empty, load it first
|
|
242
|
+
if (instance.propertyIndex.size === 0) {
|
|
243
|
+
await PropertyManager.load();
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Transform the Map into an array of objects, each representing a property
|
|
247
|
+
return Array.from(instance.propertyIndex).map(([id, property]) => ({
|
|
248
|
+
id,
|
|
249
|
+
ticker: property.ticker,
|
|
250
|
+
totalInCirculation: property.totalInCirculation,
|
|
251
|
+
type: property.type
|
|
252
|
+
}));
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Checks if the given ticker already exists in the property index.
|
|
258
|
+
* @param {string} ticker - The ticker to check for existence.
|
|
259
|
+
* @returns {boolean} - True if the ticker exists, false otherwise.
|
|
260
|
+
*/
|
|
261
|
+
static async doesTickerExist(ticker) {
|
|
262
|
+
// Ensure the property index is loaded before checking
|
|
263
|
+
const base = await db.getDatabase('propertyList')
|
|
264
|
+
const index = await base.findOneAsync({ _id: 'propertyIndex' });
|
|
265
|
+
|
|
266
|
+
if(!index){
|
|
267
|
+
return false
|
|
268
|
+
}
|
|
269
|
+
// Parse the JSON string to get the actual array
|
|
270
|
+
const parsedIndex = JSON.parse(index.value);
|
|
271
|
+
|
|
272
|
+
// Iterate over the parsed array to check for the ticker
|
|
273
|
+
for (let [propertyId, propertyData] of parsedIndex) {
|
|
274
|
+
if (propertyData.ticker === ticker) {
|
|
275
|
+
return true;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
return false;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Checks if the given propertyId is a synthetic token.
|
|
284
|
+
* @param {number} propertyId - The ID of the property to check.
|
|
285
|
+
* @returns {boolean} - True if the property is a synthetic token, false otherwise.
|
|
286
|
+
*/
|
|
287
|
+
static async isSyntheticToken(propertyId) {
|
|
288
|
+
if(!this.propertyIndex){await this.load();} // Make sure the property list is loaded
|
|
289
|
+
const propertyInfo = this.propertyIndex.get(propertyId);
|
|
290
|
+
// Check if the propertyInfo is valid and the type is 5 (synthetic)
|
|
291
|
+
return propertyInfo && propertyInfo.type === 5;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
async grantTokens(propertyId, recipient, amount,block) {
|
|
295
|
+
const propertyData = await this.getPropertyData(propertyId);
|
|
296
|
+
if (!propertyData) {
|
|
297
|
+
throw new Error(`Property with ID ${propertyId} not found.`);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// Update managed supply
|
|
301
|
+
propertyData.totalInCirculation += amount;
|
|
302
|
+
|
|
303
|
+
// Update tally map to credit the amount to recipient
|
|
304
|
+
await TallyMap.updateBalance(recipient, propertyId, amount,0,0,0,'grantToken',block);
|
|
305
|
+
|
|
306
|
+
// Save changes
|
|
307
|
+
await this.save();
|
|
308
|
+
console.log(`Granted ${amount} managed tokens to ${recipient} for property ${propertyId}.`);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
async redeemTokens(propertyId, recipient, amount,block) {
|
|
312
|
+
const propertyData = await this.getPropertyData(propertyId);
|
|
313
|
+
if (!propertyData) {
|
|
314
|
+
throw new Error(`Property with ID ${propertyId} not found.`);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// Ensure enough managed tokens available for redemption
|
|
318
|
+
if (propertyData.totalInCirculation < amount) {
|
|
319
|
+
throw new Error(`Insufficient managed tokens for redemption for property ${propertyId}.`);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// Update managed supply
|
|
323
|
+
propertyData.totalInCirculation -= amount;
|
|
324
|
+
|
|
325
|
+
// Update tally map to debit the amount from recipient
|
|
326
|
+
await TallyMap.updateBalance(recipient, propertyId, -amount,0,0,0,'redeemToken',block);
|
|
327
|
+
|
|
328
|
+
// Save changes
|
|
329
|
+
await this.save();
|
|
330
|
+
console.log(`Redeemed ${amount} managed tokens from ${recipient} for property ${propertyId}.`);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
static async getPropertyData(propertyId) {
|
|
335
|
+
try {
|
|
336
|
+
const base = await db.getDatabase('propertyList')
|
|
337
|
+
const propertyData = await base.findOneAsync({ _id: 'propertyIndex' });
|
|
338
|
+
//console.log('property list ' +JSON.stringify(propertyData))
|
|
339
|
+
if (propertyData && propertyData.value) {
|
|
340
|
+
const parsedData = JSON.parse(propertyData.value);
|
|
341
|
+
//console.log(propertyId)
|
|
342
|
+
// Check if propertyId is a synthetic ID
|
|
343
|
+
if (typeof propertyId === 'string' && propertyId.startsWith('s')) {
|
|
344
|
+
console.log('inside get property synthetic '+propertyId)
|
|
345
|
+
const syntheticEntry = parsedData.find(entry => entry[0] === propertyId);
|
|
346
|
+
console.log(JSON.stringify(syntheticEntry))
|
|
347
|
+
if (syntheticEntry) {
|
|
348
|
+
return syntheticEntry[1];
|
|
349
|
+
}/* else {
|
|
350
|
+
// Optionally, look for the synthetic ID in a separate registry
|
|
351
|
+
const syntheticData = await db.getDatabase('syntheticTokens').findOneAsync({ _id: propertyId });
|
|
352
|
+
return syntheticData ? JSON.parse(syntheticData.value) : null;
|
|
353
|
+
}*/
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// Check for integer-based property ID
|
|
357
|
+
//console.log('propertyId:', propertyId, 'type:', typeof propertyId);
|
|
358
|
+
const propertyEntry = parsedData.find(entry => Number(entry[0]) === Number(propertyId));
|
|
359
|
+
//console.log('retrieving property data '+JSON.stringify(propertyEntry)+' '+JSON.stringify(parsedData))
|
|
360
|
+
if (propertyEntry) {
|
|
361
|
+
return propertyEntry[1];
|
|
362
|
+
} else {
|
|
363
|
+
return null;
|
|
364
|
+
}
|
|
365
|
+
} else {
|
|
366
|
+
return null; // Return null if no property data found in the database
|
|
367
|
+
}
|
|
368
|
+
} catch (error) {
|
|
369
|
+
console.error('Error fetching property data:', error);
|
|
370
|
+
return null; // Return null in case of any errors
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
static async updateAdmin(propertyId, newAddress, backup) {
|
|
376
|
+
try {
|
|
377
|
+
// Ensure the property index is loaded
|
|
378
|
+
await PropertyManager.load();
|
|
379
|
+
|
|
380
|
+
// Check if the property exists
|
|
381
|
+
if (!PropertyManager.instance.propertyIndex.has(propertyId)) {
|
|
382
|
+
throw new Error(`Property with ID ${propertyId} does not exist.`);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// Get the property data
|
|
386
|
+
const propertyData = await getPropertyData(propertyId);
|
|
387
|
+
|
|
388
|
+
if(backup){
|
|
389
|
+
properData.backupAddress=newAddress
|
|
390
|
+
}else{
|
|
391
|
+
// Update the admin address
|
|
392
|
+
propertyData.issuer = newAddress;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// Update the property index with the modified property data
|
|
396
|
+
this.propertyIndex.set(propertyId, propertyData);
|
|
397
|
+
|
|
398
|
+
await this.save();
|
|
399
|
+
|
|
400
|
+
console.log(`Admin address for property ID ${propertyId} updated to ${newAddress}.`);
|
|
401
|
+
} catch (error) {
|
|
402
|
+
console.error(`Error updating admin address for property ID ${propertyId}:`, error);
|
|
403
|
+
throw error;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
// ... other methods like verifyIfManaged, updateAdmin ...
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
module.exports = PropertyManager;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const litecoin = require('litecoin');
|
|
2
|
+
const config = {host: '127.0.0.1',
|
|
3
|
+
port: 18332,
|
|
4
|
+
user: 'user',
|
|
5
|
+
pass: 'pass',
|
|
6
|
+
timeout: 10000}
|
|
7
|
+
|
|
8
|
+
class ReOrgChecker {
|
|
9
|
+
constructor(config) {
|
|
10
|
+
this.client = new litecoin.Client(config);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async getBlock(hash) {
|
|
14
|
+
try {
|
|
15
|
+
return await this.client.getBlock(hash);
|
|
16
|
+
} catch (error) {
|
|
17
|
+
console.error('Error fetching block:', error);
|
|
18
|
+
throw error;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async checkReOrg() {
|
|
23
|
+
try {
|
|
24
|
+
const chainTips = await this.client.cmd('getchaintips');
|
|
25
|
+
const potentialReorgs = chainTips.filter(tip => tip.status === 'valid-fork' || tip.status === 'headers-only');
|
|
26
|
+
|
|
27
|
+
for (const tip of potentialReorgs) {
|
|
28
|
+
const block = await this.getBlock(tip.hash);
|
|
29
|
+
// Compare this block with your database
|
|
30
|
+
// If this block is not in your main chain, a reorg might have occurred
|
|
31
|
+
|
|
32
|
+
console.log(`Potential reorg detected at block ${block.height}: ${block.hash}`);
|
|
33
|
+
// Implement additional logic to handle reorg if needed
|
|
34
|
+
}
|
|
35
|
+
} catch (error) {
|
|
36
|
+
console.error('Error in checkReOrg:', error);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
module.exports = ReOrgChecker;
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
const data = require('./db.js');
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
const Scaling = {
|
|
5
|
+
// Check if a settlement has already been neutralized
|
|
6
|
+
async isThisSettlementAlreadyNeutralized(channel, txid) {
|
|
7
|
+
const settlements = await this.getFileByChannel(txid, channel);
|
|
8
|
+
|
|
9
|
+
// If settlements is undefined or empty, no settlement has been recorded yet
|
|
10
|
+
if (!settlements || settlements.length === 0) {
|
|
11
|
+
return false; // Return false if no settlements found
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Loop through settlements array to check if the txid exists and is neutralized
|
|
15
|
+
for (const settlement of settlements) {
|
|
16
|
+
if (settlement.txid === txid && settlement.status=='neutralized') {
|
|
17
|
+
return true; // Return true if the txid is found and is neutralized
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return false; // Return false if txid is not found or not neutralized
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
// Mark a settlement as neutralized
|
|
25
|
+
async neutralizeSettlement(channel, txid){
|
|
26
|
+
let settlements = await this.getFileByChannel(channel, txid);
|
|
27
|
+
let settlement = null
|
|
28
|
+
for(const item of settlements){
|
|
29
|
+
if (item.txid === txid && item.status=='neutralized') {
|
|
30
|
+
settlement=item; // Return true if the txid is found and is neutralized
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (settlement==null) {
|
|
34
|
+
settlement = {txid: txid, status: 'neutralized' };
|
|
35
|
+
} else {
|
|
36
|
+
settlement.status = "neutralized";
|
|
37
|
+
}
|
|
38
|
+
await this.recordTransaction(channel,settlement);
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
// Check if a trade has been published or if it's in a certain status (live, expired, unpublished)
|
|
42
|
+
async isTradePublished(txidNeutralized1){
|
|
43
|
+
const trade = await this.getTradeByTxid(txidNeutralized1);
|
|
44
|
+
if (!trade) {
|
|
45
|
+
return { status: "unpublished" };
|
|
46
|
+
} else if (trade.expired && trade.type === "contract") {
|
|
47
|
+
return { status: "expiredContract", params: trade };
|
|
48
|
+
} else if (trade.expired && trade.type === "token") {
|
|
49
|
+
return { status: "expiredToken", params: trade };
|
|
50
|
+
} else {
|
|
51
|
+
return { status: trade.live ? "liveContract" : "liveToken", params: trade };
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
// Put settlement into a limbo state if trade is not yet published
|
|
56
|
+
async settlementLimbo(channel, txid) {
|
|
57
|
+
const limbo = { txid, status: "pending" };
|
|
58
|
+
await this.saveSettlement(channel, limbo);
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
// Generate an offset based on the trade parameters and the current mark price
|
|
62
|
+
generateOffset(tradeParams, markPrice) {
|
|
63
|
+
// Assume some logic here to calculate the offset based on the markPrice vs original trade price
|
|
64
|
+
const offsetAmount = calculatePNL(tradeParams, markPrice);
|
|
65
|
+
const offsetParams = { ...tradeParams, adjustedAmount: offsetAmount };
|
|
66
|
+
return { params: offsetParams };
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
// Query prior settlements related to the transaction for chaining logic
|
|
70
|
+
async queryPriorSettlements(txidNeutralized1, txidNeutralized2, channelAddress) {
|
|
71
|
+
// Assume logic here to look up prior settlements in the same channel
|
|
72
|
+
const settlements = await this.getFileByChannel(txidNeutralized1, channelAddress);
|
|
73
|
+
return settlements;
|
|
74
|
+
},
|
|
75
|
+
|
|
76
|
+
// Settle the PNL based on the mark price and previous settlements
|
|
77
|
+
async settlePNL(lastSettlement, markPrice, txidNeutralized1) {
|
|
78
|
+
const lastPrice = lastSettlement ? lastSettlement.markPrice : null;
|
|
79
|
+
const pnlAmount = calculatePNL({ previousPrice: lastPrice, markPrice });
|
|
80
|
+
|
|
81
|
+
// Store the final settlement
|
|
82
|
+
const finalSettlement = { txid: txidNeutralized1, markPrice, pnlAmount };
|
|
83
|
+
await this.saveSettlement(finalSettlement);
|
|
84
|
+
|
|
85
|
+
return finalSettlement;
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
// Helper function to get a settlement by its txid
|
|
89
|
+
async getSettlementByTxid(channel, txid) {
|
|
90
|
+
// Assume logic to get settlement from the database
|
|
91
|
+
const db = await data.getDatabase('scaling');
|
|
92
|
+
return await db.findOneAsync({ txid });
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
// Function to update a specific part of the document
|
|
97
|
+
async recordTransaction(channelAddress, txid, txType, status) {
|
|
98
|
+
// Fetch the full document or initialize a new one if it doesn't exist
|
|
99
|
+
let scalingData = await scalingDb.findOneAsync({ _id: channelAddress }) || {
|
|
100
|
+
_id: channelAddress,
|
|
101
|
+
contractTrades: [],
|
|
102
|
+
tokenTrades: [],
|
|
103
|
+
settlements: [],
|
|
104
|
+
misc: []
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
// Determine the transaction type and update the appropriate array
|
|
108
|
+
switch (txType) {
|
|
109
|
+
case 19: // Contract trade
|
|
110
|
+
scalingData.contractTrades.push({ txid: txid, status: status });
|
|
111
|
+
break;
|
|
112
|
+
case 20: // Token trade
|
|
113
|
+
scalingData.tokenTrades.push({ txid: txid, status: status });
|
|
114
|
+
break;
|
|
115
|
+
case 23: // Settlement
|
|
116
|
+
scalingData.settlements.push({ txid: txid, status: status });
|
|
117
|
+
break;
|
|
118
|
+
default: // Miscellaneous transactions
|
|
119
|
+
scalingData.misc.push({ txid: txid, status: status });
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Save or update the document in the database
|
|
124
|
+
await scalingDb.updateAsync({ _id: channelAddress }, scalingData, { upsert: true });
|
|
125
|
+
},
|
|
126
|
+
|
|
127
|
+
// Helper function to get settlements based on txid and channel
|
|
128
|
+
async getFileByChannel(channelAddress, type) {
|
|
129
|
+
const db = await data.getDatabase('scaling');
|
|
130
|
+
const query = { _id: channelAddress }; // Searching by channelAddress
|
|
131
|
+
const doc = await db.findOneAsync(query);
|
|
132
|
+
|
|
133
|
+
// If no doc or settlements exist for the channel, return an empty array
|
|
134
|
+
return doc && doc.settlements ? doc.settlements : [];
|
|
135
|
+
},
|
|
136
|
+
|
|
137
|
+
// Mock function to calculate PNL (replace with your actual logic)
|
|
138
|
+
calculatePNL({ previousPrice, markPrice }) {
|
|
139
|
+
// Simple PNL calculation, replace with actual formula
|
|
140
|
+
return markPrice - previousPrice;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
module.exports = Scaling;
|