@totemsdk/core 1.2.6 → 1.2.8
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/dist/MiniNumber.js +9 -1
- package/dist/canonical.d.ts +3 -0
- package/dist/canonical.js +22 -0
- package/dist/cjs/MiniNumber.d.ts +47 -0
- package/dist/cjs/MiniNumber.js +310 -0
- package/dist/cjs/Streamable.d.ts +268 -0
- package/dist/cjs/Streamable.js +439 -0
- package/dist/cjs/adapters/index.d.ts +190 -0
- package/dist/cjs/adapters/index.js +118 -0
- package/dist/cjs/adapters/types.d.ts +150 -0
- package/dist/cjs/adapters/types.js +81 -0
- package/dist/cjs/binio.d.ts +9 -0
- package/dist/cjs/binio.js +25 -0
- package/dist/cjs/bip39.d.ts +91 -0
- package/dist/cjs/bip39.js +434 -0
- package/dist/cjs/canonical.d.ts +3 -0
- package/dist/cjs/canonical.js +27 -0
- package/dist/cjs/derive.d.ts +2 -0
- package/dist/cjs/derive.js +13 -0
- package/dist/cjs/index.d.ts +49 -0
- package/dist/cjs/index.js +231 -0
- package/dist/cjs/javaStreamables.d.ts +254 -0
- package/dist/cjs/javaStreamables.js +391 -0
- package/dist/cjs/lease/LeaseMonitor.d.ts +44 -0
- package/dist/cjs/lease/LeaseMonitor.js +115 -0
- package/dist/cjs/lease/LeaseStore.d.ts +58 -0
- package/dist/cjs/lease/LeaseStore.js +151 -0
- package/dist/cjs/lease/WatermarkStore.d.ts +61 -0
- package/dist/cjs/lease/WatermarkStore.js +209 -0
- package/dist/cjs/lease/index.d.ts +14 -0
- package/dist/cjs/lease/index.js +22 -0
- package/dist/cjs/lease-client.d.ts +31 -0
- package/dist/cjs/lease-client.js +44 -0
- package/dist/cjs/legacy.d.ts +23 -0
- package/dist/cjs/legacy.js +163 -0
- package/dist/cjs/minima32.d.ts +18 -0
- package/dist/cjs/minima32.js +121 -0
- package/dist/cjs/minimaWireSerializer.d.ts +60 -0
- package/dist/cjs/minimaWireSerializer.js +77 -0
- package/dist/cjs/mmr.d.ts +157 -0
- package/dist/cjs/mmr.js +352 -0
- package/dist/cjs/mx.d.ts +1 -0
- package/dist/cjs/mx.js +10 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/params.d.ts +29 -0
- package/dist/cjs/params.js +20 -0
- package/dist/cjs/script.d.ts +7 -0
- package/dist/cjs/script.js +27 -0
- package/dist/cjs/scripts/contract-helpers.d.ts +252 -0
- package/dist/cjs/scripts/contract-helpers.js +407 -0
- package/dist/cjs/scripts/dapp-types.d.ts +119 -0
- package/dist/cjs/scripts/dapp-types.js +77 -0
- package/dist/cjs/scripts/index.d.ts +4 -0
- package/dist/cjs/scripts/index.js +38 -0
- package/dist/cjs/scripts/types.d.ts +81 -0
- package/dist/cjs/scripts/types.js +159 -0
- package/dist/cjs/scripts/witness-serializer.d.ts +29 -0
- package/dist/cjs/scripts/witness-serializer.js +306 -0
- package/dist/cjs/transaction.d.ts +106 -0
- package/dist/cjs/transaction.js +293 -0
- package/dist/cjs/treekey.d.ts +399 -0
- package/dist/cjs/treekey.js +827 -0
- package/dist/cjs/tx/TransactionLifecycle.d.ts +55 -0
- package/dist/cjs/tx/TransactionLifecycle.js +205 -0
- package/dist/cjs/tx/TransactionReceiptStore.d.ts +36 -0
- package/dist/cjs/tx/TransactionReceiptStore.js +93 -0
- package/dist/cjs/tx/TransactionService.d.ts +50 -0
- package/dist/cjs/tx/TransactionService.js +186 -0
- package/dist/cjs/tx/index.d.ts +13 -0
- package/dist/cjs/tx/index.js +20 -0
- package/dist/cjs/tx/types.d.ts +115 -0
- package/dist/cjs/tx/types.js +6 -0
- package/dist/cjs/util.d.ts +1 -0
- package/dist/cjs/util.js +5 -0
- package/dist/cjs/utils.d.ts +8 -0
- package/dist/cjs/utils.js +42 -0
- package/dist/cjs/verify.d.ts +18 -0
- package/dist/cjs/verify.js +174 -0
- package/dist/cjs/version.d.ts +12 -0
- package/dist/cjs/version.js +15 -0
- package/dist/cjs/wasm-sync.d.ts +71 -0
- package/dist/cjs/wasm-sync.js +97 -0
- package/dist/cjs/wots.d.ts +232 -0
- package/dist/cjs/wots.js +589 -0
- package/dist/index.d.ts +9 -3
- package/dist/index.js +25 -2
- package/dist/minimaWireSerializer.js +2 -2
- package/dist/mmr.js +1 -1
- package/dist/transaction.js +10 -10
- package/dist/treekey.js +14 -0
- package/dist/wasm-sync.d.ts +2 -2
- package/dist/wasm-sync.js +3 -1
- package/dist/wots.d.ts +1 -1
- package/package.json +84 -45
- package/dist/wasm-bridge.d.ts +0 -54
- package/dist/wasm-bridge.js +0 -303
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contract Helpers
|
|
3
|
+
*
|
|
4
|
+
* Provides high-level helpers for building specific contract types:
|
|
5
|
+
* - Timelock contracts
|
|
6
|
+
* - HTLC (Hashed Timelock Contracts)
|
|
7
|
+
* - MAST (Merkelized Abstract Syntax Trees)
|
|
8
|
+
* - Exchange contracts
|
|
9
|
+
* - Vault/covenant contracts
|
|
10
|
+
* - Flash/slow cash
|
|
11
|
+
* - Stateful game contracts
|
|
12
|
+
*
|
|
13
|
+
* Each helper validates inputs and builds the appropriate ScriptDescriptor
|
|
14
|
+
* for use with the EnhancedTransactionBuilder.
|
|
15
|
+
*/
|
|
16
|
+
import type { ScriptDescriptor, StateValue } from './types.js';
|
|
17
|
+
/**
|
|
18
|
+
* Timelock Helper
|
|
19
|
+
*
|
|
20
|
+
* Creates timelocked scripts that can only be spent after a certain block.
|
|
21
|
+
*/
|
|
22
|
+
export declare class TimelockHelper {
|
|
23
|
+
/**
|
|
24
|
+
* Create a timelock script that unlocks at a specific block.
|
|
25
|
+
*/
|
|
26
|
+
static createBlockTimelock(publicKey: string, unlockBlock: bigint): {
|
|
27
|
+
script: string;
|
|
28
|
+
address: string;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Create a timelock script based on coin age.
|
|
32
|
+
*/
|
|
33
|
+
static createCoinageTimelock(publicKey: string, minCoinAge: bigint): {
|
|
34
|
+
script: string;
|
|
35
|
+
address: string;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Check if a timelock is satisfied given current block.
|
|
39
|
+
*/
|
|
40
|
+
static isUnlocked(unlockBlock: bigint, currentBlock: bigint): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Build ScriptDescriptor for a timelock spend.
|
|
43
|
+
*/
|
|
44
|
+
static buildDescriptor(address: string, publicKey: string, unlockBlock: bigint): ScriptDescriptor;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* HTLC Helper
|
|
48
|
+
*
|
|
49
|
+
* Creates Hashed Timelock Contracts for atomic swaps and lightning-style payments.
|
|
50
|
+
*/
|
|
51
|
+
export declare class HTLCHelper {
|
|
52
|
+
/**
|
|
53
|
+
* Generate a random preimage and its hash.
|
|
54
|
+
*/
|
|
55
|
+
static generateSecret(): {
|
|
56
|
+
preimage: string;
|
|
57
|
+
hash: string;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Hash a preimage using SHA3 (default) or SHA2.
|
|
61
|
+
*/
|
|
62
|
+
static hashPreimage(preimage: string, algorithm?: 'sha3' | 'sha2'): string;
|
|
63
|
+
/**
|
|
64
|
+
* Verify a preimage matches a hash.
|
|
65
|
+
*/
|
|
66
|
+
static verifyPreimage(preimage: string, expectedHash: string, algorithm?: 'sha3' | 'sha2'): boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Create an HTLC script.
|
|
69
|
+
*
|
|
70
|
+
* The script allows:
|
|
71
|
+
* - Recipient to claim with preimage before timeout
|
|
72
|
+
* - Sender to refund after timeout
|
|
73
|
+
*/
|
|
74
|
+
static createHTLC(senderPublicKey: string, recipientPublicKey: string, hashLock: string, timeoutBlock: bigint, algorithm?: 'sha3' | 'sha2'): {
|
|
75
|
+
script: string;
|
|
76
|
+
address: string;
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* Build ScriptDescriptor to claim HTLC with preimage.
|
|
80
|
+
*/
|
|
81
|
+
static buildClaimDescriptor(address: string, senderPublicKey: string, recipientPublicKey: string, hashLock: string, timeoutBlock: bigint, preimage: string): ScriptDescriptor;
|
|
82
|
+
/**
|
|
83
|
+
* Build ScriptDescriptor to refund HTLC after timeout.
|
|
84
|
+
*/
|
|
85
|
+
static buildRefundDescriptor(address: string, senderPublicKey: string, recipientPublicKey: string, hashLock: string, timeoutBlock: bigint): ScriptDescriptor;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* MAST Helper
|
|
89
|
+
*
|
|
90
|
+
* Creates Merkelized Abstract Syntax Tree contracts for privacy and scalability.
|
|
91
|
+
*/
|
|
92
|
+
export declare class MASTHelper {
|
|
93
|
+
/**
|
|
94
|
+
* Compute hash of a script for MAST leaf.
|
|
95
|
+
*/
|
|
96
|
+
static hashScript(script: string): string;
|
|
97
|
+
/**
|
|
98
|
+
* Build a simple MAST tree from multiple scripts.
|
|
99
|
+
* Returns the root hash and proofs for each script.
|
|
100
|
+
*
|
|
101
|
+
* For a proper implementation, this should call the mmrcreate RPC.
|
|
102
|
+
* This is a simplified local version for 2 scripts.
|
|
103
|
+
*/
|
|
104
|
+
static buildSimpleTree(scripts: string[]): {
|
|
105
|
+
root: string;
|
|
106
|
+
proofs: Map<string, {
|
|
107
|
+
proof: string;
|
|
108
|
+
index: number;
|
|
109
|
+
}>;
|
|
110
|
+
};
|
|
111
|
+
/**
|
|
112
|
+
* Create a MAST script with the given root hash.
|
|
113
|
+
*/
|
|
114
|
+
static createMASTScript(rootHash: string): {
|
|
115
|
+
script: string;
|
|
116
|
+
address: string;
|
|
117
|
+
};
|
|
118
|
+
/**
|
|
119
|
+
* Build ScriptDescriptor for spending a MAST branch.
|
|
120
|
+
*/
|
|
121
|
+
static buildDescriptor(address: string, rootHash: string, branchScript: string, branchProof: string, wotsPublicKey?: string): ScriptDescriptor;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Exchange Contract Helper
|
|
125
|
+
*
|
|
126
|
+
* Creates DEX-style exchange contracts using VERIFYOUT.
|
|
127
|
+
*/
|
|
128
|
+
export declare class ExchangeHelper {
|
|
129
|
+
/**
|
|
130
|
+
* Create an exchange offer script.
|
|
131
|
+
*
|
|
132
|
+
* Owner can cancel, or anyone can take the offer by providing
|
|
133
|
+
* the specified output.
|
|
134
|
+
*/
|
|
135
|
+
static createOffer(ownerPublicKey: string, desiredAddress: string, desiredAmount: string, desiredTokenId: string): {
|
|
136
|
+
script: string;
|
|
137
|
+
address: string;
|
|
138
|
+
};
|
|
139
|
+
/**
|
|
140
|
+
* Build state variables for an exchange offer.
|
|
141
|
+
*/
|
|
142
|
+
static buildOfferState(ownerPublicKey: string, desiredAddress: string, desiredAmount: string, desiredTokenId: string): StateValue[];
|
|
143
|
+
/**
|
|
144
|
+
* Build ScriptDescriptor for taking an exchange offer.
|
|
145
|
+
*/
|
|
146
|
+
static buildTakeOfferDescriptor(address: string, ownerPublicKey: string, desiredAddress: string, desiredAmount: string, desiredTokenId: string): ScriptDescriptor;
|
|
147
|
+
/**
|
|
148
|
+
* Validate VERIFYOUT for an exchange transaction.
|
|
149
|
+
*/
|
|
150
|
+
static validateExchange(outputs: Array<{
|
|
151
|
+
address: string;
|
|
152
|
+
amount: string;
|
|
153
|
+
tokenId: string;
|
|
154
|
+
}>, expectedAddress: string, expectedAmount: string, expectedTokenId: string, inputIndex: number): {
|
|
155
|
+
valid: boolean;
|
|
156
|
+
error?: string;
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Vault Helper
|
|
161
|
+
*
|
|
162
|
+
* Creates vault/covenant contracts with safe house enforcement.
|
|
163
|
+
*/
|
|
164
|
+
export declare class VaultHelper {
|
|
165
|
+
/**
|
|
166
|
+
* Generate safe house script from vault parameters.
|
|
167
|
+
*/
|
|
168
|
+
static generateSafeHouseScript(coldKey: string, hotKey: string, cooldownBlocks?: bigint): string;
|
|
169
|
+
/**
|
|
170
|
+
* Create a vault script.
|
|
171
|
+
*/
|
|
172
|
+
static createVault(coldKey: string, hotKey: string, cooldownBlocks?: bigint): {
|
|
173
|
+
vaultScript: string;
|
|
174
|
+
vaultAddress: string;
|
|
175
|
+
safeHouseScript: string;
|
|
176
|
+
safeHouseAddress: string;
|
|
177
|
+
};
|
|
178
|
+
/**
|
|
179
|
+
* Build state for vault withdrawal.
|
|
180
|
+
*/
|
|
181
|
+
static buildWithdrawalState(amount: string, recipientAddress: string): StateValue[];
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Flash Cash Helper
|
|
185
|
+
*
|
|
186
|
+
* Creates flash loan contracts for single-transaction borrowing.
|
|
187
|
+
*/
|
|
188
|
+
export declare class FlashCashHelper {
|
|
189
|
+
/**
|
|
190
|
+
* Create a flash cash contract.
|
|
191
|
+
*/
|
|
192
|
+
static createFlashCash(ownerPublicKey: string, interestMultiplier?: string): {
|
|
193
|
+
script: string;
|
|
194
|
+
address: string;
|
|
195
|
+
};
|
|
196
|
+
/**
|
|
197
|
+
* Calculate return amount with interest.
|
|
198
|
+
*/
|
|
199
|
+
static calculateReturn(borrowAmount: bigint, interestMultiplier: number): bigint;
|
|
200
|
+
/**
|
|
201
|
+
* Build ScriptDescriptor for borrowing flash cash.
|
|
202
|
+
*/
|
|
203
|
+
static buildBorrowDescriptor(address: string, ownerPublicKey: string, interestMultiplier?: string): ScriptDescriptor;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Slow Cash Helper
|
|
207
|
+
*
|
|
208
|
+
* Creates rate-limited withdrawal contracts.
|
|
209
|
+
*/
|
|
210
|
+
export declare class SlowCashHelper {
|
|
211
|
+
/**
|
|
212
|
+
* Create a slow cash contract.
|
|
213
|
+
*/
|
|
214
|
+
static createSlowCash(ownerPublicKey: string, withdrawalPercent?: string, cooldownBlocks?: bigint): {
|
|
215
|
+
script: string;
|
|
216
|
+
address: string;
|
|
217
|
+
};
|
|
218
|
+
/**
|
|
219
|
+
* Calculate withdrawal amount.
|
|
220
|
+
*/
|
|
221
|
+
static calculateWithdrawal(currentAmount: bigint, withdrawalPercent: number): {
|
|
222
|
+
withdrawal: bigint;
|
|
223
|
+
remaining: bigint;
|
|
224
|
+
};
|
|
225
|
+
/**
|
|
226
|
+
* Check if withdrawal is allowed based on coin age.
|
|
227
|
+
*/
|
|
228
|
+
static canWithdraw(coinAge: bigint, cooldownBlocks: bigint): boolean;
|
|
229
|
+
/**
|
|
230
|
+
* Build ScriptDescriptor for slow cash withdrawal.
|
|
231
|
+
*/
|
|
232
|
+
static buildWithdrawalDescriptor(address: string, ownerPublicKey: string, withdrawalPercent?: string, cooldownBlocks?: bigint): ScriptDescriptor;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Stateful Game Helper
|
|
236
|
+
*
|
|
237
|
+
* Creates multi-round stateful contracts (like coin flip).
|
|
238
|
+
*/
|
|
239
|
+
export declare class StatefulGameHelper {
|
|
240
|
+
/**
|
|
241
|
+
* Create a round increment assertion.
|
|
242
|
+
*/
|
|
243
|
+
static createRoundCheck(): string;
|
|
244
|
+
/**
|
|
245
|
+
* Build state for next round.
|
|
246
|
+
*/
|
|
247
|
+
static buildNextRoundState(currentRound: number, preservedPorts: number[], newStates: StateValue[]): StateValue[];
|
|
248
|
+
/**
|
|
249
|
+
* Validate round progression.
|
|
250
|
+
*/
|
|
251
|
+
static validateRound(previousRound: number, currentRound: number): boolean;
|
|
252
|
+
}
|
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Contract Helpers
|
|
4
|
+
*
|
|
5
|
+
* Provides high-level helpers for building specific contract types:
|
|
6
|
+
* - Timelock contracts
|
|
7
|
+
* - HTLC (Hashed Timelock Contracts)
|
|
8
|
+
* - MAST (Merkelized Abstract Syntax Trees)
|
|
9
|
+
* - Exchange contracts
|
|
10
|
+
* - Vault/covenant contracts
|
|
11
|
+
* - Flash/slow cash
|
|
12
|
+
* - Stateful game contracts
|
|
13
|
+
*
|
|
14
|
+
* Each helper validates inputs and builds the appropriate ScriptDescriptor
|
|
15
|
+
* for use with the EnhancedTransactionBuilder.
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.StatefulGameHelper = exports.SlowCashHelper = exports.FlashCashHelper = exports.VaultHelper = exports.ExchangeHelper = exports.MASTHelper = exports.HTLCHelper = exports.TimelockHelper = void 0;
|
|
19
|
+
const wasm_sync_js_1 = require("../wasm-sync.js");
|
|
20
|
+
const node_crypto_1 = require("node:crypto");
|
|
21
|
+
function sha256(data) {
|
|
22
|
+
return new Uint8Array((0, node_crypto_1.createHash)('sha256').update(data).digest());
|
|
23
|
+
}
|
|
24
|
+
const types_js_1 = require("./types.js");
|
|
25
|
+
function kissHex(hex) {
|
|
26
|
+
const raw = hex.startsWith('0x') || hex.startsWith('0X') ? hex.slice(2) : hex;
|
|
27
|
+
return '0x' + raw.toUpperCase();
|
|
28
|
+
}
|
|
29
|
+
function hexToBytes(hex) {
|
|
30
|
+
const cleanHex = hex.startsWith('0x') ? hex.slice(2) : hex;
|
|
31
|
+
const bytes = new Uint8Array(cleanHex.length / 2);
|
|
32
|
+
for (let i = 0; i < cleanHex.length; i += 2) {
|
|
33
|
+
bytes[i / 2] = parseInt(cleanHex.slice(i, i + 2), 16);
|
|
34
|
+
}
|
|
35
|
+
return bytes;
|
|
36
|
+
}
|
|
37
|
+
function bytesToHex(bytes) {
|
|
38
|
+
return '0x' + Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join('');
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Timelock Helper
|
|
42
|
+
*
|
|
43
|
+
* Creates timelocked scripts that can only be spent after a certain block.
|
|
44
|
+
*/
|
|
45
|
+
class TimelockHelper {
|
|
46
|
+
/**
|
|
47
|
+
* Create a timelock script that unlocks at a specific block.
|
|
48
|
+
*/
|
|
49
|
+
static createBlockTimelock(publicKey, unlockBlock) {
|
|
50
|
+
const script = `RETURN SIGNEDBY(${kissHex(publicKey)}) AND @BLOCK GT ${unlockBlock}`;
|
|
51
|
+
const address = computeScriptAddress(script);
|
|
52
|
+
return { script, address };
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Create a timelock script based on coin age.
|
|
56
|
+
*/
|
|
57
|
+
static createCoinageTimelock(publicKey, minCoinAge) {
|
|
58
|
+
const script = `RETURN SIGNEDBY(${kissHex(publicKey)}) AND @COINAGE GT ${minCoinAge}`;
|
|
59
|
+
const address = computeScriptAddress(script);
|
|
60
|
+
return { script, address };
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Check if a timelock is satisfied given current block.
|
|
64
|
+
*/
|
|
65
|
+
static isUnlocked(unlockBlock, currentBlock) {
|
|
66
|
+
return currentBlock > unlockBlock;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Build ScriptDescriptor for a timelock spend.
|
|
70
|
+
*/
|
|
71
|
+
static buildDescriptor(address, publicKey, unlockBlock) {
|
|
72
|
+
return (0, types_js_1.createTimelockDescriptor)(address, publicKey, unlockBlock);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
exports.TimelockHelper = TimelockHelper;
|
|
76
|
+
/**
|
|
77
|
+
* HTLC Helper
|
|
78
|
+
*
|
|
79
|
+
* Creates Hashed Timelock Contracts for atomic swaps and lightning-style payments.
|
|
80
|
+
*/
|
|
81
|
+
class HTLCHelper {
|
|
82
|
+
/**
|
|
83
|
+
* Generate a random preimage and its hash.
|
|
84
|
+
*/
|
|
85
|
+
static generateSecret() {
|
|
86
|
+
const preimageBytes = (0, node_crypto_1.randomBytes)(32);
|
|
87
|
+
const preimage = bytesToHex(preimageBytes);
|
|
88
|
+
const hashBytes = (0, wasm_sync_js_1.sha3_256)(preimageBytes);
|
|
89
|
+
const hash = bytesToHex(hashBytes);
|
|
90
|
+
return { preimage, hash };
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Hash a preimage using SHA3 (default) or SHA2.
|
|
94
|
+
*/
|
|
95
|
+
static hashPreimage(preimage, algorithm = 'sha3') {
|
|
96
|
+
const preimageBytes = hexToBytes(preimage);
|
|
97
|
+
if (algorithm === 'sha2') {
|
|
98
|
+
const hashBytes = sha256(preimageBytes);
|
|
99
|
+
return bytesToHex(hashBytes);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
const hashBytes = (0, wasm_sync_js_1.sha3_256)(preimageBytes);
|
|
103
|
+
return bytesToHex(hashBytes);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Verify a preimage matches a hash.
|
|
108
|
+
*/
|
|
109
|
+
static verifyPreimage(preimage, expectedHash, algorithm = 'sha3') {
|
|
110
|
+
const computedHash = this.hashPreimage(preimage, algorithm);
|
|
111
|
+
return computedHash.toLowerCase() === expectedHash.toLowerCase();
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Create an HTLC script.
|
|
115
|
+
*
|
|
116
|
+
* The script allows:
|
|
117
|
+
* - Recipient to claim with preimage before timeout
|
|
118
|
+
* - Sender to refund after timeout
|
|
119
|
+
*/
|
|
120
|
+
static createHTLC(senderPublicKey, recipientPublicKey, hashLock, timeoutBlock, algorithm = 'sha3') {
|
|
121
|
+
const hashFunc = algorithm === 'sha2' ? 'SHA2' : 'SHA3';
|
|
122
|
+
const script = `IF @BLOCK GT ${timeoutBlock} AND SIGNEDBY(${kissHex(senderPublicKey)}) THEN RETURN TRUE ENDIF RETURN (SIGNEDBY(${kissHex(recipientPublicKey)}) AND ${hashFunc}(STATE(1)) EQ ${kissHex(hashLock)})`;
|
|
123
|
+
const address = computeScriptAddress(script);
|
|
124
|
+
return { script, address };
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Build ScriptDescriptor to claim HTLC with preimage.
|
|
128
|
+
*/
|
|
129
|
+
static buildClaimDescriptor(address, senderPublicKey, recipientPublicKey, hashLock, timeoutBlock, preimage) {
|
|
130
|
+
return (0, types_js_1.createHTLCDescriptor)(address, senderPublicKey, recipientPublicKey, hashLock, timeoutBlock, false, preimage);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Build ScriptDescriptor to refund HTLC after timeout.
|
|
134
|
+
*/
|
|
135
|
+
static buildRefundDescriptor(address, senderPublicKey, recipientPublicKey, hashLock, timeoutBlock) {
|
|
136
|
+
return (0, types_js_1.createHTLCDescriptor)(address, senderPublicKey, recipientPublicKey, hashLock, timeoutBlock, true);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
exports.HTLCHelper = HTLCHelper;
|
|
140
|
+
/**
|
|
141
|
+
* MAST Helper
|
|
142
|
+
*
|
|
143
|
+
* Creates Merkelized Abstract Syntax Tree contracts for privacy and scalability.
|
|
144
|
+
*/
|
|
145
|
+
class MASTHelper {
|
|
146
|
+
/**
|
|
147
|
+
* Compute hash of a script for MAST leaf.
|
|
148
|
+
*/
|
|
149
|
+
static hashScript(script) {
|
|
150
|
+
const scriptBytes = new TextEncoder().encode(script.trim().toUpperCase());
|
|
151
|
+
const hashBytes = (0, wasm_sync_js_1.sha3_256)(scriptBytes);
|
|
152
|
+
return bytesToHex(hashBytes);
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Build a simple MAST tree from multiple scripts.
|
|
156
|
+
* Returns the root hash and proofs for each script.
|
|
157
|
+
*
|
|
158
|
+
* For a proper implementation, this should call the mmrcreate RPC.
|
|
159
|
+
* This is a simplified local version for 2 scripts.
|
|
160
|
+
*/
|
|
161
|
+
static buildSimpleTree(scripts) {
|
|
162
|
+
if (scripts.length === 0) {
|
|
163
|
+
throw new Error('MAST requires at least one script');
|
|
164
|
+
}
|
|
165
|
+
if (scripts.length === 1) {
|
|
166
|
+
const hash = this.hashScript(scripts[0]);
|
|
167
|
+
return {
|
|
168
|
+
root: hash,
|
|
169
|
+
proofs: new Map([[scripts[0], { proof: '', index: 0 }]])
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
const hashes = scripts.map(s => this.hashScript(s));
|
|
173
|
+
const proofs = new Map();
|
|
174
|
+
for (let i = 0; i < scripts.length; i++) {
|
|
175
|
+
const siblingIndex = i % 2 === 0 ? i + 1 : i - 1;
|
|
176
|
+
const siblingHash = hashes[siblingIndex] || hashes[i];
|
|
177
|
+
const isLeft = i % 2 === 1;
|
|
178
|
+
const proofHex = encodeSimpleProof(siblingHash, isLeft);
|
|
179
|
+
proofs.set(scripts[i], { proof: proofHex, index: i });
|
|
180
|
+
}
|
|
181
|
+
const combinedBytes = hexToBytes(hashes[0].slice(2) + hashes[1].slice(2));
|
|
182
|
+
const rootBytes = (0, wasm_sync_js_1.sha3_256)(combinedBytes);
|
|
183
|
+
const root = bytesToHex(rootBytes);
|
|
184
|
+
return { root, proofs };
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Create a MAST script with the given root hash.
|
|
188
|
+
*/
|
|
189
|
+
static createMASTScript(rootHash) {
|
|
190
|
+
const script = `MAST ${kissHex(rootHash)}`;
|
|
191
|
+
const address = computeScriptAddress(script);
|
|
192
|
+
return { script, address };
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Build ScriptDescriptor for spending a MAST branch.
|
|
196
|
+
*/
|
|
197
|
+
static buildDescriptor(address, rootHash, branchScript, branchProof, wotsPublicKey) {
|
|
198
|
+
return (0, types_js_1.createMASTDescriptor)(address, rootHash, branchScript, branchProof, wotsPublicKey);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
exports.MASTHelper = MASTHelper;
|
|
202
|
+
/**
|
|
203
|
+
* Exchange Contract Helper
|
|
204
|
+
*
|
|
205
|
+
* Creates DEX-style exchange contracts using VERIFYOUT.
|
|
206
|
+
*/
|
|
207
|
+
class ExchangeHelper {
|
|
208
|
+
/**
|
|
209
|
+
* Create an exchange offer script.
|
|
210
|
+
*
|
|
211
|
+
* Owner can cancel, or anyone can take the offer by providing
|
|
212
|
+
* the specified output.
|
|
213
|
+
*/
|
|
214
|
+
static createOffer(ownerPublicKey, desiredAddress, desiredAmount, desiredTokenId) {
|
|
215
|
+
const script = `IF SIGNEDBY(PREVSTATE(0)) THEN RETURN TRUE ENDIF ASSERT VERIFYOUT(@INPUT PREVSTATE(1) PREVSTATE(2) PREVSTATE(3) TRUE) RETURN TRUE`;
|
|
216
|
+
const address = computeScriptAddress(script);
|
|
217
|
+
return { script, address };
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Build state variables for an exchange offer.
|
|
221
|
+
*/
|
|
222
|
+
static buildOfferState(ownerPublicKey, desiredAddress, desiredAmount, desiredTokenId) {
|
|
223
|
+
return [
|
|
224
|
+
{ port: 0, value: ownerPublicKey, type: 'hex' },
|
|
225
|
+
{ port: 1, value: desiredAddress, type: 'hex' },
|
|
226
|
+
{ port: 2, value: desiredAmount, type: 'number' },
|
|
227
|
+
{ port: 3, value: desiredTokenId, type: 'hex' }
|
|
228
|
+
];
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Build ScriptDescriptor for taking an exchange offer.
|
|
232
|
+
*/
|
|
233
|
+
static buildTakeOfferDescriptor(address, ownerPublicKey, desiredAddress, desiredAmount, desiredTokenId) {
|
|
234
|
+
return (0, types_js_1.createExchangeDescriptor)(address, ownerPublicKey, desiredAddress, desiredAmount, desiredTokenId);
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Validate VERIFYOUT for an exchange transaction.
|
|
238
|
+
*/
|
|
239
|
+
static validateExchange(outputs, expectedAddress, expectedAmount, expectedTokenId, inputIndex) {
|
|
240
|
+
if (inputIndex >= outputs.length) {
|
|
241
|
+
return { valid: false, error: `Output at index ${inputIndex} does not exist` };
|
|
242
|
+
}
|
|
243
|
+
const output = outputs[inputIndex];
|
|
244
|
+
if (output.address.toLowerCase() !== expectedAddress.toLowerCase()) {
|
|
245
|
+
return { valid: false, error: 'Address mismatch' };
|
|
246
|
+
}
|
|
247
|
+
if (output.amount !== expectedAmount) {
|
|
248
|
+
return { valid: false, error: 'Amount mismatch' };
|
|
249
|
+
}
|
|
250
|
+
if (output.tokenId.toLowerCase() !== expectedTokenId.toLowerCase()) {
|
|
251
|
+
return { valid: false, error: 'TokenId mismatch' };
|
|
252
|
+
}
|
|
253
|
+
return { valid: true };
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
exports.ExchangeHelper = ExchangeHelper;
|
|
257
|
+
/**
|
|
258
|
+
* Vault Helper
|
|
259
|
+
*
|
|
260
|
+
* Creates vault/covenant contracts with safe house enforcement.
|
|
261
|
+
*/
|
|
262
|
+
class VaultHelper {
|
|
263
|
+
/**
|
|
264
|
+
* Generate safe house script from vault parameters.
|
|
265
|
+
*/
|
|
266
|
+
static generateSafeHouseScript(coldKey, hotKey, cooldownBlocks = 20n) {
|
|
267
|
+
return `LET pkcold = ${kissHex(coldKey)} LET pkhot = ${kissHex(hotKey)} IF SIGNEDBY(pkcold) THEN RETURN TRUE ENDIF IF SIGNEDBY(pkhot) THEN IF @COINAGE GT ${cooldownBlocks} THEN RETURN VERIFYOUT(@INPUT PREVSTATE(21) @AMOUNT @TOKENID TRUE) ENDIF ENDIF`;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Create a vault script.
|
|
271
|
+
*/
|
|
272
|
+
static createVault(coldKey, hotKey, cooldownBlocks = 20n) {
|
|
273
|
+
const safeHouseScript = this.generateSafeHouseScript(coldKey, hotKey, cooldownBlocks);
|
|
274
|
+
const safeHouseAddress = computeScriptAddress(safeHouseScript);
|
|
275
|
+
const vaultScript = `LET pkcold = ${kissHex(coldKey)} LET pkhot = ${kissHex(hotKey)} IF SIGNEDBY(pkcold) THEN RETURN TRUE ENDIF LET amt = STATE(20) LET recip = STATE(21) LET safehouse = [${safeHouseScript}] ASSERT VERIFYOUT(@INPUT ADDRESS(safehouse) amt @TOKENID TRUE) LET chg = @AMOUNT - amt IF chg GT 0 THEN ASSERT VERIFYOUT(INC(@INPUT) @ADDRESS (@AMOUNT - amt) @TOKENID TRUE) ENDIF RETURN SIGNEDBY(pkhot)`;
|
|
276
|
+
const vaultAddress = computeScriptAddress(vaultScript);
|
|
277
|
+
return {
|
|
278
|
+
vaultScript,
|
|
279
|
+
vaultAddress,
|
|
280
|
+
safeHouseScript,
|
|
281
|
+
safeHouseAddress
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Build state for vault withdrawal.
|
|
286
|
+
*/
|
|
287
|
+
static buildWithdrawalState(amount, recipientAddress) {
|
|
288
|
+
return [
|
|
289
|
+
{ port: 20, value: amount, type: 'number' },
|
|
290
|
+
{ port: 21, value: recipientAddress, type: 'hex' }
|
|
291
|
+
];
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
exports.VaultHelper = VaultHelper;
|
|
295
|
+
/**
|
|
296
|
+
* Flash Cash Helper
|
|
297
|
+
*
|
|
298
|
+
* Creates flash loan contracts for single-transaction borrowing.
|
|
299
|
+
*/
|
|
300
|
+
class FlashCashHelper {
|
|
301
|
+
/**
|
|
302
|
+
* Create a flash cash contract.
|
|
303
|
+
*/
|
|
304
|
+
static createFlashCash(ownerPublicKey, interestMultiplier = '1.01') {
|
|
305
|
+
const script = `IF SIGNEDBY(PREVSTATE(1)) THEN RETURN TRUE ENDIF ASSERT SAMESTATE(1 1) RETURN VERIFYOUT(@INPUT @ADDRESS @AMOUNT*${interestMultiplier} @TOKENID TRUE)`;
|
|
306
|
+
const address = computeScriptAddress(script);
|
|
307
|
+
return { script, address };
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Calculate return amount with interest.
|
|
311
|
+
*/
|
|
312
|
+
static calculateReturn(borrowAmount, interestMultiplier) {
|
|
313
|
+
const multiplied = Number(borrowAmount) * interestMultiplier;
|
|
314
|
+
return BigInt(Math.ceil(multiplied));
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Build ScriptDescriptor for borrowing flash cash.
|
|
318
|
+
*/
|
|
319
|
+
static buildBorrowDescriptor(address, ownerPublicKey, interestMultiplier = '1.01') {
|
|
320
|
+
return (0, types_js_1.createFlashCashDescriptor)(address, ownerPublicKey, interestMultiplier);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
exports.FlashCashHelper = FlashCashHelper;
|
|
324
|
+
/**
|
|
325
|
+
* Slow Cash Helper
|
|
326
|
+
*
|
|
327
|
+
* Creates rate-limited withdrawal contracts.
|
|
328
|
+
*/
|
|
329
|
+
class SlowCashHelper {
|
|
330
|
+
/**
|
|
331
|
+
* Create a slow cash contract.
|
|
332
|
+
*/
|
|
333
|
+
static createSlowCash(ownerPublicKey, withdrawalPercent = '0.9', cooldownBlocks = 10000n) {
|
|
334
|
+
const script = `IF @COINAGE LT ${cooldownBlocks} THEN RETURN FALSE ENDIF ASSERT SIGNEDBY(${kissHex(ownerPublicKey)}) AND VERIFYOUT(@INPUT @ADDRESS @AMOUNT*${withdrawalPercent} @TOKENID TRUE)`;
|
|
335
|
+
const address = computeScriptAddress(script);
|
|
336
|
+
return { script, address };
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Calculate withdrawal amount.
|
|
340
|
+
*/
|
|
341
|
+
static calculateWithdrawal(currentAmount, withdrawalPercent) {
|
|
342
|
+
const remaining = BigInt(Math.floor(Number(currentAmount) * withdrawalPercent));
|
|
343
|
+
const withdrawal = currentAmount - remaining;
|
|
344
|
+
return { withdrawal, remaining };
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Check if withdrawal is allowed based on coin age.
|
|
348
|
+
*/
|
|
349
|
+
static canWithdraw(coinAge, cooldownBlocks) {
|
|
350
|
+
return coinAge >= cooldownBlocks;
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Build ScriptDescriptor for slow cash withdrawal.
|
|
354
|
+
*/
|
|
355
|
+
static buildWithdrawalDescriptor(address, ownerPublicKey, withdrawalPercent = '0.9', cooldownBlocks = 10000n) {
|
|
356
|
+
return (0, types_js_1.createSlowCashDescriptor)(address, ownerPublicKey, withdrawalPercent, cooldownBlocks);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
exports.SlowCashHelper = SlowCashHelper;
|
|
360
|
+
/**
|
|
361
|
+
* Stateful Game Helper
|
|
362
|
+
*
|
|
363
|
+
* Creates multi-round stateful contracts (like coin flip).
|
|
364
|
+
*/
|
|
365
|
+
class StatefulGameHelper {
|
|
366
|
+
/**
|
|
367
|
+
* Create a round increment assertion.
|
|
368
|
+
*/
|
|
369
|
+
static createRoundCheck() {
|
|
370
|
+
return `LET round = STATE(0) LET prevround = PREVSTATE(0) ASSERT round EQ INC(prevround)`;
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Build state for next round.
|
|
374
|
+
*/
|
|
375
|
+
static buildNextRoundState(currentRound, preservedPorts, newStates) {
|
|
376
|
+
const states = [
|
|
377
|
+
{ port: 0, value: BigInt(currentRound + 1), type: 'number' }
|
|
378
|
+
];
|
|
379
|
+
for (const sv of newStates) {
|
|
380
|
+
states.push(sv);
|
|
381
|
+
}
|
|
382
|
+
return states;
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* Validate round progression.
|
|
386
|
+
*/
|
|
387
|
+
static validateRound(previousRound, currentRound) {
|
|
388
|
+
return currentRound === previousRound + 1;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
exports.StatefulGameHelper = StatefulGameHelper;
|
|
392
|
+
function computeScriptAddress(script) {
|
|
393
|
+
const cleanScript = script.trim().toUpperCase();
|
|
394
|
+
const scriptBytes = new TextEncoder().encode(cleanScript);
|
|
395
|
+
const hashBytes = (0, wasm_sync_js_1.sha3_256)(scriptBytes);
|
|
396
|
+
return bytesToHex(hashBytes);
|
|
397
|
+
}
|
|
398
|
+
function encodeSimpleProof(siblingHash, isLeft) {
|
|
399
|
+
const parts = [];
|
|
400
|
+
parts.push(0, 0, 0, 1, 0, 1);
|
|
401
|
+
parts.push(isLeft ? 1 : 0);
|
|
402
|
+
const hashBytes = hexToBytes(siblingHash);
|
|
403
|
+
parts.push(0, 0, 0, hashBytes.length);
|
|
404
|
+
parts.push(...Array.from(hashBytes));
|
|
405
|
+
parts.push(0, 0, 0, 0, 1, 0);
|
|
406
|
+
return bytesToHex(new Uint8Array(parts));
|
|
407
|
+
}
|