mainnet-js 2.3.15 → 2.4.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.
Files changed (41) hide show
  1. package/dist/index.html +1 -1
  2. package/dist/{mainnet-2.3.15.js → mainnet-2.4.0.js} +15 -5
  3. package/dist/module/history/electrumTransformer.d.ts +11 -3
  4. package/dist/module/history/electrumTransformer.d.ts.map +1 -1
  5. package/dist/module/history/electrumTransformer.js +199 -195
  6. package/dist/module/history/electrumTransformer.js.map +1 -1
  7. package/dist/module/history/interface.d.ts +19 -13
  8. package/dist/module/history/interface.d.ts.map +1 -1
  9. package/dist/module/interface.d.ts +10 -1
  10. package/dist/module/interface.d.ts.map +1 -1
  11. package/dist/module/interface.js.map +1 -1
  12. package/dist/module/network/ElectrumNetworkProvider.d.ts +8 -6
  13. package/dist/module/network/ElectrumNetworkProvider.d.ts.map +1 -1
  14. package/dist/module/network/ElectrumNetworkProvider.js +28 -6
  15. package/dist/module/network/ElectrumNetworkProvider.js.map +1 -1
  16. package/dist/module/network/NetworkProvider.d.ts +8 -3
  17. package/dist/module/network/NetworkProvider.d.ts.map +1 -1
  18. package/dist/module/util/header.d.ts +3 -0
  19. package/dist/module/util/header.d.ts.map +1 -0
  20. package/dist/module/util/header.js +13 -0
  21. package/dist/module/util/header.js.map +1 -0
  22. package/dist/module/util/index.d.ts +1 -0
  23. package/dist/module/util/index.d.ts.map +1 -1
  24. package/dist/module/util/index.js +1 -0
  25. package/dist/module/util/index.js.map +1 -1
  26. package/dist/module/wallet/Wif.d.ts +27 -6
  27. package/dist/module/wallet/Wif.d.ts.map +1 -1
  28. package/dist/module/wallet/Wif.js +29 -7
  29. package/dist/module/wallet/Wif.js.map +1 -1
  30. package/dist/tsconfig.tsbuildinfo +1 -1
  31. package/package.json +1 -1
  32. package/src/history/electrumTransformer.test.ts +112 -55
  33. package/src/history/electrumTransformer.ts +279 -284
  34. package/src/history/interface.ts +19 -13
  35. package/src/interface.ts +11 -1
  36. package/src/network/ElectrumNetworkProvider.ts +58 -11
  37. package/src/network/NetworkProvider.ts +13 -3
  38. package/src/util/header.test.ts +34 -0
  39. package/src/util/header.ts +16 -0
  40. package/src/util/index.ts +1 -0
  41. package/src/wallet/Wif.ts +55 -21
@@ -1,319 +1,314 @@
1
1
  import {
2
2
  binToHex,
3
- cashAddressToLockingBytecode,
4
3
  decodeTransaction,
5
4
  hexToBin,
6
- Transaction,
7
5
  lockingBytecodeToCashAddress,
8
- Output,
6
+ CashAddressNetworkPrefix,
7
+ decodeCashAddress,
8
+ TransactionCommon,
9
9
  } from "@bitauth/libauth";
10
10
  import { UnitEnum } from "../enum.js";
11
11
  import NetworkProvider from "../network/NetworkProvider.js";
12
- import { derivePrefix } from "../util/derivePublicKeyHash.js";
13
12
  import { convert } from "../util/convert.js";
