mainnet-js 1.1.1 → 1.1.2
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/index.html +1 -1
- package/dist/{mainnet-1.1.1.js → mainnet-1.1.2.js} +4 -4
- package/dist/module/libauth.d.ts +1 -1
- package/dist/module/libauth.d.ts.map +1 -1
- package/dist/module/libauth.js +1 -1
- package/dist/module/libauth.js.map +1 -1
- package/dist/module/transaction/Wif.d.ts +42 -7
- package/dist/module/transaction/Wif.d.ts.map +1 -1
- package/dist/module/transaction/Wif.js +128 -107
- package/dist/module/transaction/Wif.js.map +1 -1
- package/dist/module/wallet/Slp.d.ts.map +1 -1
- package/dist/module/wallet/Slp.js +11 -1
- package/dist/module/wallet/Slp.js.map +1 -1
- package/dist/module/wallet/Wif.d.ts +8 -4
- package/dist/module/wallet/Wif.d.ts.map +1 -1
- package/dist/module/wallet/Wif.js +121 -55
- package/dist/module/wallet/Wif.js.map +1 -1
- package/dist/module/wallet/interface.d.ts +2 -0
- package/dist/module/wallet/interface.d.ts.map +1 -1
- package/dist/module/wallet/model.d.ts +4 -0
- package/dist/module/wallet/model.d.ts.map +1 -1
- package/dist/module/wallet/model.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/libauth.ts +1 -0
- package/src/transaction/Wif.ts +200 -155
- package/src/wallet/Cashtokens.test.headless.js +161 -0
- package/src/wallet/Cashtokens.test.ts +149 -1
- package/src/wallet/Slp.ts +10 -7
- package/src/wallet/Wif.test.ts +101 -1
- package/src/wallet/Wif.ts +161 -92
- package/src/wallet/interface.ts +2 -0
- package/src/wallet/model.ts +6 -0
package/src/transaction/Wif.ts
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
CompilationContextBCH,
|
|
13
13
|
Output,
|
|
14
14
|
hexToBin,
|
|
15
|
+
verifyTransactionTokens,
|
|
15
16
|
} from "@bitauth/libauth";
|
|
16
17
|
import { NFTCapability, TokenI, UtxoI } from "../interface.js";
|
|
17
18
|
import { allocateFee } from "./allocateFee.js";
|
|
@@ -29,16 +30,27 @@ import { sumUtxoValue } from "../util/sumUtxoValue.js";
|
|
|
29
30
|
import { FeePaidByEnum } from "../wallet/enum.js";
|
|
30
31
|
|
|
31
32
|
// Build a transaction for a p2pkh transaction for a non HD wallet
|
|
32
|
-
export async function buildP2pkhNonHdTransaction(
|
|
33
|
-
inputs
|
|
34
|
-
outputs
|
|
35
|
-
signingKey
|
|
36
|
-
|
|
33
|
+
export async function buildP2pkhNonHdTransaction({
|
|
34
|
+
inputs,
|
|
35
|
+
outputs,
|
|
36
|
+
signingKey,
|
|
37
|
+
sourceAddress,
|
|
38
|
+
fee = 0,
|
|
37
39
|
discardChange = false,
|
|
38
|
-
slpOutputs
|
|
39
|
-
feePaidBy
|
|
40
|
-
changeAddress
|
|
41
|
-
|
|
40
|
+
slpOutputs = [],
|
|
41
|
+
feePaidBy = FeePaidByEnum.change,
|
|
42
|
+
changeAddress = "",
|
|
43
|
+
}: {
|
|
44
|
+
inputs: UtxoI[];
|
|
45
|
+
outputs: Array<SendRequest | TokenSendRequest | OpReturnData>;
|
|
46
|
+
signingKey: Uint8Array;
|
|
47
|
+
sourceAddress: string;
|
|
48
|
+
fee?: number;
|
|
49
|
+
discardChange?: boolean;
|
|
50
|
+
slpOutputs?: Output[];
|
|
51
|
+
feePaidBy?: FeePaidByEnum;
|
|
52
|
+
changeAddress?: string;
|
|
53
|
+
}) {
|
|
42
54
|
if (!signingKey) {
|
|
43
55
|
throw new Error("Missing signing key when building transaction");
|
|
44
56
|
}
|
|
@@ -59,7 +71,7 @@ export async function buildP2pkhNonHdTransaction(
|
|
|
59
71
|
|
|
60
72
|
outputs = allocateFee(outputs, fee, feePaidBy, changeAmount);
|
|
61
73
|
|
|
62
|
-
|
|
74
|
+
const lockedOutputs = await prepareOutputs(outputs);
|
|
63
75
|
|
|
64
76
|
if (discardChange !== true) {
|
|
65
77
|
if (changeAmount > DUST_UTXO_THRESHOLD) {
|
|
@@ -85,31 +97,56 @@ export async function buildP2pkhNonHdTransaction(
|
|
|
85
97
|
}
|
|
86
98
|
}
|
|
87
99
|
|
|
88
|
-
|
|
100
|
+
const { preparedInputs, sourceOutputs } = prepareInputs({
|
|
101
|
+
inputs,
|
|
102
|
+
compiler,
|
|
103
|
+
signingKey,
|
|
104
|
+
sourceAddress,
|
|
105
|
+
});
|
|
89
106
|
const result = generateTransaction({
|
|
90
|
-
inputs:
|
|
107
|
+
inputs: preparedInputs,
|
|
91
108
|
locktime: 0,
|
|
92
109
|
outputs: [...slpOutputs, ...lockedOutputs],
|
|
93
110
|
version: 2,
|
|
94
111
|
});
|
|
95
|
-
|
|
112
|
+
|
|
113
|
+
if (!result.success) {
|
|
114
|
+
throw Error("Error building transaction with fee");
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const tokenValidationResult = verifyTransactionTokens(
|
|
118
|
+
result.transaction,
|
|
119
|
+
sourceOutputs
|
|
120
|
+
);
|
|
121
|
+
if (tokenValidationResult !== true && fee > 0) {
|
|
122
|
+
throw tokenValidationResult;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return { transaction: result.transaction, sourceOutputs: sourceOutputs };
|
|
96
126
|
}
|
|
97
127
|
|
|
98
|
-
export function prepareInputs(
|
|
99
|
-
inputs
|
|
128
|
+
export function prepareInputs({
|
|
129
|
+
inputs,
|
|
130
|
+
compiler,
|
|
131
|
+
signingKey,
|
|
132
|
+
sourceAddress,
|
|
133
|
+
}: {
|
|
134
|
+
inputs: UtxoI[];
|
|
100
135
|
compiler: Compiler<
|
|
101
136
|
CompilationContextBCH,
|
|
102
137
|
AnyCompilerConfiguration<CompilationContextBCH>,
|
|
103
138
|
AuthenticationProgramStateCommon
|
|
104
|
-
|
|
105
|
-
signingKey: Uint8Array
|
|
106
|
-
|
|
107
|
-
|
|
139
|
+
>;
|
|
140
|
+
signingKey: Uint8Array;
|
|
141
|
+
sourceAddress: string;
|
|
142
|
+
}) {
|
|
143
|
+
const preparedInputs: any[] = [];
|
|
144
|
+
const sourceOutputs: any[] = [];
|
|
108
145
|
for (const i of inputs) {
|
|
109
146
|
const utxoTxnValue = i.satoshis;
|
|
110
147
|
const utxoIndex = i.vout;
|
|
111
148
|
// slice will create a clone of the array
|
|
112
|
-
|
|
149
|
+
const utxoOutpointTransactionHash = new Uint8Array(
|
|
113
150
|
i.txid.match(/.{1,2}/g)!.map((byte) => parseInt(byte, 16))
|
|
114
151
|
);
|
|
115
152
|
// reverse the cloned copy
|
|
@@ -122,30 +159,51 @@ export function prepareInputs(
|
|
|
122
159
|
amount: BigInt(i.token.amount),
|
|
123
160
|
category: hexToBin(i.token.tokenId),
|
|
124
161
|
nft:
|
|
125
|
-
i.token.capability || i.token.commitment
|
|
162
|
+
i.token.capability !== undefined || i.token.commitment !== undefined
|
|
126
163
|
? {
|
|
127
164
|
capability: i.token.capability,
|
|
128
|
-
commitment:
|
|
165
|
+
commitment:
|
|
166
|
+
i.token.commitment !== undefined &&
|
|
167
|
+
hexToBin(i.token.commitment!),
|
|
129
168
|
}
|
|
130
169
|
: undefined,
|
|
131
170
|
};
|
|
132
|
-
|
|
171
|
+
const newInput = signingKey?.length
|
|
172
|
+
? {
|
|
173
|
+
outpointIndex: utxoIndex,
|
|
174
|
+
outpointTransactionHash: utxoOutpointTransactionHash,
|
|
175
|
+
sequenceNumber: 0,
|
|
176
|
+
unlockingBytecode: {
|
|
177
|
+
compiler,
|
|
178
|
+
data: {
|
|
179
|
+
keys: { privateKeys: { key: signingKey } },
|
|
180
|
+
},
|
|
181
|
+
valueSatoshis: BigInt(utxoTxnValue),
|
|
182
|
+
script: "unlock",
|
|
183
|
+
token: libAuthToken,
|
|
184
|
+
},
|
|
185
|
+
}
|
|
186
|
+
: {
|
|
187
|
+
outpointIndex: utxoIndex,
|
|
188
|
+
outpointTransactionHash: utxoOutpointTransactionHash,
|
|
189
|
+
sequenceNumber: 0,
|
|
190
|
+
unlockingBytecode: Uint8Array.from([]),
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
preparedInputs.push(newInput);
|
|
194
|
+
sourceOutputs.push({
|
|
133
195
|
outpointIndex: utxoIndex,
|
|
134
196
|
outpointTransactionHash: utxoOutpointTransactionHash,
|
|
135
197
|
sequenceNumber: 0,
|
|
136
|
-
unlockingBytecode:
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
token: libAuthToken,
|
|
144
|
-
},
|
|
145
|
-
};
|
|
146
|
-
signedInputs.push(newInput);
|
|
198
|
+
unlockingBytecode: Uint8Array.from([]),
|
|
199
|
+
|
|
200
|
+
// additional info for sourceOutputs
|
|
201
|
+
lockingBytecode: cashAddressToLockingBytecode(sourceAddress),
|
|
202
|
+
valueSatoshis: BigInt(utxoTxnValue),
|
|
203
|
+
token: libAuthToken,
|
|
204
|
+
});
|
|
147
205
|
}
|
|
148
|
-
return
|
|
206
|
+
return { preparedInputs, sourceOutputs };
|
|
149
207
|
}
|
|
150
208
|
|
|
151
209
|
/**
|
|
@@ -156,13 +214,12 @@ export function prepareInputs(
|
|
|
156
214
|
* @returns A promise to a list of unspent outputs
|
|
157
215
|
*/
|
|
158
216
|
export async function prepareOutputs(
|
|
159
|
-
outputs: Array<SendRequest | TokenSendRequest | OpReturnData
|
|
160
|
-
inputs: UtxoI[]
|
|
217
|
+
outputs: Array<SendRequest | TokenSendRequest | OpReturnData>
|
|
161
218
|
) {
|
|
162
|
-
|
|
219
|
+
const lockedOutputs: Output[] = [];
|
|
163
220
|
for (const output of outputs) {
|
|
164
221
|
if (output instanceof TokenSendRequest) {
|
|
165
|
-
lockedOutputs.push(prepareTokenOutputs(output
|
|
222
|
+
lockedOutputs.push(prepareTokenOutputs(output));
|
|
166
223
|
continue;
|
|
167
224
|
}
|
|
168
225
|
|
|
@@ -207,49 +264,9 @@ export function prepareOpReturnOutput(request: OpReturnData): Output {
|
|
|
207
264
|
*
|
|
208
265
|
* @returns A libauth Output
|
|
209
266
|
*/
|
|
210
|
-
export function prepareTokenOutputs(
|
|
211
|
-
request: TokenSendRequest,
|
|
212
|
-
inputs: UtxoI[]
|
|
213
|
-
): Output {
|
|
267
|
+
export function prepareTokenOutputs(request: TokenSendRequest): Output {
|
|
214
268
|
const token: TokenI = request;
|
|
215
|
-
const
|
|
216
|
-
let satValue = 0;
|
|
217
|
-
if (isGenesis) {
|
|
218
|
-
const genesisInputs = inputs.filter((val) => val.vout === 0);
|
|
219
|
-
if (genesisInputs.length === 0) {
|
|
220
|
-
throw new Error(
|
|
221
|
-
"No suitable inputs with vout=0 available for new token genesis"
|
|
222
|
-
);
|
|
223
|
-
}
|
|
224
|
-
token.tokenId = genesisInputs[0].txid;
|
|
225
|
-
satValue = request.value || 1000;
|
|
226
|
-
(request as any)._isGenesis = true;
|
|
227
|
-
} else {
|
|
228
|
-
const tokenInputs = inputs.filter(
|
|
229
|
-
(val) =>
|
|
230
|
-
val.token?.tokenId &&
|
|
231
|
-
val.token?.tokenId === request.tokenId &&
|
|
232
|
-
(val.token?.capability === "none"
|
|
233
|
-
? val.token.capability === request.capability &&
|
|
234
|
-
val.token?.commitment === request.commitment
|
|
235
|
-
: true)
|
|
236
|
-
);
|
|
237
|
-
if (!tokenInputs.length) {
|
|
238
|
-
throw new Error(
|
|
239
|
-
`No suitable token utxos available to send token with id "${request.tokenId}", capability "${request.capability}", commitment "${request.commitment}"`
|
|
240
|
-
);
|
|
241
|
-
}
|
|
242
|
-
if (!token.capability && tokenInputs[0].token?.capability) {
|
|
243
|
-
token.capability = tokenInputs[0].token!.capability;
|
|
244
|
-
}
|
|
245
|
-
if (!token.commitment && tokenInputs[0].token?.commitment) {
|
|
246
|
-
token.commitment = tokenInputs[0].token!.commitment;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
satValue = request.value || tokenInputs[0].satoshis;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
let outputLockingBytecode = cashAddressToLockingBytecode(request.cashaddr);
|
|
269
|
+
const outputLockingBytecode = cashAddressToLockingBytecode(request.cashaddr);
|
|
253
270
|
if (typeof outputLockingBytecode === "string")
|
|
254
271
|
throw new Error(outputLockingBytecode);
|
|
255
272
|
|
|
@@ -257,17 +274,18 @@ export function prepareTokenOutputs(
|
|
|
257
274
|
amount: BigInt(token.amount),
|
|
258
275
|
category: hexToBin(token.tokenId),
|
|
259
276
|
nft:
|
|
260
|
-
token.capability || token.commitment
|
|
277
|
+
token.capability !== undefined || token.commitment !== undefined
|
|
261
278
|
? {
|
|
262
279
|
capability: token.capability,
|
|
263
|
-
commitment:
|
|
280
|
+
commitment:
|
|
281
|
+
token.commitment !== undefined && hexToBin(token.commitment!),
|
|
264
282
|
}
|
|
265
283
|
: undefined,
|
|
266
284
|
};
|
|
267
285
|
|
|
268
286
|
return {
|
|
269
287
|
lockingBytecode: outputLockingBytecode.bytecode,
|
|
270
|
-
valueSatoshis: BigInt(
|
|
288
|
+
valueSatoshis: BigInt(request.value || 1000),
|
|
271
289
|
token: libAuthToken,
|
|
272
290
|
} as Output;
|
|
273
291
|
}
|
|
@@ -287,61 +305,72 @@ export async function getSuitableUtxos(
|
|
|
287
305
|
bestHeight: number,
|
|
288
306
|
feePaidBy: FeePaidByEnum,
|
|
289
307
|
requests: SendRequestType[],
|
|
290
|
-
ensureUtxos: UtxoI[] = []
|
|
308
|
+
ensureUtxos: UtxoI[] = [],
|
|
309
|
+
tokenOperation: "send" | "genesis" | "mint" | "burn" = "send"
|
|
291
310
|
): Promise<UtxoI[]> {
|
|
292
|
-
|
|
311
|
+
const suitableUtxos: UtxoI[] = [...ensureUtxos];
|
|
293
312
|
let amountAvailable = BigInt(0);
|
|
294
|
-
const tokenAmountsRequired: any[] = [];
|
|
295
313
|
const tokenRequests = requests.filter(
|
|
296
314
|
(val) => val instanceof TokenSendRequest
|
|
297
315
|
) as TokenSendRequest[];
|
|
298
316
|
|
|
299
|
-
|
|
300
|
-
const isTokenGenesis = tokenRequests.some(
|
|
301
|
-
(val) => !val.tokenId || (val as any)._isGenesis
|
|
302
|
-
);
|
|
303
|
-
const bchOnlyTransfer = tokenRequests.length === 0;
|
|
304
|
-
let filteredInputs =
|
|
305
|
-
isTokenGenesis || bchOnlyTransfer
|
|
306
|
-
? inputs.slice(0).filter((val) => !val.token)
|
|
307
|
-
: inputs.slice();
|
|
308
|
-
const tokenIds = tokenRequests
|
|
309
|
-
.map((val) => val.tokenId)
|
|
310
|
-
.filter((value, index, array) => array.indexOf(value) === index);
|
|
311
|
-
for (let tokenId of tokenIds) {
|
|
312
|
-
const requiredAmount = tokenRequests
|
|
313
|
-
.map((val) => val.amount)
|
|
314
|
-
.reduce((prev, cur) => prev + cur, 0);
|
|
315
|
-
tokenAmountsRequired.push({ tokenId, requiredAmount });
|
|
316
|
-
}
|
|
317
|
+
const availableInputs = inputs.slice();
|
|
317
318
|
|
|
318
|
-
// find
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
319
|
+
// find matching utxos for token transfers
|
|
320
|
+
if (tokenOperation === "send") {
|
|
321
|
+
for (const request of tokenRequests) {
|
|
322
|
+
const tokenInputs = availableInputs.filter(
|
|
323
|
+
(val) => val.token?.tokenId === request.tokenId
|
|
324
|
+
);
|
|
325
|
+
const sameCommitmentTokens = [...suitableUtxos, ...tokenInputs].filter(
|
|
326
|
+
(val) =>
|
|
327
|
+
val.token?.capability === request.capability &&
|
|
328
|
+
val.token?.commitment === request.commitment
|
|
329
|
+
);
|
|
330
|
+
if (sameCommitmentTokens.length) {
|
|
331
|
+
const input = sameCommitmentTokens[0];
|
|
332
|
+
const index = availableInputs.indexOf(input);
|
|
333
|
+
if (index !== -1) {
|
|
334
|
+
suitableUtxos.push(input);
|
|
335
|
+
availableInputs.splice(index, 1);
|
|
336
|
+
amountAvailable += BigInt(input.satoshis);
|
|
332
337
|
}
|
|
338
|
+
|
|
339
|
+
continue;
|
|
333
340
|
}
|
|
341
|
+
|
|
342
|
+
if (
|
|
343
|
+
request.capability === NFTCapability.minting ||
|
|
344
|
+
request.capability === NFTCapability.mutable
|
|
345
|
+
) {
|
|
346
|
+
const changeCommitmentTokens = [
|
|
347
|
+
...suitableUtxos,
|
|
348
|
+
...tokenInputs,
|
|
349
|
+
].filter((val) => val.token?.capability === request.capability);
|
|
350
|
+
if (changeCommitmentTokens.length) {
|
|
351
|
+
const input = changeCommitmentTokens[0];
|
|
352
|
+
const index = availableInputs.indexOf(input);
|
|
353
|
+
if (index !== -1) {
|
|
354
|
+
suitableUtxos.push(input);
|
|
355
|
+
availableInputs.splice(index, 1);
|
|
356
|
+
amountAvailable += BigInt(input.satoshis);
|
|
357
|
+
}
|
|
358
|
+
continue;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
throw Error(
|
|
362
|
+
`No suitable token utxos available to send token with id "${request.tokenId}", capability "${request.capability}", commitment "${request.commitment}"`
|
|
363
|
+
);
|
|
334
364
|
}
|
|
335
365
|
}
|
|
336
|
-
|
|
337
366
|
// find plain bch outputs
|
|
338
|
-
for (const u of
|
|
367
|
+
for (const u of availableInputs) {
|
|
339
368
|
if (u.token) {
|
|
340
369
|
continue;
|
|
341
370
|
}
|
|
342
371
|
|
|
343
372
|
if (u.coinbase && u.height && bestHeight) {
|
|
344
|
-
|
|
373
|
+
const age = bestHeight - u.height;
|
|
345
374
|
if (age > 100) {
|
|
346
375
|
suitableUtxos.push(u);
|
|
347
376
|
amountAvailable += BigInt(u.satoshis);
|
|
@@ -357,8 +386,11 @@ export async function getSuitableUtxos(
|
|
|
357
386
|
}
|
|
358
387
|
|
|
359
388
|
const addEnsured = (suitableUtxos) => {
|
|
360
|
-
return [...
|
|
361
|
-
(val, index, array) =>
|
|
389
|
+
return [...ensureUtxos, ...suitableUtxos].filter(
|
|
390
|
+
(val, index, array) =>
|
|
391
|
+
array.findIndex(
|
|
392
|
+
(other) => other.txid === val.txid && other.vout === val.vout
|
|
393
|
+
) === index
|
|
362
394
|
);
|
|
363
395
|
};
|
|
364
396
|
|
|
@@ -371,7 +403,7 @@ export async function getSuitableUtxos(
|
|
|
371
403
|
if (typeof amountRequired === "undefined") {
|
|
372
404
|
return addEnsured(suitableUtxos);
|
|
373
405
|
} else if (amountAvailable < amountRequired) {
|
|
374
|
-
|
|
406
|
+
const e = Error(
|
|
375
407
|
`Amount required was not met, ${amountRequired} satoshis needed, ${amountAvailable} satoshis available`
|
|
376
408
|
);
|
|
377
409
|
e["data"] = {
|
|
@@ -388,6 +420,7 @@ export async function getFeeAmount({
|
|
|
388
420
|
utxos,
|
|
389
421
|
sendRequests,
|
|
390
422
|
privateKey,
|
|
423
|
+
sourceAddress,
|
|
391
424
|
relayFeePerByteInSatoshi,
|
|
392
425
|
slpOutputs,
|
|
393
426
|
feePaidBy,
|
|
@@ -396,6 +429,7 @@ export async function getFeeAmount({
|
|
|
396
429
|
utxos: UtxoI[];
|
|
397
430
|
sendRequests: Array<SendRequest | TokenSendRequest | OpReturnData>;
|
|
398
431
|
privateKey: Uint8Array;
|
|
432
|
+
sourceAddress: string;
|
|
399
433
|
relayFeePerByteInSatoshi: number;
|
|
400
434
|
slpOutputs: Output[];
|
|
401
435
|
feePaidBy: FeePaidByEnum;
|
|
@@ -404,15 +438,18 @@ export async function getFeeAmount({
|
|
|
404
438
|
// build transaction
|
|
405
439
|
if (utxos) {
|
|
406
440
|
// Build the transaction to get the approximate size
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
441
|
+
const { encodedTransaction: draftTransaction } =
|
|
442
|
+
await buildEncodedTransaction({
|
|
443
|
+
inputs: utxos,
|
|
444
|
+
outputs: sendRequests,
|
|
445
|
+
signingKey: privateKey,
|
|
446
|
+
sourceAddress,
|
|
447
|
+
fee: 0, //DUST_UTXO_THRESHOLD
|
|
448
|
+
discardChange: discardChange ?? false,
|
|
449
|
+
slpOutputs,
|
|
450
|
+
feePaidBy,
|
|
451
|
+
changeAddress: "",
|
|
452
|
+
});
|
|
416
453
|
|
|
417
454
|
return draftTransaction.length * relayFeePerByteInSatoshi + 1;
|
|
418
455
|
} else {
|
|
@@ -423,30 +460,38 @@ export async function getFeeAmount({
|
|
|
423
460
|
}
|
|
424
461
|
|
|
425
462
|
// Build encoded transaction
|
|
426
|
-
export async function buildEncodedTransaction(
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
463
|
+
export async function buildEncodedTransaction({
|
|
464
|
+
inputs,
|
|
465
|
+
outputs,
|
|
466
|
+
signingKey,
|
|
467
|
+
sourceAddress,
|
|
468
|
+
fee = 0,
|
|
431
469
|
discardChange = false,
|
|
432
|
-
slpOutputs
|
|
433
|
-
feePaidBy
|
|
434
|
-
changeAddress
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
470
|
+
slpOutputs = [],
|
|
471
|
+
feePaidBy = FeePaidByEnum.change,
|
|
472
|
+
changeAddress = "",
|
|
473
|
+
}: {
|
|
474
|
+
inputs: UtxoI[];
|
|
475
|
+
outputs: Array<SendRequest | TokenSendRequest | OpReturnData>;
|
|
476
|
+
signingKey: Uint8Array;
|
|
477
|
+
sourceAddress: string;
|
|
478
|
+
fee?: number;
|
|
479
|
+
discardChange?: boolean;
|
|
480
|
+
slpOutputs?: Output[];
|
|
481
|
+
feePaidBy?: FeePaidByEnum;
|
|
482
|
+
changeAddress?: string;
|
|
483
|
+
}) {
|
|
484
|
+
const { transaction, sourceOutputs } = await buildP2pkhNonHdTransaction({
|
|
485
|
+
inputs,
|
|
486
|
+
outputs,
|
|
487
|
+
signingKey,
|
|
488
|
+
sourceAddress,
|
|
440
489
|
fee,
|
|
441
490
|
discardChange,
|
|
442
491
|
slpOutputs,
|
|
443
492
|
feePaidBy,
|
|
444
|
-
changeAddress
|
|
445
|
-
);
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
return encodeTransaction(txn.transaction);
|
|
449
|
-
} else {
|
|
450
|
-
throw Error("Error building transaction with fee");
|
|
451
|
-
}
|
|
493
|
+
changeAddress,
|
|
494
|
+
});
|
|
495
|
+
|
|
496
|
+
return { encodedTransaction: encodeTransaction(transaction), sourceOutputs };
|
|
452
497
|
}
|