@thru/thru-sdk 0.2.0 → 0.2.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/dist/{VersionInfo-Cw5HUNrn.d.ts → VersionInfo-DaC9Se29.d.ts} +15 -0
- package/dist/{chunk-YIQKZL4H.js → chunk-BYQMY4EE.js} +168 -35
- package/dist/chunk-BYQMY4EE.js.map +1 -0
- package/dist/client.d.ts +1 -1
- package/dist/client.js +1 -1
- package/dist/metafile-esm.json +1 -1
- package/dist/sdk.d.ts +2 -2
- package/dist/sdk.js +1 -1
- package/package.json +4 -4
- package/dist/chunk-YIQKZL4H.js.map +0 -1
|
@@ -533,12 +533,27 @@ declare class Block {
|
|
|
533
533
|
});
|
|
534
534
|
static fromProto(proto: Block$1): Block;
|
|
535
535
|
static fromWire(data: Uint8Array): Block;
|
|
536
|
+
private static tryParseWireWithHeaderSize;
|
|
536
537
|
toWire(): Uint8Array;
|
|
537
538
|
getTransactions(): Transaction[];
|
|
538
539
|
private static extractTransactionBody;
|
|
540
|
+
private static extractWithHeaderSize;
|
|
541
|
+
/**
|
|
542
|
+
* Checks if the data looks like a valid transaction body.
|
|
543
|
+
* Uses heuristics to detect if we've correctly offset into the block data.
|
|
544
|
+
* Wire format: header (112 bytes) + body + signature (64 bytes at end)
|
|
545
|
+
* This is a lenient heuristic for format detection - version/flag validation
|
|
546
|
+
* happens in Transaction.parseWire.
|
|
547
|
+
*/
|
|
548
|
+
private static looksLikeValidTransactionBody;
|
|
539
549
|
private serializeHeader;
|
|
540
550
|
private serializeFooter;
|
|
541
551
|
private static parseHeader;
|
|
552
|
+
/**
|
|
553
|
+
* Parses a block header with a specific expected size.
|
|
554
|
+
* Handles both current (168 bytes with weight_slot) and legacy (160 bytes without weight_slot) formats.
|
|
555
|
+
*/
|
|
556
|
+
private static parseHeaderWithSize;
|
|
542
557
|
private static parseFooter;
|
|
543
558
|
private static parseTransactionsFromBody;
|
|
544
559
|
}
|
|
@@ -296,9 +296,10 @@ var SIGNATURE_SIZE2 = 64;
|
|
|
296
296
|
var PUBKEY_SIZE2 = 32;
|
|
297
297
|
var HASH_SIZE = 32;
|
|
298
298
|
var BLOCK_HEADER_SIZE = 168;
|
|
299
|
+
var BLOCK_HEADER_SIZE_LEGACY = 160;
|
|
299
300
|
var BLOCK_FOOTER_SIZE = 104;
|
|
300
301
|
var BLOCK_VERSION_V1 = 1;
|
|
301
|
-
var
|
|
302
|
+
var TXN_HEADER_BODY_SIZE = 112;
|
|
302
303
|
var TXN_VERSION_V1 = 1;
|
|
303
304
|
var TXN_MAX_ACCOUNTS = 1024;
|
|
304
305
|
var STATE_PROOF_HEADER_SIZE = 40;
|
|
@@ -354,11 +355,11 @@ var Transaction = class _Transaction {
|
|
|
354
355
|
return transaction;
|
|
355
356
|
}
|
|
356
357
|
static parseWire(data, options = {}) {
|
|
357
|
-
if (data.length < TXN_HEADER_SIZE + SIGNATURE_SIZE2) {
|
|
358
|
-
throw new Error(`Transaction data too short: ${data.length} bytes (expected at least ${TXN_HEADER_SIZE + SIGNATURE_SIZE2})`);
|
|
359
|
-
}
|
|
360
358
|
const strict = options.strict ?? false;
|
|
361
359
|
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
360
|
+
if (data.length < TXN_HEADER_BODY_SIZE) {
|
|
361
|
+
throw new Error(`Transaction data too short: ${data.length} bytes (minimum ${TXN_HEADER_BODY_SIZE})`);
|
|
362
|
+
}
|
|
362
363
|
let offset = 0;
|
|
363
364
|
const version = view.getUint8(offset);
|
|
364
365
|
offset += 1;
|
|
@@ -400,8 +401,8 @@ var Transaction = class _Transaction {
|
|
|
400
401
|
_Transaction.ensureAvailable(data.length, offset, PUBKEY_SIZE2, "program account");
|
|
401
402
|
const program = data.slice(offset, offset + PUBKEY_SIZE2);
|
|
402
403
|
offset += PUBKEY_SIZE2;
|
|
403
|
-
if (offset !==
|
|
404
|
-
throw new Error(`Transaction header parsing mismatch (expected offset ${
|
|
404
|
+
if (offset !== TXN_HEADER_BODY_SIZE) {
|
|
405
|
+
throw new Error(`Transaction header parsing mismatch (expected offset ${TXN_HEADER_BODY_SIZE}, got ${offset})`);
|
|
405
406
|
}
|
|
406
407
|
const totalAccountCount = Number(readwriteAccountsCount + readonlyAccountsCount);
|
|
407
408
|
if (strict && totalAccountCount > TXN_MAX_ACCOUNTS) {
|
|
@@ -412,7 +413,7 @@ var Transaction = class _Transaction {
|
|
|
412
413
|
const accountsSize = totalAccountCount * PUBKEY_SIZE2;
|
|
413
414
|
let expectedBodySize = accountsSize + instructionDataSize;
|
|
414
415
|
if ((flags & TXN_FLAG_HAS_FEE_PAYER_PROOF) !== 0) {
|
|
415
|
-
const proofOffset =
|
|
416
|
+
const proofOffset = TXN_HEADER_BODY_SIZE + accountsSize + instructionDataSize;
|
|
416
417
|
_Transaction.ensureAvailable(data.length, proofOffset, STATE_PROOF_HEADER_SIZE, "state proof header");
|
|
417
418
|
const proofView = new DataView(data.buffer, data.byteOffset + proofOffset, STATE_PROOF_HEADER_SIZE);
|
|
418
419
|
const typeSlot = proofView.getBigUint64(0, true);
|
|
@@ -426,9 +427,9 @@ var Transaction = class _Transaction {
|
|
|
426
427
|
expectedBodySize += ACCOUNT_META_FOOTPRINT;
|
|
427
428
|
}
|
|
428
429
|
}
|
|
429
|
-
const txnSize =
|
|
430
|
+
const txnSize = TXN_HEADER_BODY_SIZE + expectedBodySize + SIGNATURE_SIZE2;
|
|
430
431
|
_Transaction.ensureAvailable(data.length, 0, txnSize, "full transaction");
|
|
431
|
-
const sigStart =
|
|
432
|
+
const sigStart = TXN_HEADER_BODY_SIZE + expectedBodySize;
|
|
432
433
|
const readWriteAccounts = [];
|
|
433
434
|
for (let i = 0; i < readwriteAccountsCount; i++) {
|
|
434
435
|
_Transaction.ensureAvailable(sigStart, offset, PUBKEY_SIZE2, "read-write accounts");
|
|
@@ -461,7 +462,7 @@ var Transaction = class _Transaction {
|
|
|
461
462
|
}
|
|
462
463
|
if (offset !== sigStart) {
|
|
463
464
|
throw new Error(
|
|
464
|
-
`Transaction body has trailing bytes: expected ${
|
|
465
|
+
`Transaction body has trailing bytes: expected ${sigStart} bytes consumed but found ${offset}`
|
|
465
466
|
);
|
|
466
467
|
}
|
|
467
468
|
const signatureBytes = data.slice(sigStart, sigStart + SIGNATURE_SIZE2);
|
|
@@ -495,7 +496,7 @@ var Transaction = class _Transaction {
|
|
|
495
496
|
if (hasSignature) {
|
|
496
497
|
transaction.setSignature(Signature.from(signatureBytes));
|
|
497
498
|
}
|
|
498
|
-
return { transaction, size:
|
|
499
|
+
return { transaction, size: txnSize };
|
|
499
500
|
}
|
|
500
501
|
static fromProto(proto) {
|
|
501
502
|
if (!proto.header) {
|
|
@@ -524,9 +525,9 @@ var Transaction = class _Transaction {
|
|
|
524
525
|
header.flags ?? DEFAULT_FLAGS
|
|
525
526
|
);
|
|
526
527
|
} catch (sectionErr) {
|
|
527
|
-
if (body.length >=
|
|
528
|
+
if (body.length >= TXN_HEADER_BODY_SIZE) {
|
|
528
529
|
parsed = this.parseBodySections(
|
|
529
|
-
body.slice(
|
|
530
|
+
body.slice(TXN_HEADER_BODY_SIZE),
|
|
530
531
|
header.readwriteAccountsCount ?? 0,
|
|
531
532
|
header.readonlyAccountsCount ?? 0,
|
|
532
533
|
header.instructionDataSize ?? 0,
|
|
@@ -621,7 +622,7 @@ var Transaction = class _Transaction {
|
|
|
621
622
|
return this.buildWirePayload(new Uint8Array(header), true);
|
|
622
623
|
}
|
|
623
624
|
createHeader() {
|
|
624
|
-
const buffer = new ArrayBuffer(
|
|
625
|
+
const buffer = new ArrayBuffer(TXN_HEADER_BODY_SIZE);
|
|
625
626
|
const headerBytes = new Uint8Array(buffer);
|
|
626
627
|
const view = new DataView(buffer);
|
|
627
628
|
let offset = 0;
|
|
@@ -1558,28 +1559,54 @@ var Block = class _Block {
|
|
|
1558
1559
|
return block;
|
|
1559
1560
|
}
|
|
1560
1561
|
static fromWire(data) {
|
|
1561
|
-
|
|
1562
|
-
|
|
1562
|
+
const result = _Block.tryParseWireWithHeaderSize(data, BLOCK_HEADER_SIZE);
|
|
1563
|
+
if (result) {
|
|
1564
|
+
return result;
|
|
1565
|
+
}
|
|
1566
|
+
const legacyResult = _Block.tryParseWireWithHeaderSize(data, BLOCK_HEADER_SIZE_LEGACY);
|
|
1567
|
+
if (legacyResult) {
|
|
1568
|
+
return legacyResult;
|
|
1569
|
+
}
|
|
1570
|
+
throw new Error(`Block data too short: ${data.length} bytes (expected at least ${BLOCK_HEADER_SIZE})`);
|
|
1571
|
+
}
|
|
1572
|
+
static tryParseWireWithHeaderSize(data, headerSize) {
|
|
1573
|
+
if (data.length < headerSize) {
|
|
1574
|
+
return null;
|
|
1575
|
+
}
|
|
1576
|
+
const headerBytes = data.slice(0, headerSize);
|
|
1577
|
+
let header;
|
|
1578
|
+
let blockTimeNs;
|
|
1579
|
+
try {
|
|
1580
|
+
const parsed = this.parseHeaderWithSize(headerBytes, headerSize);
|
|
1581
|
+
header = parsed.header;
|
|
1582
|
+
blockTimeNs = parsed.blockTimeNs;
|
|
1583
|
+
} catch {
|
|
1584
|
+
return null;
|
|
1563
1585
|
}
|
|
1564
|
-
const headerBytes = data.slice(0, BLOCK_HEADER_SIZE);
|
|
1565
|
-
const { header, blockTimeNs } = this.parseHeader(headerBytes);
|
|
1566
1586
|
if (header.version !== BLOCK_VERSION_V1) {
|
|
1567
|
-
|
|
1587
|
+
return null;
|
|
1568
1588
|
}
|
|
1569
1589
|
let finalHeader = header;
|
|
1570
1590
|
let footer;
|
|
1571
1591
|
let footerInfo;
|
|
1572
1592
|
let body;
|
|
1573
|
-
if (data.length >=
|
|
1593
|
+
if (data.length >= headerSize + BLOCK_FOOTER_SIZE) {
|
|
1574
1594
|
const footerOffset = data.length - BLOCK_FOOTER_SIZE;
|
|
1575
1595
|
const footerBytes = data.slice(footerOffset);
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1596
|
+
try {
|
|
1597
|
+
const parsedFooter = this.parseFooter(footerBytes);
|
|
1598
|
+
footer = parsedFooter.footer;
|
|
1599
|
+
footerInfo = { blockHash: parsedFooter.blockHash, attestorPayment: parsedFooter.attestorPayment };
|
|
1600
|
+
finalHeader = header.withBlockHash(parsedFooter.blockHash);
|
|
1601
|
+
} catch {
|
|
1602
|
+
return null;
|
|
1603
|
+
}
|
|
1604
|
+
body = footerOffset > headerSize ? data.slice(headerSize, footerOffset) : void 0;
|
|
1581
1605
|
} else {
|
|
1582
|
-
body = data.length >
|
|
1606
|
+
body = data.length > headerSize ? data.slice(headerSize) : void 0;
|
|
1607
|
+
}
|
|
1608
|
+
if (body && body.length > 0 && !_Block.looksLikeValidTransactionBody(body)) {
|
|
1609
|
+
return null;
|
|
1583
1610
|
}
|
|
1584
1611
|
const block = new _Block({ header: finalHeader, footer, body });
|
|
1585
1612
|
block.blockTimeNs = blockTimeNs;
|
|
@@ -1606,17 +1633,56 @@ var Block = class _Block {
|
|
|
1606
1633
|
return _Block.parseTransactionsFromBody(this.body);
|
|
1607
1634
|
}
|
|
1608
1635
|
static extractTransactionBody(raw, hasFooter) {
|
|
1609
|
-
if (!raw || raw.length
|
|
1610
|
-
return
|
|
1636
|
+
if (!raw || raw.length === 0) {
|
|
1637
|
+
return void 0;
|
|
1638
|
+
}
|
|
1639
|
+
const bodyWithCurrentHeader = _Block.extractWithHeaderSize(raw, hasFooter, BLOCK_HEADER_SIZE);
|
|
1640
|
+
if (bodyWithCurrentHeader && bodyWithCurrentHeader.length > 0 && _Block.looksLikeValidTransactionBody(bodyWithCurrentHeader)) {
|
|
1641
|
+
return bodyWithCurrentHeader;
|
|
1611
1642
|
}
|
|
1612
|
-
const
|
|
1613
|
-
|
|
1643
|
+
const bodyWithLegacyHeader = _Block.extractWithHeaderSize(raw, hasFooter, BLOCK_HEADER_SIZE_LEGACY);
|
|
1644
|
+
if (bodyWithLegacyHeader && bodyWithLegacyHeader.length > 0 && _Block.looksLikeValidTransactionBody(bodyWithLegacyHeader)) {
|
|
1645
|
+
return bodyWithLegacyHeader;
|
|
1646
|
+
}
|
|
1647
|
+
return void 0;
|
|
1648
|
+
}
|
|
1649
|
+
static extractWithHeaderSize(raw, hasFooter, headerSize) {
|
|
1650
|
+
if (raw.length <= headerSize) {
|
|
1651
|
+
return void 0;
|
|
1652
|
+
}
|
|
1653
|
+
const footerSize = hasFooter && raw.length >= headerSize + BLOCK_FOOTER_SIZE ? BLOCK_FOOTER_SIZE : 0;
|
|
1654
|
+
const start = headerSize;
|
|
1614
1655
|
const end = Math.max(start, raw.length - footerSize);
|
|
1615
1656
|
if (end <= start) {
|
|
1616
1657
|
return void 0;
|
|
1617
1658
|
}
|
|
1618
1659
|
return raw.slice(start, end);
|
|
1619
1660
|
}
|
|
1661
|
+
/**
|
|
1662
|
+
* Checks if the data looks like a valid transaction body.
|
|
1663
|
+
* Uses heuristics to detect if we've correctly offset into the block data.
|
|
1664
|
+
* Wire format: header (112 bytes) + body + signature (64 bytes at end)
|
|
1665
|
+
* This is a lenient heuristic for format detection - version/flag validation
|
|
1666
|
+
* happens in Transaction.parseWire.
|
|
1667
|
+
*/
|
|
1668
|
+
static looksLikeValidTransactionBody(data) {
|
|
1669
|
+
const MIN_TXN_SIZE = TXN_HEADER_BODY_SIZE + SIGNATURE_SIZE2;
|
|
1670
|
+
if (data.length < MIN_TXN_SIZE) {
|
|
1671
|
+
return false;
|
|
1672
|
+
}
|
|
1673
|
+
const readwriteCount = data[2] | data[3] << 8;
|
|
1674
|
+
const readonlyCount = data[4] | data[5] << 8;
|
|
1675
|
+
const totalAccounts = readwriteCount + readonlyCount;
|
|
1676
|
+
if (totalAccounts > 1024) {
|
|
1677
|
+
return false;
|
|
1678
|
+
}
|
|
1679
|
+
const instrDataSize = data[6] | data[7] << 8;
|
|
1680
|
+
const expectedMinSize = TXN_HEADER_BODY_SIZE + totalAccounts * PUBKEY_SIZE2 + instrDataSize + SIGNATURE_SIZE2;
|
|
1681
|
+
if (data.length < expectedMinSize) {
|
|
1682
|
+
return false;
|
|
1683
|
+
}
|
|
1684
|
+
return true;
|
|
1685
|
+
}
|
|
1620
1686
|
serializeHeader() {
|
|
1621
1687
|
const buffer = new ArrayBuffer(BLOCK_HEADER_SIZE);
|
|
1622
1688
|
const bytes = new Uint8Array(buffer);
|
|
@@ -1721,6 +1787,66 @@ var Block = class _Block {
|
|
|
1721
1787
|
});
|
|
1722
1788
|
return { header, blockTimeNs };
|
|
1723
1789
|
}
|
|
1790
|
+
/**
|
|
1791
|
+
* Parses a block header with a specific expected size.
|
|
1792
|
+
* Handles both current (168 bytes with weight_slot) and legacy (160 bytes without weight_slot) formats.
|
|
1793
|
+
*/
|
|
1794
|
+
static parseHeaderWithSize(bytes, expectedSize) {
|
|
1795
|
+
if (bytes.length !== expectedSize) {
|
|
1796
|
+
throw new Error(`Invalid block header size: ${bytes.length}, expected ${expectedSize}`);
|
|
1797
|
+
}
|
|
1798
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
1799
|
+
let offset = 0;
|
|
1800
|
+
const signature = bytes.slice(offset, offset + SIGNATURE_SIZE2);
|
|
1801
|
+
offset += SIGNATURE_SIZE2;
|
|
1802
|
+
const version = view.getUint8(offset);
|
|
1803
|
+
offset += 1;
|
|
1804
|
+
offset += 5;
|
|
1805
|
+
const chainId = view.getUint16(offset, true);
|
|
1806
|
+
offset += 2;
|
|
1807
|
+
const producer = bytes.slice(offset, offset + PUBKEY_SIZE2);
|
|
1808
|
+
offset += PUBKEY_SIZE2;
|
|
1809
|
+
const bondAmountLockUp = view.getBigUint64(offset, true);
|
|
1810
|
+
offset += 8;
|
|
1811
|
+
const expiryTimestampNs = view.getBigUint64(offset, true);
|
|
1812
|
+
offset += 8;
|
|
1813
|
+
const startSlot = view.getBigUint64(offset, true);
|
|
1814
|
+
offset += 8;
|
|
1815
|
+
const expiryAfter = view.getUint32(offset, true);
|
|
1816
|
+
offset += 4;
|
|
1817
|
+
const maxBlockSize = view.getUint32(offset, true);
|
|
1818
|
+
offset += 4;
|
|
1819
|
+
const maxComputeUnits = view.getBigUint64(offset, true);
|
|
1820
|
+
offset += 8;
|
|
1821
|
+
const maxStateUnits = view.getUint32(offset, true);
|
|
1822
|
+
offset += 4;
|
|
1823
|
+
offset += 4;
|
|
1824
|
+
let weightSlot;
|
|
1825
|
+
let blockTimeNs;
|
|
1826
|
+
if (expectedSize === BLOCK_HEADER_SIZE) {
|
|
1827
|
+
weightSlot = view.getBigUint64(offset, true);
|
|
1828
|
+
offset += 8;
|
|
1829
|
+
blockTimeNs = view.getBigUint64(offset, true);
|
|
1830
|
+
} else {
|
|
1831
|
+
blockTimeNs = view.getBigUint64(offset, true);
|
|
1832
|
+
}
|
|
1833
|
+
const header = new BlockHeader({
|
|
1834
|
+
slot: startSlot,
|
|
1835
|
+
version,
|
|
1836
|
+
headerSignature: signature,
|
|
1837
|
+
producer,
|
|
1838
|
+
expiryTimestamp: nanosecondsToTimestamp(expiryTimestampNs),
|
|
1839
|
+
startSlot,
|
|
1840
|
+
expiryAfter,
|
|
1841
|
+
maxBlockSize,
|
|
1842
|
+
maxComputeUnits,
|
|
1843
|
+
maxStateUnits,
|
|
1844
|
+
bondAmountLockUp,
|
|
1845
|
+
weightSlot,
|
|
1846
|
+
chainId
|
|
1847
|
+
});
|
|
1848
|
+
return { header, blockTimeNs };
|
|
1849
|
+
}
|
|
1724
1850
|
static parseFooter(bytes) {
|
|
1725
1851
|
if (bytes.length !== BLOCK_FOOTER_SIZE) {
|
|
1726
1852
|
throw new Error(`Invalid block footer size: ${bytes.length}`);
|
|
@@ -1746,9 +1872,16 @@ var Block = class _Block {
|
|
|
1746
1872
|
let offset = 0;
|
|
1747
1873
|
while (offset < body.length) {
|
|
1748
1874
|
const slice = body.subarray(offset);
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1875
|
+
if (slice.length < 176) {
|
|
1876
|
+
break;
|
|
1877
|
+
}
|
|
1878
|
+
try {
|
|
1879
|
+
const { transaction, size } = Transaction.parseWire(slice);
|
|
1880
|
+
transactions.push(transaction);
|
|
1881
|
+
offset += size;
|
|
1882
|
+
} catch {
|
|
1883
|
+
break;
|
|
1884
|
+
}
|
|
1752
1885
|
}
|
|
1753
1886
|
return transactions;
|
|
1754
1887
|
}
|
|
@@ -2932,5 +3065,5 @@ var VersionInfo = class _VersionInfo {
|
|
|
2932
3065
|
};
|
|
2933
3066
|
|
|
2934
3067
|
export { Account, Block, ChainEvent, Filter, FilterParamValue, HeightSnapshot, PageRequest, PageResponse, Pubkey, Signature, SignatureDomain, StateProof, Transaction, TransactionBuilder, TransactionStatusSnapshot, VersionInfo, accounts_exports, batchSendTransactions, blocks_exports, buildAndSignTransaction, buildTransaction, chain_exports, collectStream, consensusStatusToString, consensus_exports, createAccount, createThruClientContext, currentOrHistoricalVersionContext, currentVersionContext, deriveAddress, deriveProgramAddress, events_exports, firstStreamValue, forEachStreamValue, fromPrivateKey, generateKeyPair, generateStateProof, getAccount, getBlock, getBlockHeight, getEvent, getRawAccount, getRawBlock, getRawTransaction, getTransaction, getTransactionStatus, height_exports, keys_exports, listAccounts, listBlocks, listEvents, listTransactions, listTransactionsForAccount, proofs_exports, sendTransaction, seqVersionContext, signWithDomain, slotVersionContext, streamAccountUpdates, streamBlocks, streamEvents, streamHeight, streamTransactions, streaming_exports, timestampVersionContext, trackTransaction, transactions_exports, verifyWithDomain, versionContext, withCallOptions };
|
|
2935
|
-
//# sourceMappingURL=chunk-
|
|
2936
|
-
//# sourceMappingURL=chunk-
|
|
3068
|
+
//# sourceMappingURL=chunk-BYQMY4EE.js.map
|
|
3069
|
+
//# sourceMappingURL=chunk-BYQMY4EE.js.map
|