ecash-lib 2.1.0 → 3.0.0
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/README.md +4 -3
- package/dist/consts.d.ts +2 -2
- package/dist/consts.d.ts.map +1 -1
- package/dist/consts.js +3 -3
- package/dist/consts.js.map +1 -1
- package/dist/ffi/ecash_lib_wasm_bg_browser.js +6 -6
- package/dist/ffi/ecash_lib_wasm_bg_browser.wasm +0 -0
- package/dist/ffi/ecash_lib_wasm_bg_nodejs.wasm +0 -0
- package/dist/test/testRunner.d.ts +2 -2
- package/dist/test/testRunner.d.ts.map +1 -1
- package/dist/test/testRunner.js +13 -10
- package/dist/test/testRunner.js.map +1 -1
- package/dist/token/alp.d.ts +6 -6
- package/dist/token/alp.d.ts.map +1 -1
- package/dist/token/alp.js +13 -13
- package/dist/token/alp.js.map +1 -1
- package/dist/token/common.d.ts +0 -1
- package/dist/token/common.d.ts.map +1 -1
- package/dist/token/common.js.map +1 -1
- package/dist/token/slp.d.ts +7 -7
- package/dist/token/slp.d.ts.map +1 -1
- package/dist/token/slp.js +25 -25
- package/dist/token/slp.js.map +1 -1
- package/dist/tx.d.ts +2 -2
- package/dist/tx.d.ts.map +1 -1
- package/dist/tx.js +5 -5
- package/dist/tx.js.map +1 -1
- package/dist/txBuilder.d.ts +3 -3
- package/dist/txBuilder.d.ts.map +1 -1
- package/dist/txBuilder.js +12 -12
- package/dist/txBuilder.js.map +1 -1
- package/dist/unsignedTx.js +2 -2
- package/dist/unsignedTx.js.map +1 -1
- package/package.json +2 -2
- package/src/consts.ts +2 -2
- package/src/ffi/ecash_lib_wasm_bg_browser.js +6 -6
- package/src/ffi/ecash_lib_wasm_bg_browser.wasm +0 -0
- package/src/ffi/ecash_lib_wasm_bg_nodejs.wasm +0 -0
- package/src/test/testRunner.ts +15 -13
- package/src/token/alp.ts +17 -17
- package/src/token/common.ts +0 -2
- package/src/token/slp.ts +27 -27
- package/src/tx.ts +7 -7
- package/src/txBuilder.ts +15 -15
- package/src/unsignedTx.ts +2 -2
package/src/token/slp.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { strToBytes } from '../io/str.js';
|
|
|
7
7
|
import { Op, pushBytesOp } from '../op.js';
|
|
8
8
|
import { OP_PUSHDATA1, OP_RETURN } from '../opcode.js';
|
|
9
9
|
import { Script } from '../script.js';
|
|
10
|
-
import {
|
|
10
|
+
import { BURN, GENESIS, GenesisInfo, MINT, SEND } from './common.js';
|
|
11
11
|
|
|
12
12
|
/** LOKAD ID for SLP */
|
|
13
13
|
export const SLP_LOKAD_ID = strToBytes('SLP\0');
|
|
@@ -25,7 +25,7 @@ export const SLP_NFT1_GROUP = 0x81;
|
|
|
25
25
|
export function slpGenesis(
|
|
26
26
|
tokenType: number,
|
|
27
27
|
genesisInfo: GenesisInfo,
|
|
28
|
-
initialQuantity:
|
|
28
|
+
initialQuantity: bigint,
|
|
29
29
|
mintBatonOutIdx?: number,
|
|
30
30
|
): Script {
|
|
31
31
|
verifyTokenType(tokenType);
|
|
@@ -53,7 +53,7 @@ export function slpGenesis(
|
|
|
53
53
|
data.push(new Uint8Array());
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
|
-
data.push(
|
|
56
|
+
data.push(slpAtoms(initialQuantity));
|
|
57
57
|
return Script.fromOps([OP_RETURN as Op].concat(data.map(pushdataOpSlp)));
|
|
58
58
|
}
|
|
59
59
|
|
|
@@ -64,7 +64,7 @@ export function slpGenesis(
|
|
|
64
64
|
export function slpMint(
|
|
65
65
|
tokenId: string,
|
|
66
66
|
tokenType: number,
|
|
67
|
-
|
|
67
|
+
additionalAtoms: bigint,
|
|
68
68
|
mintBatonOutIdx?: number,
|
|
69
69
|
): Script {
|
|
70
70
|
verifyTokenType(tokenType);
|
|
@@ -80,7 +80,7 @@ export function slpMint(
|
|
|
80
80
|
mintBatonOutIdx !== undefined ? [mintBatonOutIdx] : [],
|
|
81
81
|
),
|
|
82
82
|
),
|
|
83
|
-
pushdataOpSlp(
|
|
83
|
+
pushdataOpSlp(slpAtoms(additionalAtoms)),
|
|
84
84
|
]);
|
|
85
85
|
}
|
|
86
86
|
|
|
@@ -90,10 +90,10 @@ export function slpMint(
|
|
|
90
90
|
**/
|
|
91
91
|
export function slpMintVault(
|
|
92
92
|
tokenId: string,
|
|
93
|
-
|
|
93
|
+
additionalAtomsArray: bigint[],
|
|
94
94
|
): Script {
|
|
95
95
|
verifyTokenId(tokenId);
|
|
96
|
-
|
|
96
|
+
verifySendAtomsArray(additionalAtomsArray);
|
|
97
97
|
return Script.fromOps(
|
|
98
98
|
[
|
|
99
99
|
OP_RETURN,
|
|
@@ -102,7 +102,7 @@ export function slpMintVault(
|
|
|
102
102
|
pushdataOpSlp(MINT),
|
|
103
103
|
pushdataOpSlp(fromHex(tokenId)),
|
|
104
104
|
].concat(
|
|
105
|
-
|
|
105
|
+
additionalAtomsArray.map(atoms => pushdataOpSlp(slpAtoms(atoms))),
|
|
106
106
|
),
|
|
107
107
|
);
|
|
108
108
|
}
|
|
@@ -113,11 +113,11 @@ export function slpMintVault(
|
|
|
113
113
|
export function slpSend(
|
|
114
114
|
tokenId: string,
|
|
115
115
|
tokenType: number,
|
|
116
|
-
|
|
116
|
+
sendAtomsArray: bigint[],
|
|
117
117
|
): Script {
|
|
118
118
|
verifyTokenType(tokenType);
|
|
119
119
|
verifyTokenId(tokenId);
|
|
120
|
-
|
|
120
|
+
verifySendAtomsArray(sendAtomsArray);
|
|
121
121
|
return Script.fromOps(
|
|
122
122
|
[
|
|
123
123
|
OP_RETURN,
|
|
@@ -125,7 +125,7 @@ export function slpSend(
|
|
|
125
125
|
pushdataOpSlp(new Uint8Array([tokenType])),
|
|
126
126
|
pushdataOpSlp(SEND),
|
|
127
127
|
pushdataOpSlp(fromHex(tokenId)),
|
|
128
|
-
].concat(
|
|
128
|
+
].concat(sendAtomsArray.map(atoms => pushdataOpSlp(slpAtoms(atoms)))),
|
|
129
129
|
);
|
|
130
130
|
}
|
|
131
131
|
|
|
@@ -136,7 +136,7 @@ export function slpSend(
|
|
|
136
136
|
export function slpBurn(
|
|
137
137
|
tokenId: string,
|
|
138
138
|
tokenType: number,
|
|
139
|
-
|
|
139
|
+
burnAtoms: bigint,
|
|
140
140
|
): Script {
|
|
141
141
|
verifyTokenType(tokenType);
|
|
142
142
|
verifyTokenId(tokenId);
|
|
@@ -146,7 +146,7 @@ export function slpBurn(
|
|
|
146
146
|
pushdataOpSlp(new Uint8Array([tokenType])),
|
|
147
147
|
pushdataOpSlp(BURN),
|
|
148
148
|
pushdataOpSlp(fromHex(tokenId)),
|
|
149
|
-
pushdataOpSlp(
|
|
149
|
+
pushdataOpSlp(slpAtoms(burnAtoms)),
|
|
150
150
|
]);
|
|
151
151
|
}
|
|
152
152
|
|
|
@@ -170,13 +170,13 @@ function verifyTokenId(tokenId: string) {
|
|
|
170
170
|
}
|
|
171
171
|
}
|
|
172
172
|
|
|
173
|
-
function
|
|
174
|
-
if (
|
|
175
|
-
throw new Error('
|
|
173
|
+
function verifySendAtomsArray(sendAtomsArray: bigint[]) {
|
|
174
|
+
if (sendAtomsArray.length == 0) {
|
|
175
|
+
throw new Error('sendAtomsArray cannot be empty');
|
|
176
176
|
}
|
|
177
|
-
if (
|
|
177
|
+
if (sendAtomsArray.length > 19) {
|
|
178
178
|
throw new Error(
|
|
179
|
-
`Cannot use more than 19 amounts, but got ${
|
|
179
|
+
`Cannot use more than 19 amounts, but got ${sendAtomsArray.length}`,
|
|
180
180
|
);
|
|
181
181
|
}
|
|
182
182
|
}
|
|
@@ -197,16 +197,16 @@ function pushdataOpSlp(pushdata: Uint8Array): Op {
|
|
|
197
197
|
return pushBytesOp(pushdata);
|
|
198
198
|
}
|
|
199
199
|
|
|
200
|
-
export function
|
|
201
|
-
if (
|
|
202
|
-
throw new Error(`
|
|
200
|
+
export function slpAtoms(atoms: bigint): Uint8Array {
|
|
201
|
+
if (atoms < 0n || atoms > 0xffffffffffffffffn) {
|
|
202
|
+
throw new Error(`Atoms out of range: ${atoms}`);
|
|
203
203
|
}
|
|
204
|
-
const
|
|
204
|
+
const atomsBytes = new Uint8Array(8);
|
|
205
205
|
const view = new DataView(
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
206
|
+
atomsBytes.buffer,
|
|
207
|
+
atomsBytes.byteOffset,
|
|
208
|
+
atomsBytes.byteLength,
|
|
209
209
|
);
|
|
210
|
-
view.setBigUint64(0,
|
|
211
|
-
return
|
|
210
|
+
view.setBigUint64(0, atoms, /*little endian=*/ false);
|
|
211
|
+
return atomsBytes;
|
|
212
212
|
}
|
package/src/tx.ts
CHANGED
|
@@ -49,7 +49,7 @@ export interface TxInput {
|
|
|
49
49
|
/** CTxOut, creating a new output. */
|
|
50
50
|
export interface TxOutput {
|
|
51
51
|
/** Value in satoshis of the output (1 XEC = 100 satoshis) */
|
|
52
|
-
|
|
52
|
+
sats: bigint;
|
|
53
53
|
/** Script locking the output */
|
|
54
54
|
script: Script;
|
|
55
55
|
}
|
|
@@ -57,7 +57,7 @@ export interface TxOutput {
|
|
|
57
57
|
/** All the data required to sign an input (using BIP143). */
|
|
58
58
|
export interface SignData {
|
|
59
59
|
/** Value of the output being spent */
|
|
60
|
-
|
|
60
|
+
sats: bigint;
|
|
61
61
|
/** Script of the output being spent (not for P2SH) */
|
|
62
62
|
outputScript?: Script;
|
|
63
63
|
/**
|
|
@@ -120,10 +120,10 @@ export class Tx {
|
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
export function readTxOutput(bytes: Bytes): TxOutput {
|
|
123
|
-
const
|
|
123
|
+
const sats = bytes.readU64();
|
|
124
124
|
const script = Script.readWithSize(bytes);
|
|
125
125
|
return {
|
|
126
|
-
|
|
126
|
+
sats,
|
|
127
127
|
script,
|
|
128
128
|
};
|
|
129
129
|
}
|
|
@@ -147,7 +147,7 @@ export function writeTxInput(input: TxInput, writer: Writer): void {
|
|
|
147
147
|
|
|
148
148
|
/** Write a TxOutput to a Writer */
|
|
149
149
|
export function writeTxOutput(output: TxOutput, writer: Writer): void {
|
|
150
|
-
writer.putU64(output.
|
|
150
|
+
writer.putU64(output.sats);
|
|
151
151
|
output.script.writeWithSize(writer);
|
|
152
152
|
}
|
|
153
153
|
|
|
@@ -164,7 +164,7 @@ export function copyTxInput(input: TxInput): TxInput {
|
|
|
164
164
|
script: input.script?.copy(),
|
|
165
165
|
sequence: input.sequence,
|
|
166
166
|
signData: input.signData && {
|
|
167
|
-
|
|
167
|
+
sats: input.signData.sats,
|
|
168
168
|
outputScript: input.signData.outputScript?.copy(),
|
|
169
169
|
redeemScript: input.signData.redeemScript?.copy(),
|
|
170
170
|
},
|
|
@@ -174,7 +174,7 @@ export function copyTxInput(input: TxInput): TxInput {
|
|
|
174
174
|
/** Create a deep copy of the TxOutput */
|
|
175
175
|
export function copyTxOutput(output: TxOutput): TxOutput {
|
|
176
176
|
return {
|
|
177
|
-
|
|
177
|
+
sats: output.sats,
|
|
178
178
|
script: output.script.copy(),
|
|
179
179
|
};
|
|
180
180
|
}
|
package/src/txBuilder.ts
CHANGED
|
@@ -84,7 +84,7 @@ export class TxBuilder {
|
|
|
84
84
|
if (input.input.signData === undefined) {
|
|
85
85
|
return undefined;
|
|
86
86
|
}
|
|
87
|
-
inputSum += BigInt(input.input.signData.
|
|
87
|
+
inputSum += BigInt(input.input.signData.sats);
|
|
88
88
|
}
|
|
89
89
|
return inputSum;
|
|
90
90
|
}
|
|
@@ -108,11 +108,11 @@ export class TxBuilder {
|
|
|
108
108
|
}
|
|
109
109
|
leftoverIdx = idx;
|
|
110
110
|
outputs[idx] = {
|
|
111
|
-
|
|
111
|
+
sats: 0n, // placeholder
|
|
112
112
|
script: builderOutput.copy(),
|
|
113
113
|
};
|
|
114
114
|
} else {
|
|
115
|
-
fixedOutputSum += BigInt(builderOutput.
|
|
115
|
+
fixedOutputSum += BigInt(builderOutput.sats);
|
|
116
116
|
outputs[idx] = copyTxOutput(builderOutput);
|
|
117
117
|
}
|
|
118
118
|
}
|
|
@@ -122,8 +122,8 @@ export class TxBuilder {
|
|
|
122
122
|
/** Sign the tx built by this builder and return a Tx */
|
|
123
123
|
public sign(params?: {
|
|
124
124
|
ecc?: Ecc;
|
|
125
|
-
feePerKb?:
|
|
126
|
-
|
|
125
|
+
feePerKb?: bigint;
|
|
126
|
+
dustSats?: bigint;
|
|
127
127
|
}): Tx {
|
|
128
128
|
const ecc = params?.ecc ?? new Ecc();
|
|
129
129
|
const { fixedOutputSum, leftoverIdx, outputs } = this.prepareOutputs();
|
|
@@ -147,7 +147,7 @@ export class TxBuilder {
|
|
|
147
147
|
const inputSum = this.inputSum();
|
|
148
148
|
if (inputSum === undefined) {
|
|
149
149
|
throw new Error(
|
|
150
|
-
'Using a leftover output requires setting SignData.
|
|
150
|
+
'Using a leftover output requires setting SignData.sats for all inputs',
|
|
151
151
|
);
|
|
152
152
|
}
|
|
153
153
|
if (params?.feePerKb === undefined) {
|
|
@@ -155,12 +155,12 @@ export class TxBuilder {
|
|
|
155
155
|
'Using a leftover output requires setting feePerKb',
|
|
156
156
|
);
|
|
157
157
|
}
|
|
158
|
-
if (
|
|
159
|
-
throw new Error('feePerKb must be
|
|
158
|
+
if (typeof params.feePerKb !== 'bigint') {
|
|
159
|
+
throw new Error('feePerKb must be a bigint');
|
|
160
160
|
}
|
|
161
|
-
if (params?.
|
|
161
|
+
if (params?.dustSats === undefined) {
|
|
162
162
|
throw new Error(
|
|
163
|
-
'Using a leftover output requires setting
|
|
163
|
+
'Using a leftover output requires setting dustSats',
|
|
164
164
|
);
|
|
165
165
|
}
|
|
166
166
|
const dummyUnsignedTx = UnsignedTx.dummyFromTx(
|
|
@@ -175,8 +175,8 @@ export class TxBuilder {
|
|
|
175
175
|
updateSignatories(new EccDummy(), dummyUnsignedTx);
|
|
176
176
|
let txSize = dummyUnsignedTx.tx.serSize();
|
|
177
177
|
let txFee = calcTxFee(txSize, params.feePerKb);
|
|
178
|
-
const
|
|
179
|
-
if (
|
|
178
|
+
const leftoverSats = inputSum - (fixedOutputSum + txFee);
|
|
179
|
+
if (leftoverSats < params.dustSats) {
|
|
180
180
|
// inputs cannot pay for a dust leftover -> remove & recalc
|
|
181
181
|
outputs.splice(leftoverIdx, 1);
|
|
182
182
|
dummyUnsignedTx.tx.outputs = outputs;
|
|
@@ -185,11 +185,11 @@ export class TxBuilder {
|
|
|
185
185
|
txSize = dummyUnsignedTx.tx.serSize();
|
|
186
186
|
txFee = calcTxFee(txSize, params.feePerKb);
|
|
187
187
|
} else {
|
|
188
|
-
outputs[leftoverIdx].
|
|
188
|
+
outputs[leftoverIdx].sats = leftoverSats;
|
|
189
189
|
}
|
|
190
190
|
if (inputSum < fixedOutputSum + txFee) {
|
|
191
191
|
throw new Error(
|
|
192
|
-
`Insufficient input
|
|
192
|
+
`Insufficient input sats (${inputSum}): Can only pay for ${
|
|
193
193
|
inputSum - fixedOutputSum
|
|
194
194
|
} fees, but ${txFee} required`,
|
|
195
195
|
);
|
|
@@ -210,7 +210,7 @@ export class TxBuilder {
|
|
|
210
210
|
|
|
211
211
|
/** Calculate the required tx fee for the given txSize and feePerKb,
|
|
212
212
|
* rounding up */
|
|
213
|
-
export function calcTxFee(txSize: number, feePerKb:
|
|
213
|
+
export function calcTxFee(txSize: number, feePerKb: bigint): bigint {
|
|
214
214
|
return (BigInt(txSize) * BigInt(feePerKb) + 999n) / 1000n;
|
|
215
215
|
}
|
|
216
216
|
|
package/src/unsignedTx.ts
CHANGED
|
@@ -146,7 +146,7 @@ function writeLegacyPreimage(
|
|
|
146
146
|
idx != inputIdx
|
|
147
147
|
) {
|
|
148
148
|
// Do not lock-in the txout payee at other indices as txin
|
|
149
|
-
writeTxOutput({
|
|
149
|
+
writeTxOutput({ sats: 0n, script: new Script() }, writer);
|
|
150
150
|
} else {
|
|
151
151
|
writeTxOutput(tx.outputs[idx], writer);
|
|
152
152
|
}
|
|
@@ -288,7 +288,7 @@ export class UnsignedTxInput {
|
|
|
288
288
|
}
|
|
289
289
|
writeOutPoint(input.prevOut, writer);
|
|
290
290
|
scriptCode.writeWithSize(writer);
|
|
291
|
-
writer.putU64(signData.
|
|
291
|
+
writer.putU64(signData.sats);
|
|
292
292
|
writer.putU32(input.sequence ?? DEFAULT_SEQUENCE);
|
|
293
293
|
writer.putBytes(hashOutputs);
|
|
294
294
|
writer.putU32(tx.locktime);
|