14
- import { bchParam } from "../chain.js";
15
- import { floor } from "../util/floor.js";
16
- import { TransactionHistoryI, TransactionHistoryItemI } from "./interface.js";
17
-
18
- export async function getAddressHistory(
19
- cashaddr: string,
20
- provider: NetworkProvider,
13
+ import { HeaderI, TokenI } from "../interface.js";
14
+ import { TransactionHistoryItem, InOutput } from "./interface.js";
15
+
16
+ type Transaction = TransactionCommon & {
17
+ size: number;
18
+ blockHeight: number;
19
+ timestamp?: number;
20
+ hash: string;
21
+ };
22
+
23
+ export const getAddressHistory = async ({
24
+ address,
25
+ provider,
21
26
  unit = "sat",
27
+ fromHeight = 0,
28
+ toHeight = -1,
22
29
  start = 0,
23
- count = 25,
24
- collapseChange = true
25
- ): Promise<TransactionHistoryI> {
26
- // Get an array of raw transactions as hex
27
- let txnHashes = await provider.getHistory(cashaddr);
28
-
29
- // Assume transaction hashes will be served in chronological order
30
- // Slice count in from the end and count to the provided inputs
31
- let len = txnHashes.length;
32
- txnHashes = txnHashes.slice(len - start - count, len - start);
33
-
34
- // get the current balance in satoshis
35
- let currentBalance = await provider.getBalance(cashaddr);
36
-
37
- // Transform the hex transactions to and array of histroy item array promises.
38
- let txItemPromises = txnHashes.map((tx) => {
39
- return getDetailedHistory(
40
- cashaddr,
41
- tx.tx_hash,
42
- tx.height,
43
- provider,
44
- collapseChange
45
- );
46
- });
30
+ count = -1,
31
+ }: {
32
+ address: string;
33
+ provider: NetworkProvider;
34
+ unit?: UnitEnum;
35
+ fromHeight?: number;
36
+ toHeight?: number;
37
+ start?: number;
38
+ count?: number;
39
+ }): Promise<TransactionHistoryItem[]> => {
40
+ if (count === -1) {
41
+ count = 1e10;
42
+ }
43
+
44
+ const history = (await provider.getHistory(address, fromHeight, toHeight))
45
+ .sort((a, b) =>
46
+ a.height <= 0 || b.height <= 0 ? a.height - b.height : b.height - a.height
47
+ )
48
+ .slice(start, start + count);
49
+
50
+ // fill transaction timestamps by requesting headers from network and parsing them
51
+ const heights = history
52
+ .map((tx) => tx.height)
53
+ .filter((height) => height > 0)
54
+ .filter((value, index, array) => array.indexOf(value) === index);
55
+ const timestampMap = (
56
+ await Promise.all(
57
+ heights.map(async (height) => [
58
+ height,
59
+ ((await provider.getHeader(height, true)) as HeaderI).timestamp,
60
+ ])
61
+ )
62
+ ).reduce((acc, [height, timestamp]) => ({ ...acc, [height]: timestamp }), {});
63
+
64
+ // first load all transactions
65
+ const historicTransactions = await Promise.all(
66
+ history.map(async (tx) => {
67
+ const txHex = (await provider.getRawTransaction(tx.tx_hash)) as string;
68
+
69
+ const transactionCommon = decodeTransaction(hexToBin(txHex));
70
+ if (typeof transactionCommon === "string") {
71
+ throw transactionCommon;
72
+ }
47
73
 
48
- // await the history array promises
49
- let items = await Promise.all(txItemPromises);
50
-
51
- // flatten the array of responses
52
- let preprocessedTxns = Array.prototype.concat.apply([], items);
53
-
54
- // Reverse chronological order (again), so list appear as newest first.
55
- preprocessedTxns = preprocessedTxns.reverse();
56
-
57
- // Get the factor to apply the requested unit of measure
58
- let factor =
59
- (await convert(bchParam.subUnits, "sat", unit)) / bchParam.subUnits;
60
-
61
- // Apply the unit factor and
62
- let txns = applyBalance(preprocessedTxns, currentBalance, unit, factor);
63
-
64
- return {
65
- transactions: txns,
66
- };
67
- }
68
-
69
- export async function getDetailedHistory(
70
- cashaddr: string,
71
- hash: string,
72
- height: number,
73
- provider: NetworkProvider,
74
- collapseChange: boolean
75
- ): Promise<TransactionHistoryItemI[]> {
76
- let transactionHex = await provider.getRawTransaction(hash);
77
-
78
- collapseChange;
79
- let addressBytecode = cashAddressToLockingBytecode(cashaddr);
80
- if (typeof addressBytecode === "string") throw Error(addressBytecode);
81
-
82
- let transaction = decodeTransaction(hexToBin(transactionHex));
83
- if (typeof transaction === "string") throw Error(transaction);
84
-
85
- let r: TransactionHistoryItemI[] = [];
86
- r.push(
87
- ...(await getMatchingInputs(
88
- transaction,
89
- cashaddr,
90
- height,
91
- hash,
92
- provider,
93
- collapseChange
94
- ))
74
+ const transaction = transactionCommon as Transaction;
75
+ transaction.blockHeight = tx.height;
76
+ transaction.timestamp = timestampMap[tx.height];
77
+ transaction.hash = tx.tx_hash;
78
+ transaction.size = txHex.length / 2;
79
+
80
+ return transaction;
81
+ })
95
82
  );
96
- return r;
97
- }
98
-
99
- async function getMatchingInputs(
100
- transaction: Transaction,
101
- cashaddr: string,
102
- height: number,
103
- hash: string,
104
- provider,
105
- collapseChange
106
- ) {
107
- let addressBytecode = cashAddressToLockingBytecode(cashaddr);
108
- if (typeof addressBytecode === "string") throw Error(addressBytecode);
109
- let lockingBytecodeHex = binToHex(addressBytecode.bytecode);
110
- let prefix = derivePrefix(cashaddr);
111
-
112
- let inputUtxos = await getInputTransactions(transaction, provider);
113
-
114
- let fee = getFee(
115
- inputUtxos,
116
- transaction.outputs,
117
- lockingBytecodeHex,
118
- collapseChange
83
+
84
+ // then load their prevout transactions
85
+ const prevoutTransactionHashes = historicTransactions
86
+ .map((tx) =>
87
+ tx.inputs.map((input) => binToHex(input.outpointTransactionHash))
88
+ )
89
+ .flat()
90
+ .filter((value, index, array) => array.indexOf(value) === index);
91
+ const prevoutTransactionMap = (
92
+ await Promise.all(
93
+ prevoutTransactionHashes.map(async (hash) => {
94
+ const txHex = (await provider.getRawTransaction(hash)) as string;
95
+
96
+ const transaction = decodeTransaction(hexToBin(txHex));
97
+ if (typeof transaction === "string") {
98
+ throw transaction;
99
+ }
100
+
101
+ return [hash, transaction];
102
+ })
103
+ )
104
+ ).reduce(
105
+ (acc, [hash, transaction]) => ({
106
+ ...acc,
107
+ [hash as string]: transaction as TransactionCommon,
108
+ }),
109
+ {} as { [hash: string]: TransactionCommon }
119
110
  );
120
111
 
121
- let r: TransactionHistoryItemI[] = [];
112
+ const decoded = decodeCashAddress(address);
113
+ if (typeof decoded === "string") {
114
+ throw decoded;
115
+ }
122
116
 
123
- let txIds: string[] = [];
117
+ const addressCache: Record<any, string> = {};
124
118
 
125
- for (let input of transaction.inputs) {
126
- let outpoint = inputUtxos[transaction.inputs.indexOf(input)];
119
+ // map decoded transaction data to TransactionHistoryItem
120
+ const historyItems = historicTransactions.map((tx) => {
121
+ const result = {} as TransactionHistoryItem;
127
122
 
128
- // if the utxo of the input matches the address in question
129
- if (binToHex(outpoint.lockingBytecode) === lockingBytecodeHex) {
130
- for (let output of transaction.outputs) {
131
- let idx = transaction.outputs.indexOf(output);
132
- let from = lockingBytecodeToCashAddress(
133
- outpoint.lockingBytecode,
134
- prefix
123
+ let inputTotalValue = 0n;
124
+ let outputTotalValue = 0n;
125
+
126
+ result.inputs = tx.inputs.map((input) => {
127
+ const prevoutTx =
128
+ prevoutTransactionMap[binToHex(input.outpointTransactionHash)];
129
+ if (!prevoutTx) {
130
+ throw new Error("Could not find prevout transaction");
131
+ }
132
+
133
+ const prevoutOutput = prevoutTx.outputs[input.outpointIndex];
134
+ if (!prevoutOutput) {
135
+ throw new Error("Could not find prevout output");
136
+ }
137
+
138
+ const cached = addressCache[prevoutOutput.lockingBytecode as any];
139
+ let address: string;
140
+ if (!cached) {
141
+ address = lockingBytecodeToCashAddress(
142
+ prevoutOutput.lockingBytecode,
143
+ decoded.prefix as CashAddressNetworkPrefix
135
144
  ) as string;
145
+ addressCache[prevoutOutput.lockingBytecode as any] = address;
146
+ } else {
147
+ address = cached;
148
+ }
136
149
 
137
- // the output was change
138
- if (binToHex(output.lockingBytecode) === lockingBytecodeHex) {
139
- if (!collapseChange) {
140
- r.push({
141
- from: from,
142
- to: cashaddr,
143
- unit: "sat",
144
- index: idx,
145
- blockheight: height,
146
- txn: `${hash}`,
147
- txId: `${hash}:i:${idx}`,
148
- value: -Number(output.valueSatoshis),
149
- fee: 0,
150
- });
151
- }
150
+ inputTotalValue += prevoutOutput.valueSatoshis;
151
+
152
+ return {
153
+ address: address,
154
+ value: Number(prevoutOutput.valueSatoshis),
155
+ token: prevoutOutput.token
156
+ ? {
157
+ tokenId: binToHex(prevoutOutput.token.category),
158
+ amount: prevoutOutput.token.amount,
159
+ capability: prevoutOutput.token.nft?.capability
160
+ ? prevoutOutput.token.nft.capability
161
+ : undefined,
162
+ commitment: prevoutOutput.token.nft?.capability
163
+ ? binToHex(prevoutOutput.token.nft.commitment)
164
+ : undefined,
165
+ }
166
+ : undefined,
167
+ } as InOutput;
168
+ });
169
+
170
+ result.outputs = tx.outputs.map((output) => {
171
+ const cached = addressCache[output.lockingBytecode as any];
172
+ let address: string;
173
+ if (!cached) {
174
+ if (output.valueSatoshis === 0n) {
175
+ address = `OP_RETURN: ${binToHex(output.lockingBytecode)}`;
152
176
  } else {
153
- if (!txIds.find((str) => str === `${hash}:i:${idx}`)) {
154
- // the utxo was sent to another address
155
- let to = lockingBytecodeToCashAddress(
156
- output.lockingBytecode,
157
- prefix
158
- ) as string;
159
- r.push({
160
- from: from,
161
- to: to,
162
- unit: "sat",
163
- index: idx,
164
- blockheight: height,
165
- txn: `${hash}`,
166
- txId: `${hash}:i:${idx}`,
167
- value: -Number(output.valueSatoshis),
168
- fee: fee,
169
- });
170
- txIds.push(`${hash}:i:${idx}`);
171
- }
177
+ address = lockingBytecodeToCashAddress(
178
+ output.lockingBytecode,
179
+ decoded.prefix as CashAddressNetworkPrefix
180
+ ) as string;
181
+ addressCache[output.lockingBytecode as any] = address;
172
182
  }
183
+ } else {
184
+ address = cached;
173
185
  }
174
- }
175
- }
176
186
 
177
- // check the transaction outputs for receiving transactions
178
- for (let output of transaction.outputs) {
179
- // the output was a utxo for the address in question
180
- if (binToHex(output.lockingBytecode) === lockingBytecodeHex) {
181
- // the input was from a single address
182
- if (transaction.inputs.length == 1) {
183
- const input = transaction.inputs[0];
184
- const inHash = binToHex(input.outpointTransactionHash);
185
- const transactionHex = await provider.getRawTransaction(inHash);
186
- const inTransaction = decodeTransaction(hexToBin(transactionHex));
187
- if (typeof inTransaction === "string") throw Error(inTransaction);
188
-
189
- let outpoint = inTransaction.outputs[input.outpointIndex];
190
- let from = lockingBytecodeToCashAddress(
191
- outpoint.lockingBytecode,
192
- prefix
193
- ) as string;
187
+ outputTotalValue += output.valueSatoshis;
188
+
189
+ return {
190
+ address: address,
191
+ value: Number(output.valueSatoshis),
192
+ token: output.token
193
+ ? {
194
+ tokenId: binToHex(output.token.category),
195
+ amount: output.token.amount,
196
+ capability: output.token.nft?.capability
197
+ ? output.token.nft.capability
198
+ : undefined,
199
+ commitment: output.token.nft?.capability
200
+ ? binToHex(output.token.nft.commitment)
201
+ : undefined,
202
+ }
203
+ : undefined,
204
+ } as InOutput;
205
+ });
206
+
207
+ result.blockHeight = tx.blockHeight;
208
+ result.timestamp = tx.timestamp;
209
+ result.hash = tx.hash;
210
+ result.size = tx.size;
211
+ result.fee = Number(inputTotalValue - outputTotalValue);
212
+
213
+ return result;
214
+ });
194
215
 
195
- // if the utxo was from a different address and change is not being output...
196
- if (from !== cashaddr || !collapseChange) {
197
- r.push({
198
- from: from,
199
- to: cashaddr,
200
- unit: "sat",
201
- index: transaction.outputs.indexOf(output),
202
- blockheight: height,
203
- txn: `${hash}`,
204
- txId: `${hash}:o:${transaction.outputs.indexOf(output)}`,
205
- value: Number(output.valueSatoshis),
206
- });
216
+ // compute value changes
217
+ historyItems.forEach((tx) => {
218
+ let satoshiBalance = 0;
219
+ const ftTokenBalances: Record<string, bigint> = {};
220
+ const nftTokenBalances: Record<string, bigint> = {};
221
+
222
+ tx.inputs.forEach((input) => {
223
+ if (input.address === address) {
224
+ satoshiBalance -= input.value;
225
+
226
+ if (input.token?.amount) {
227
+ ftTokenBalances[input.token.tokenId] =
228
+ (ftTokenBalances[input.token.tokenId] || BigInt(0)) -
229
+ input.token.amount;
230
+ }
231
+
232
+ if (input.token?.capability) {
233
+ nftTokenBalances[input.token.tokenId] =
234
+ (nftTokenBalances[input.token.tokenId] || BigInt(0)) - 1n;
207
235
  }
236
+ }
237
+ });
238
+ tx.outputs.forEach((output) => {
239
+ if (output.address === address) {
240
+ satoshiBalance += Number(output.value);
241
+
242
+ if (output.token?.amount) {
243
+ ftTokenBalances[output.token.tokenId] =
244
+ (ftTokenBalances[output.token.tokenId] || BigInt(0)) +
245
+ output.token.amount;
246
+ }
247
+
248
+ if (output.token?.capability) {
249
+ nftTokenBalances[output.token.tokenId] =
250
+ (nftTokenBalances[output.token.tokenId] || BigInt(0)) + 1n;
251
+ }
252
+ }
253
+ });
254
+
255
+ tx.valueChange = satoshiBalance;
256
+ tx.tokenAmountChanges = Object.entries(ftTokenBalances).map(
257
+ ([tokenId, amount]) => ({
258
+ tokenId,
259
+ amount,
260
+ nftAmount: BigInt(0),
261
+ })
262
+ );
263
+
264
+ for (const [tokenId, nftAmount] of Object.entries(nftTokenBalances)) {
265
+ const tokenChange = tx.tokenAmountChanges.find(
266
+ (tokenChange) => tokenChange.tokenId === tokenId
267
+ );
268
+ if (tokenChange) {
269
+ tokenChange.nftAmount = nftAmount;
208
270
  } else {
209
- let from = transaction.inputs
210
- .map(
211
- (i) => `${binToHex(i.outpointTransactionHash)}:o:${i.outpointIndex}`
212
- )
213
- .join(";");
214
- r.push({
215
- from: from,
216
- to: cashaddr,
217
- unit: "sat",
218
- index: transaction.outputs.indexOf(output),
219
- blockheight: height,
220
- txn: `${hash}`,
221
- txId: `${hash}:o:${transaction.outputs.indexOf(output)}`,
222
- value: Number(output.valueSatoshis),
223
- // incoming transactions pay no fee.
224
- fee: 0,
271
+ tx.tokenAmountChanges.push({
272
+ tokenId,
273
+ amount: BigInt(0),
274
+ nftAmount,
225
275
  });
226
276
  }
227
277
  }
228
- }
278
+ });
229
279
 
230
- return r;
231
- }
232
-
233
- async function getInputTransactions(
234
- transaction: Transaction,
235
- provider: NetworkProvider
236
- ) {
237
- let inputTransactions: Output[] = [];
238
- for (let input of transaction.inputs) {
239
- let inHash = binToHex(input.outpointTransactionHash);
240
- let transactionHex = await provider.getRawTransaction(inHash);
241
- let inTransaction = decodeTransaction(hexToBin(transactionHex));
242
- if (typeof inTransaction === "string") throw Error(inTransaction);
243
-
244
- inputTransactions.push(inTransaction.outputs[input.outpointIndex]);
245
- }
246
- return inputTransactions;
247
- }
248
-
249
- function getFee(
250
- inputUtxos: Output[],
251
- utxos: Output[],
252
- lockingBytecodeHex,
253
- collapseChange
254
- ) {
255
- let inValues = 0;
256
- for (let outpoint of inputUtxos) {
257
- if (binToHex(outpoint.lockingBytecode)) {
258
- inValues += Number(outpoint.valueSatoshis);
259
- }
260
- }
280
+ // order transactions in a way such that receives are always ordered before sends, per block
281
+ historyItems.sort(
282
+ (a, b) =>
283
+ (a.blockHeight <= 0 || b.blockHeight <= 0
284
+ ? a.blockHeight - b.blockHeight
285
+ : b.blockHeight - a.blockHeight) || a.valueChange - b.valueChange
286
+ );
261
287
 
262
- const outValues = utxos
263
- .map((utxo) => Number(utxo.valueSatoshis))
264
- .reduce((a: number, b: number) => a + b, 0);
265
-
266
- let fee = 0;
267
- if (collapseChange) {
268
- const nonChangeOutputs = utxos
269
- .map((output) =>
270
- binToHex(output.lockingBytecode) === lockingBytecodeHex ? 0 : 1
271
- )
272
- .reduce((a: number, b: number) => a + b, 0);
273
- fee = floor((inValues - outValues) / nonChangeOutputs, 0);
274
- } else {
275
- fee = floor((inValues - outValues) / utxos.length, 0);
276
- }
277
- return fee;
278
- }
279
-
280
- function applyBalance(
281
- preprocessedTxns: TransactionHistoryItemI[],
282
- currentBalance: number,
283
- unit: string,
284
- factor: number
285
- ): TransactionHistoryItemI[] {
286
- // balance in satoshis
287
- let bal = currentBalance;
288
-
289
- let r: TransactionHistoryItemI[] = [];
290
- for (let txn of preprocessedTxns) {
291
- // set the balance to the current balance in the appropriate unit
292
- txn.balance = bal;
293
-
294
- // If fee is not defined, configure it to zero.
295
- txn.fee = txn.fee ? txn.fee : 0;
296
-
297
- // update the running balance in satoshis for the next record
298
- // a receiving value is positive, a send is negative
299
- // The sign is reversed in cronological order from the current balance.
300
- bal -= txn.value;
301
- bal += txn.fee;
302
-
303
- // transform the value of the transaction
304
- txn.value = txn.value * factor;
305
- txn.fee = txn.fee! * factor;
306
-
307
- // If unit is usd, round to two decimal places.
308
- if (unit.toLowerCase() == "usd") {
309
- txn.value = floor(txn.value, 2);
310
- txn.fee = floor(txn.fee, 2);
311
- }
288
+ // backfill the balances
289
+ let prevBalance = await provider.getBalance(address);
290
+ let prevValueChange = 0;
291
+ historyItems.forEach((tx) => {
292
+ tx.balance = prevBalance - prevValueChange;
293
+ prevBalance = tx.balance;
294
+ prevValueChange = tx.valueChange;
295
+ });
296
+
297
+ // convert units if needed
298
+ if (!(unit as string).includes("sat")) {
299
+ for (const tx of historyItems) {
300
+ for (const input of tx.inputs) {
301
+ input.value = await convert(input.value, "sat", unit);
302
+ }
312
303
 
313
- // note the unit
314
- txn.unit = unit as UnitEnum;
304
+ for (const output of tx.outputs) {
305
+ output.value = await convert(output.value, "sat", unit);
306
+ }
315
307
 
316
- r.push(txn);
308
+ tx.valueChange = await convert(tx.valueChange, "sat", unit);
309
+ tx.balance = await convert(tx.balance, "sat", unit);
310
+ }
317
311
  }
318
- return r;
319
- }
312
+
313
+ return historyItems;
314
+ };
@@ -1,18 +1,24 @@
1
- import { UnitEnum } from "../enum.js";
1
+ import { TokenI } from "../interface.js";
2
2
 
3
- export interface TransactionHistoryItemI {
4
- to: string;
5
- from: string;
6
- unit: UnitEnum;
7
- index: number;
8
- blockheight: number;
9
- txn: string;
10
- txId: string;
3
+ export interface InOutput {
4
+ address: string;
11
5
  value: number;
12
- fee?: number;
13
- balance?: number;
6
+ token?: TokenI;
14
7
  }
15
8
 
16
- export interface TransactionHistoryI {
17
- transactions: TransactionHistoryItemI[];
9
+ export interface TransactionHistoryItem {
10
+ inputs: InOutput[];
11
+ outputs: InOutput[];
12
+ blockHeight: number;
13
+ timestamp?: number;
14
+ hash: string;
15
+ size: number;
16
+ fee: number;
17
+ balance: number;
18
+ valueChange: number;
19
+ tokenAmountChanges: {
20
+ tokenId: string;
21
+ amount: bigint;
22
+ nftAmount: bigint;
23
+ }[];
18
24
  }
package/src/interface.ts CHANGED
@@ -35,11 +35,21 @@ export interface TxI {
35
35
  fee?: number;
36
36
  }
37
37
 
38
- export interface HeaderI {
38
+ export interface HexHeaderI {
39
39
  height: number;
40
40
  hex: string;
41
41
  }
42
42
 
43
+ export interface HeaderI {
44
+ version: number;
45
+ previousBlockHash: string;
46
+ merkleRoot: string;
47
+ timestamp: number;
48
+ bits: number;
49
+ nonce: number;
50
+ height: number;
51
+ }
52
+
43
53
  export interface TokenI {
44
54
  amount: bigint;
45
55
  tokenId: string;