@ckb-ccc/core 1.16.1 → 1.18.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/CHANGELOG.md +53 -0
- package/dist/address.advanced-Dw4qPDGb.mjs +2 -0
- package/dist/address.advanced-Dw4qPDGb.mjs.map +1 -0
- package/dist/advanced.d.mts +1 -1
- package/dist/advanced.mjs +1 -1
- package/{dist.commonjs/advancedBarrel-CiJnF8me.d.ts → dist/advancedBarrel-BbbHx4z4.d.mts} +1188 -163
- package/dist/advancedBarrel-BbbHx4z4.d.mts.map +1 -0
- package/dist/advancedBarrel.d.mts +1 -1
- package/dist/advancedBarrel.mjs +1 -1
- package/dist/barrel-BqMBxl8y.mjs +7 -0
- package/dist/barrel-BqMBxl8y.mjs.map +1 -0
- package/dist/barrel.d.mts +2 -2
- package/dist/barrel.mjs +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +1 -1
- package/dist.commonjs/address.advanced-DG1gpW7t.js +2 -0
- package/dist.commonjs/address.advanced-DG1gpW7t.js.map +1 -0
- package/dist.commonjs/advanced.d.ts +1 -1
- package/dist.commonjs/advanced.js +1 -1
- package/{dist/advancedBarrel-66JgvInl.d.mts → dist.commonjs/advancedBarrel-CJAh6sm8.d.ts} +1189 -162
- package/dist.commonjs/advancedBarrel-CJAh6sm8.d.ts.map +1 -0
- package/dist.commonjs/advancedBarrel.d.ts +1 -1
- package/dist.commonjs/advancedBarrel.js +1 -1
- package/dist.commonjs/barrel-CbH8-KWr.js +21 -0
- package/dist.commonjs/barrel-CbH8-KWr.js.map +1 -0
- package/dist.commonjs/barrel.d.ts +2 -2
- package/dist.commonjs/barrel.js +1 -1
- package/dist.commonjs/index.d.ts +2 -2
- package/dist.commonjs/index.js +1 -1
- package/dist.commonjs/rolldown-runtime-DWNI8pZO.js +1 -0
- package/package.json +4 -3
- package/src/ckb/transaction.ts +275 -55
- package/src/client/jsonRpc/client.ts +7 -3
- package/src/codec/entity.ts +93 -0
- package/src/jsonRpc/requestor.ts +9 -4
- package/src/jsonRpc/transports/fallback.ts +14 -11
- package/src/molecule/codec.ts +25 -5
- package/src/signer/btc/signerBtc.ts +1 -1
- package/src/signer/ckb/index.ts +1 -0
- package/src/signer/ckb/signerCkbAlwaysSuccess.ts +71 -0
- package/src/signer/ckb/signerCkbPrivateKey.ts +2 -3
- package/src/signer/ckb/signerMultisigCkbReadonly.ts +5 -5
- package/src/signer/doge/signerDoge.ts +1 -1
- package/src/signer/evm/signerEvm.ts +2 -2
- package/src/signer/nostr/signerNostr.ts +1 -1
- package/dist/address.advanced-C5UrS2uk.mjs +0 -2
- package/dist/address.advanced-C5UrS2uk.mjs.map +0 -1
- package/dist/advancedBarrel-66JgvInl.d.mts.map +0 -1
- package/dist/barrel-yZm3ICzn.mjs +0 -7
- package/dist/barrel-yZm3ICzn.mjs.map +0 -1
- package/dist.commonjs/address.advanced-CQJ24Iei.js +0 -2
- package/dist.commonjs/address.advanced-CQJ24Iei.js.map +0 -1
- package/dist.commonjs/advancedBarrel-CiJnF8me.d.ts.map +0 -1
- package/dist.commonjs/barrel-CddEgDBp.js +0 -21
- package/dist.commonjs/barrel-CddEgDBp.js.map +0 -1
package/src/ckb/transaction.ts
CHANGED
|
@@ -32,6 +32,30 @@ import {
|
|
|
32
32
|
} from "./transactionErrors.js";
|
|
33
33
|
import type { LumosTransactionSkeletonType } from "./transactionLumos.js";
|
|
34
34
|
|
|
35
|
+
const MAX_ARRAY_INDEX = 2n ** 32n - 2n;
|
|
36
|
+
|
|
37
|
+
function transactionIndexFrom(index: NumLike): number | undefined {
|
|
38
|
+
try {
|
|
39
|
+
const value = numFrom(index);
|
|
40
|
+
if (value < 0n || value > MAX_ARRAY_INDEX) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
return Number(value);
|
|
44
|
+
} catch (_) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function transactionIndexOrThrow(index: number): number {
|
|
50
|
+
const value = transactionIndexFrom(index);
|
|
51
|
+
if (value === undefined) {
|
|
52
|
+
throw new Error(
|
|
53
|
+
`Index ${index} must be a valid array index between 0 and ${MAX_ARRAY_INDEX}`,
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
return value;
|
|
57
|
+
}
|
|
58
|
+
|
|
35
59
|
export const DepTypeCodec: Codec<DepTypeLike, DepType> = Codec.from({
|
|
36
60
|
byteLength: 1,
|
|
37
61
|
encode: depTypeToBytes,
|
|
@@ -1169,6 +1193,10 @@ export class Transaction extends Entity.Base<TransactionLike, Transaction>() {
|
|
|
1169
1193
|
* ```
|
|
1170
1194
|
*/
|
|
1171
1195
|
copy(txLike: TransactionLike) {
|
|
1196
|
+
if (txLike === this) {
|
|
1197
|
+
return;
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1172
1200
|
const tx = Transaction.from(txLike);
|
|
1173
1201
|
this.version = tx.version;
|
|
1174
1202
|
this.cellDeps = tx.cellDeps;
|
|
@@ -1620,41 +1648,75 @@ export class Transaction extends Entity.Base<TransactionLike, Transaction>() {
|
|
|
1620
1648
|
}
|
|
1621
1649
|
|
|
1622
1650
|
/**
|
|
1623
|
-
*
|
|
1651
|
+
* Sets output data at an index.
|
|
1652
|
+
*
|
|
1653
|
+
* @deprecated Use {@link setOutputData} instead.
|
|
1654
|
+
*/
|
|
1655
|
+
setOutputDataAt(index: number, data: HexLike): void {
|
|
1656
|
+
this.setOutputData(index, data);
|
|
1657
|
+
}
|
|
1658
|
+
|
|
1659
|
+
/**
|
|
1660
|
+
* Sets output data at an index, filling any skipped positions with empty data.
|
|
1624
1661
|
*
|
|
1625
1662
|
* @param index - The index of the output data.
|
|
1626
1663
|
* @param data - The data to set.
|
|
1664
|
+
* @throws If `index` is invalid or does not identify an existing output.
|
|
1627
1665
|
*
|
|
1628
1666
|
* @example
|
|
1629
1667
|
* ```typescript
|
|
1630
|
-
* tx.
|
|
1668
|
+
* tx.setOutputData(0, "0x00");
|
|
1631
1669
|
* ```
|
|
1632
1670
|
*/
|
|
1633
|
-
|
|
1634
|
-
|
|
1671
|
+
setOutputData(index: number, data: HexLike): void {
|
|
1672
|
+
const i = transactionIndexOrThrow(index);
|
|
1673
|
+
if (i >= this.outputs.length) {
|
|
1674
|
+
throw new Error(
|
|
1675
|
+
`Index ${index} is out of bounds for outputs of length ${this.outputs.length}`,
|
|
1676
|
+
);
|
|
1677
|
+
}
|
|
1678
|
+
|
|
1679
|
+
if (this.outputsData.length < i) {
|
|
1635
1680
|
this.outputsData.push(
|
|
1636
|
-
...Array.from(
|
|
1637
|
-
new Array(index - this.outputsData.length),
|
|
1638
|
-
(): Hex => "0x",
|
|
1639
|
-
),
|
|
1681
|
+
...Array.from(new Array(i - this.outputsData.length), (): Hex => "0x"),
|
|
1640
1682
|
);
|
|
1641
1683
|
}
|
|
1642
1684
|
|
|
1643
|
-
this.outputsData[
|
|
1685
|
+
this.outputsData[i] = hexFrom(data);
|
|
1686
|
+
}
|
|
1687
|
+
|
|
1688
|
+
/**
|
|
1689
|
+
* Gets the data associated with an output.
|
|
1690
|
+
*
|
|
1691
|
+
* @param index - The output index.
|
|
1692
|
+
* @returns The output data, or `undefined` if the index is invalid or out of bounds.
|
|
1693
|
+
*
|
|
1694
|
+
* @example
|
|
1695
|
+
* ```typescript
|
|
1696
|
+
* const data = tx.getOutputData(0);
|
|
1697
|
+
* ```
|
|
1698
|
+
*/
|
|
1699
|
+
getOutputData(index: NumLike): Hex | undefined {
|
|
1700
|
+
const i = transactionIndexFrom(index);
|
|
1701
|
+
return i !== undefined && i < this.outputs.length
|
|
1702
|
+
? (this.outputsData[i] ?? "0x")
|
|
1703
|
+
: undefined;
|
|
1644
1704
|
}
|
|
1645
1705
|
|
|
1646
1706
|
/**
|
|
1647
|
-
*
|
|
1707
|
+
* Gets an input.
|
|
1648
1708
|
*
|
|
1649
|
-
* @param index - The cell input index
|
|
1709
|
+
* @param index - The cell input index.
|
|
1710
|
+
* @returns The input, or `undefined` if the index is invalid or out of bounds.
|
|
1650
1711
|
*
|
|
1651
1712
|
* @example
|
|
1652
1713
|
* ```typescript
|
|
1653
|
-
*
|
|
1714
|
+
* tx.getInput(0);
|
|
1654
1715
|
* ```
|
|
1655
1716
|
*/
|
|
1656
1717
|
getInput(index: NumLike): CellInput | undefined {
|
|
1657
|
-
|
|
1718
|
+
const i = transactionIndexFrom(index);
|
|
1719
|
+
return i === undefined ? undefined : this.inputs[i];
|
|
1658
1720
|
}
|
|
1659
1721
|
/**
|
|
1660
1722
|
* add input
|
|
@@ -1675,18 +1737,19 @@ export class Transaction extends Entity.Base<TransactionLike, Transaction>() {
|
|
|
1675
1737
|
}
|
|
1676
1738
|
|
|
1677
1739
|
/**
|
|
1678
|
-
*
|
|
1740
|
+
* Gets an output cell together with its data.
|
|
1679
1741
|
*
|
|
1680
|
-
* @param index - The cell output index
|
|
1742
|
+
* @param index - The cell output index.
|
|
1743
|
+
* @returns The output cell, or `undefined` if the index is invalid or out of bounds.
|
|
1681
1744
|
*
|
|
1682
1745
|
* @example
|
|
1683
1746
|
* ```typescript
|
|
1684
|
-
*
|
|
1747
|
+
* tx.getOutput(0);
|
|
1685
1748
|
* ```
|
|
1686
1749
|
*/
|
|
1687
1750
|
getOutput(index: NumLike): CellAny | undefined {
|
|
1688
|
-
const i =
|
|
1689
|
-
if (i >= this.outputs.length) {
|
|
1751
|
+
const i = transactionIndexFrom(index);
|
|
1752
|
+
if (i === undefined || i >= this.outputs.length) {
|
|
1690
1753
|
return;
|
|
1691
1754
|
}
|
|
1692
1755
|
return CellAny.from({
|
|
@@ -1769,85 +1832,238 @@ export class Transaction extends Entity.Base<TransactionLike, Transaction>() {
|
|
|
1769
1832
|
});
|
|
1770
1833
|
|
|
1771
1834
|
const len = this.outputs.push(cell.cellOutput);
|
|
1772
|
-
this.
|
|
1835
|
+
this.setOutputData(len - 1, cell.outputData);
|
|
1773
1836
|
|
|
1774
1837
|
return len;
|
|
1775
1838
|
}
|
|
1776
1839
|
|
|
1777
1840
|
/**
|
|
1778
|
-
*
|
|
1841
|
+
* Sets or appends an output cell.
|
|
1842
|
+
*
|
|
1843
|
+
* An index equal to the current output count appends the cell. Existing
|
|
1844
|
+
* outputs are replaced together with their corresponding output data.
|
|
1845
|
+
*
|
|
1846
|
+
* @param index - The output index to set, from zero through the current output count.
|
|
1847
|
+
* @param cellLike - A cell-like object containing both the output and its data.
|
|
1848
|
+
* @throws If `index` is not a valid array index or is greater than the output count.
|
|
1849
|
+
*
|
|
1850
|
+
* @example
|
|
1851
|
+
* ```typescript
|
|
1852
|
+
* tx.setOutput(0, {
|
|
1853
|
+
* cellOutput: { lock: recipientLock },
|
|
1854
|
+
* outputData: "0x1234",
|
|
1855
|
+
* });
|
|
1856
|
+
* ```
|
|
1857
|
+
*/
|
|
1858
|
+
setOutput(index: number, cellLike: CellAnyLike): void;
|
|
1859
|
+
|
|
1860
|
+
/**
|
|
1861
|
+
* Sets or appends an output and its data.
|
|
1862
|
+
*
|
|
1863
|
+
* @param index - The output index to set, from zero through the current output count.
|
|
1864
|
+
* @param outputLike - The cell output to set.
|
|
1865
|
+
* @param outputDataLike - The output data, defaulting to `"0x"`.
|
|
1866
|
+
* @throws If `index` is not a valid array index or is greater than the output count.
|
|
1867
|
+
*
|
|
1868
|
+
* @example
|
|
1869
|
+
* ```typescript
|
|
1870
|
+
* tx.setOutput(0, { lock: recipientLock }, "0x1234");
|
|
1871
|
+
* ```
|
|
1872
|
+
*/
|
|
1873
|
+
setOutput(
|
|
1874
|
+
index: number,
|
|
1875
|
+
outputLike: CellOutputLike,
|
|
1876
|
+
outputDataLike?: HexLike | null,
|
|
1877
|
+
): void;
|
|
1878
|
+
setOutput(
|
|
1879
|
+
index: number,
|
|
1880
|
+
cellOrOutputLike: CellAnyLike | CellOutputLike,
|
|
1881
|
+
outputDataLike?: HexLike | null,
|
|
1882
|
+
): void {
|
|
1883
|
+
const i = transactionIndexOrThrow(index);
|
|
1884
|
+
if (i > this.outputs.length) {
|
|
1885
|
+
throw new Error(
|
|
1886
|
+
`Index ${index} is out of bounds for outputs of length ${this.outputs.length}`,
|
|
1887
|
+
);
|
|
1888
|
+
}
|
|
1889
|
+
|
|
1890
|
+
const cell =
|
|
1891
|
+
"cellOutput" in cellOrOutputLike
|
|
1892
|
+
? CellAny.from(cellOrOutputLike)
|
|
1893
|
+
: CellAny.from({
|
|
1894
|
+
cellOutput: cellOrOutputLike,
|
|
1895
|
+
outputData: outputDataLike,
|
|
1896
|
+
});
|
|
1897
|
+
|
|
1898
|
+
if (i === this.outputs.length) {
|
|
1899
|
+
this.addOutput(cell);
|
|
1900
|
+
} else {
|
|
1901
|
+
this.outputs[i] = cell.cellOutput;
|
|
1902
|
+
this.setOutputData(i, cell.outputData);
|
|
1903
|
+
}
|
|
1904
|
+
}
|
|
1905
|
+
|
|
1906
|
+
/**
|
|
1907
|
+
* Sets or appends an input.
|
|
1908
|
+
*
|
|
1909
|
+
* An index equal to the current input count appends the input using
|
|
1910
|
+
* {@link addInput}, preserving witness alignment. An existing index replaces
|
|
1911
|
+
* only that input.
|
|
1912
|
+
*
|
|
1913
|
+
* @param index - The input index to set, from zero through the current input count.
|
|
1914
|
+
* @param inputLike - The cell input to set.
|
|
1915
|
+
* @throws If `index` is not a valid array index or is greater than the input count.
|
|
1916
|
+
*
|
|
1917
|
+
* @example
|
|
1918
|
+
* ```typescript
|
|
1919
|
+
* tx.setInput(0, {
|
|
1920
|
+
* previousOutput: { txHash: "0x...", index: 0 },
|
|
1921
|
+
* });
|
|
1922
|
+
* ```
|
|
1923
|
+
*/
|
|
1924
|
+
setInput(index: number, inputLike: CellInputLike): void {
|
|
1925
|
+
const i = transactionIndexOrThrow(index);
|
|
1926
|
+
if (i > this.inputs.length) {
|
|
1927
|
+
throw new Error(
|
|
1928
|
+
`Index ${index} is out of bounds for inputs of length ${this.inputs.length}`,
|
|
1929
|
+
);
|
|
1930
|
+
}
|
|
1931
|
+
|
|
1932
|
+
if (i === this.inputs.length) {
|
|
1933
|
+
this.addInput(inputLike);
|
|
1934
|
+
} else {
|
|
1935
|
+
this.inputs[i] = CellInput.from(inputLike);
|
|
1936
|
+
}
|
|
1937
|
+
}
|
|
1938
|
+
|
|
1939
|
+
/**
|
|
1940
|
+
* Gets a raw witness.
|
|
1941
|
+
*
|
|
1942
|
+
* @param index - The witness index.
|
|
1943
|
+
* @returns The witness, or `undefined` if the index is invalid or out of bounds.
|
|
1944
|
+
*
|
|
1945
|
+
* @example
|
|
1946
|
+
* ```typescript
|
|
1947
|
+
* const witness = tx.getWitness(0);
|
|
1948
|
+
* ```
|
|
1949
|
+
*/
|
|
1950
|
+
getWitness(index: NumLike): Hex | undefined {
|
|
1951
|
+
const i = transactionIndexFrom(index);
|
|
1952
|
+
return i === undefined ? undefined : this.witnesses[i];
|
|
1953
|
+
}
|
|
1954
|
+
|
|
1955
|
+
/**
|
|
1956
|
+
* Gets the witness at an index as `WitnessArgs`.
|
|
1779
1957
|
*
|
|
1780
1958
|
* @param index - The index of the witness.
|
|
1781
1959
|
* @returns The witness parsed as WitnessArgs.
|
|
1782
1960
|
*
|
|
1783
1961
|
* @example
|
|
1784
1962
|
* ```typescript
|
|
1785
|
-
* const witnessArgs = tx.
|
|
1963
|
+
* const witnessArgs = tx.getWitnessArgs(0);
|
|
1786
1964
|
* ```
|
|
1787
1965
|
*/
|
|
1788
|
-
|
|
1966
|
+
getWitnessArgs(index: NumLike): WitnessArgs | undefined {
|
|
1789
1967
|
try {
|
|
1790
|
-
return this.
|
|
1968
|
+
return this.getWitnessArgsUnsafe(index);
|
|
1791
1969
|
} catch (_) {
|
|
1792
1970
|
return undefined;
|
|
1793
1971
|
}
|
|
1794
1972
|
}
|
|
1795
1973
|
|
|
1796
1974
|
/**
|
|
1797
|
-
*
|
|
1975
|
+
* Gets the witness at an index as `WitnessArgs`, throwing if decoding fails.
|
|
1798
1976
|
*
|
|
1799
1977
|
* @param index - The index of the witness.
|
|
1800
1978
|
* @returns The witness parsed as WitnessArgs.
|
|
1979
|
+
* @throws If the witness cannot be decoded as `WitnessArgs`.
|
|
1801
1980
|
*
|
|
1802
1981
|
* @example
|
|
1803
1982
|
* ```typescript
|
|
1804
|
-
* const witnessArgs = tx.
|
|
1983
|
+
* const witnessArgs = tx.getWitnessArgsUnsafe(0);
|
|
1805
1984
|
* ```
|
|
1806
1985
|
*/
|
|
1807
|
-
|
|
1808
|
-
const rawWitness = this.
|
|
1809
|
-
return
|
|
1986
|
+
getWitnessArgsUnsafe(index: NumLike): WitnessArgs | undefined {
|
|
1987
|
+
const rawWitness = this.getWitness(index);
|
|
1988
|
+
return rawWitness && rawWitness !== "0x"
|
|
1810
1989
|
? WitnessArgs.fromBytes(rawWitness)
|
|
1811
1990
|
: undefined;
|
|
1812
1991
|
}
|
|
1813
1992
|
|
|
1814
1993
|
/**
|
|
1815
|
-
*
|
|
1994
|
+
* Sets a witness at an index from `WitnessArgs`.
|
|
1816
1995
|
*
|
|
1817
1996
|
* @param index - The index of the witness.
|
|
1818
|
-
* @param
|
|
1997
|
+
* @param witnessLike - The WitnessArgs-like value to set.
|
|
1998
|
+
* @throws If `index` is not a valid array index.
|
|
1819
1999
|
*
|
|
1820
2000
|
* @example
|
|
1821
2001
|
* ```typescript
|
|
1822
|
-
*
|
|
2002
|
+
* tx.setWitnessArgs(0, witnessArgs);
|
|
1823
2003
|
* ```
|
|
1824
2004
|
*/
|
|
1825
|
-
|
|
1826
|
-
this.
|
|
2005
|
+
setWitnessArgs(index: number, witnessLike: WitnessArgsLike): void {
|
|
2006
|
+
this.setWitness(index, WitnessArgs.from(witnessLike).toBytes());
|
|
1827
2007
|
}
|
|
1828
2008
|
|
|
1829
2009
|
/**
|
|
1830
|
-
*
|
|
2010
|
+
* Sets a witness at an index, filling any skipped positions with empty witnesses.
|
|
1831
2011
|
*
|
|
1832
2012
|
* @param index - The index of the witness.
|
|
1833
2013
|
* @param witness - The witness to set.
|
|
2014
|
+
* @throws If `index` is not a valid array index.
|
|
1834
2015
|
*
|
|
1835
2016
|
* @example
|
|
1836
2017
|
* ```typescript
|
|
1837
|
-
*
|
|
2018
|
+
* tx.setWitness(0, witness);
|
|
1838
2019
|
* ```
|
|
1839
2020
|
*/
|
|
1840
|
-
|
|
1841
|
-
|
|
2021
|
+
setWitness(index: number, witness: HexLike): void {
|
|
2022
|
+
const i = transactionIndexOrThrow(index);
|
|
2023
|
+
|
|
2024
|
+
if (this.witnesses.length < i) {
|
|
1842
2025
|
this.witnesses.push(
|
|
1843
|
-
...Array.from(
|
|
1844
|
-
new Array(index - this.witnesses.length),
|
|
1845
|
-
(): Hex => "0x",
|
|
1846
|
-
),
|
|
2026
|
+
...Array.from(new Array(i - this.witnesses.length), (): Hex => "0x"),
|
|
1847
2027
|
);
|
|
1848
2028
|
}
|
|
1849
2029
|
|
|
1850
|
-
this.witnesses[
|
|
2030
|
+
this.witnesses[i] = hexFrom(witness);
|
|
2031
|
+
}
|
|
2032
|
+
|
|
2033
|
+
/**
|
|
2034
|
+
* Gets the witness at an index as `WitnessArgs`.
|
|
2035
|
+
*
|
|
2036
|
+
* @deprecated Use {@link getWitnessArgs} instead.
|
|
2037
|
+
*/
|
|
2038
|
+
getWitnessArgsAt(index: NumLike): WitnessArgs | undefined {
|
|
2039
|
+
return this.getWitnessArgs(index);
|
|
2040
|
+
}
|
|
2041
|
+
|
|
2042
|
+
/**
|
|
2043
|
+
* Gets the witness at an index as `WitnessArgs`, throwing if decoding fails.
|
|
2044
|
+
*
|
|
2045
|
+
* @deprecated Use {@link getWitnessArgsUnsafe} instead.
|
|
2046
|
+
*/
|
|
2047
|
+
getWitnessArgsAtUnsafe(index: NumLike): WitnessArgs | undefined {
|
|
2048
|
+
return this.getWitnessArgsUnsafe(index);
|
|
2049
|
+
}
|
|
2050
|
+
|
|
2051
|
+
/**
|
|
2052
|
+
* Sets a witness at an index from `WitnessArgs`.
|
|
2053
|
+
*
|
|
2054
|
+
* @deprecated Use {@link setWitnessArgs} instead.
|
|
2055
|
+
*/
|
|
2056
|
+
setWitnessArgsAt(index: number, witnessLike: WitnessArgsLike): void {
|
|
2057
|
+
this.setWitnessArgs(index, witnessLike);
|
|
2058
|
+
}
|
|
2059
|
+
|
|
2060
|
+
/**
|
|
2061
|
+
* Sets a witness at an index.
|
|
2062
|
+
*
|
|
2063
|
+
* @deprecated Use {@link setWitness} instead.
|
|
2064
|
+
*/
|
|
2065
|
+
setWitnessAt(index: number, witness: HexLike): void {
|
|
2066
|
+
this.setWitness(index, witness);
|
|
1851
2067
|
}
|
|
1852
2068
|
|
|
1853
2069
|
/**
|
|
@@ -1873,9 +2089,9 @@ export class Transaction extends Entity.Base<TransactionLike, Transaction>() {
|
|
|
1873
2089
|
return;
|
|
1874
2090
|
}
|
|
1875
2091
|
|
|
1876
|
-
const witness = this.
|
|
2092
|
+
const witness = this.getWitnessArgs(position) ?? WitnessArgs.from({});
|
|
1877
2093
|
witness.lock = hexFrom(Array.from(new Array(lockLen), () => 0));
|
|
1878
|
-
this.
|
|
2094
|
+
this.setWitnessArgs(position, witness);
|
|
1879
2095
|
}
|
|
1880
2096
|
|
|
1881
2097
|
async getInputsCapacityExtra(client: Client): Promise<Num> {
|
|
@@ -2210,6 +2426,8 @@ export class Transaction extends Entity.Base<TransactionLike, Transaction>() {
|
|
|
2210
2426
|
let leastFee = Zero;
|
|
2211
2427
|
let leastExtraCapacity = Zero;
|
|
2212
2428
|
let collected = 0;
|
|
2429
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
2430
|
+
let tx: Transaction = this;
|
|
2213
2431
|
|
|
2214
2432
|
// ===
|
|
2215
2433
|
// Usually, for the worst situation, three iterations are needed
|
|
@@ -2224,7 +2442,7 @@ export class Transaction extends Entity.Base<TransactionLike, Transaction>() {
|
|
|
2224
2442
|
}
|
|
2225
2443
|
|
|
2226
2444
|
try {
|
|
2227
|
-
return await
|
|
2445
|
+
return await tx.completeInputsByCapacity(
|
|
2228
2446
|
from,
|
|
2229
2447
|
leastFee + leastExtraCapacity,
|
|
2230
2448
|
filter,
|
|
@@ -2243,7 +2461,8 @@ export class Transaction extends Entity.Base<TransactionLike, Transaction>() {
|
|
|
2243
2461
|
}
|
|
2244
2462
|
})();
|
|
2245
2463
|
|
|
2246
|
-
|
|
2464
|
+
tx = await from.prepareTransaction(tx);
|
|
2465
|
+
const fee = await tx.getFee(from.client);
|
|
2247
2466
|
if (fee < leastFee + leastExtraCapacity) {
|
|
2248
2467
|
// Not enough capacity are collected, it should only happens when shouldAddInputs is false
|
|
2249
2468
|
throw new ErrorTransactionInsufficientCapacity(
|
|
@@ -2251,44 +2470,45 @@ export class Transaction extends Entity.Base<TransactionLike, Transaction>() {
|
|
|
2251
2470
|
{ isForChange: leastExtraCapacity !== Zero },
|
|
2252
2471
|
);
|
|
2253
2472
|
}
|
|
2254
|
-
|
|
2255
|
-
await from.prepareTransaction(this);
|
|
2256
2473
|
if (leastFee === Zero) {
|
|
2257
2474
|
// The initial fee is calculated based on prepared transaction
|
|
2258
2475
|
// This should only happens during the first iteration
|
|
2259
|
-
leastFee =
|
|
2476
|
+
leastFee = tx.estimateFee(feeRate);
|
|
2260
2477
|
}
|
|
2261
2478
|
// The extra capacity paid the fee without a change
|
|
2262
2479
|
// leastExtraCapacity should be 0 here, otherwise we should failed in the previous check
|
|
2263
2480
|
// So this only happens in the first iteration
|
|
2264
2481
|
if (fee === leastFee) {
|
|
2482
|
+
this.copy(tx);
|
|
2265
2483
|
return [collected, false];
|
|
2266
2484
|
}
|
|
2267
2485
|
|
|
2268
2486
|
// Invoke the change function on a transaction multiple times may cause problems, so we clone it
|
|
2269
|
-
|
|
2270
|
-
const needed = numFrom(
|
|
2487
|
+
let changedTx = tx.clone();
|
|
2488
|
+
const needed = numFrom(
|
|
2489
|
+
await Promise.resolve(change(changedTx, fee - leastFee)),
|
|
2490
|
+
);
|
|
2271
2491
|
if (needed > Zero) {
|
|
2272
2492
|
// No enough extra capacity to create new cells for change, collect inputs again
|
|
2273
2493
|
leastExtraCapacity = needed;
|
|
2274
2494
|
continue;
|
|
2275
2495
|
}
|
|
2276
2496
|
|
|
2277
|
-
if ((await
|
|
2497
|
+
if ((await changedTx.getFee(from.client)) !== leastFee) {
|
|
2278
2498
|
throw new Error(
|
|
2279
2499
|
"The change function doesn't use all available capacity",
|
|
2280
2500
|
);
|
|
2281
2501
|
}
|
|
2282
2502
|
|
|
2283
2503
|
// New change cells created, update the fee
|
|
2284
|
-
await from.prepareTransaction(
|
|
2285
|
-
const changedFee =
|
|
2504
|
+
changedTx = await from.prepareTransaction(changedTx);
|
|
2505
|
+
const changedFee = changedTx.estimateFee(feeRate);
|
|
2286
2506
|
if (leastFee > changedFee) {
|
|
2287
2507
|
throw new Error("The change function removed existed transaction data");
|
|
2288
2508
|
}
|
|
2289
2509
|
// The fee has been paid
|
|
2290
2510
|
if (leastFee === changedFee) {
|
|
2291
|
-
this.copy(
|
|
2511
|
+
this.copy(changedTx);
|
|
2292
2512
|
return [collected, true];
|
|
2293
2513
|
}
|
|
2294
2514
|
|
|
@@ -13,6 +13,7 @@ import { Num, NumLike, numFrom, numToHex } from "../../num/index.js";
|
|
|
13
13
|
import { apply } from "../../utils/index.js";
|
|
14
14
|
import { ClientCache } from "../cache/index.js";
|
|
15
15
|
import { Client } from "../client.js";
|
|
16
|
+
import { DEFAULT_MIN_FEE_RATE } from "../clientTypes.advanced.js";
|
|
16
17
|
import {
|
|
17
18
|
ClientFindCellsResponse,
|
|
18
19
|
ClientIndexerSearchKeyLike,
|
|
@@ -131,9 +132,12 @@ export abstract class ClientJsonRpc extends Client {
|
|
|
131
132
|
getFeeRateStatistics = this.buildSender(
|
|
132
133
|
"get_fee_rate_statistics",
|
|
133
134
|
[(n: NumLike) => apply(numFrom, n)],
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
135
|
+
// TODO: This is a temporary workaround for the fact that the node may return null for fee rate statistics.
|
|
136
|
+
// We should change the method signature to return null instead of falling back to the default value,
|
|
137
|
+
// but this would be a breaking change.
|
|
138
|
+
(res: { mean: NumLike; median: NumLike } | null) => ({
|
|
139
|
+
mean: numFrom(res?.mean ?? DEFAULT_MIN_FEE_RATE),
|
|
140
|
+
median: numFrom(res?.median ?? DEFAULT_MIN_FEE_RATE),
|
|
137
141
|
}),
|
|
138
142
|
) as Client["getFeeRateStatistics"];
|
|
139
143
|
|
package/src/codec/entity.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { Bytes, bytesEq, bytesFrom, BytesLike } from "../bytes/index.js";
|
|
2
2
|
import { hashCkb } from "../hasher/index.js";
|
|
3
3
|
import { Hex, hexFrom } from "../hex/index.js";
|
|
4
|
+
import type { UnionDecoded, UnionMatchHandlers } from "../molecule/codec.js";
|
|
4
5
|
import { Constructor } from "../utils/index.js";
|
|
6
|
+
import type { CodecLike, DecodedType } from "./codec.js";
|
|
5
7
|
|
|
6
8
|
/**
|
|
7
9
|
* The base class of CCC to create a serializable instance. This should be used with the {@link codec} decorator.
|
|
@@ -144,10 +146,101 @@ export abstract class Entity {
|
|
|
144
146
|
return Impl;
|
|
145
147
|
}
|
|
146
148
|
|
|
149
|
+
/**
|
|
150
|
+
* Convert the entity to bytes.
|
|
151
|
+
* @public
|
|
152
|
+
* @returns The bytes representation of the entity.
|
|
153
|
+
*/
|
|
147
154
|
abstract toBytes(): Bytes;
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Calculate the hash of the entity.
|
|
158
|
+
* @public
|
|
159
|
+
* @returns The hash of the entity.
|
|
160
|
+
*/
|
|
148
161
|
abstract hash(): Hex;
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Convert the entity to a full-byte untrimmed Hex representation.
|
|
165
|
+
* @public
|
|
166
|
+
* @returns The entity full-byte untrimmed hexadecimal representation.
|
|
167
|
+
*/
|
|
149
168
|
abstract toHex(): Hex;
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Create a clone of the entity.
|
|
172
|
+
* @public
|
|
173
|
+
* @returns A clone of the entity.
|
|
174
|
+
*/
|
|
150
175
|
abstract clone(): Entity;
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Generate a base class of CCC to create a serializable Union instance.
|
|
179
|
+
* This should be used with the {@link codec} decorator.
|
|
180
|
+
* @public
|
|
181
|
+
*/
|
|
182
|
+
static BaseUnion<
|
|
183
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
184
|
+
CodecType extends CodecLike<any, UnionDecoded<any, any>>,
|
|
185
|
+
SubTypeLike,
|
|
186
|
+
SubType = SubTypeLike,
|
|
187
|
+
>() {
|
|
188
|
+
type Handlers<Result> = UnionMatchHandlers<CodecType, Result>;
|
|
189
|
+
type Decoded = DecodedType<CodecType>;
|
|
190
|
+
|
|
191
|
+
abstract class Impl extends Entity.Base<SubTypeLike, SubType>() {
|
|
192
|
+
/**
|
|
193
|
+
* The inner decoded object representing the union value.
|
|
194
|
+
* @public
|
|
195
|
+
*/
|
|
196
|
+
constructor(public readonly inner: Decoded) {
|
|
197
|
+
super();
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Match the union type with a set of handlers.
|
|
202
|
+
* @public
|
|
203
|
+
* @param handlers - A map of type-specific handlers, all variants must be handled if no default handler `_` is provided.
|
|
204
|
+
* @returns The result returned by the matching handler.
|
|
205
|
+
*/
|
|
206
|
+
match<Result>(
|
|
207
|
+
handlers: Handlers<Result> & {
|
|
208
|
+
_?: undefined | null;
|
|
209
|
+
},
|
|
210
|
+
): Result;
|
|
211
|
+
/**
|
|
212
|
+
* Match the union type with a set of handlers.
|
|
213
|
+
* @public
|
|
214
|
+
* @param handlers - A map of type-specific handlers, unmatched variants will be handled by the default handler `_`.
|
|
215
|
+
* @returns The result returned by the matching handler.
|
|
216
|
+
*/
|
|
217
|
+
match<Result>(
|
|
218
|
+
handlers: Partial<Handlers<Result>> & {
|
|
219
|
+
_: (inner: Decoded) => Result;
|
|
220
|
+
},
|
|
221
|
+
): Result;
|
|
222
|
+
match<Result>(
|
|
223
|
+
handlers:
|
|
224
|
+
| (Handlers<Result> & {
|
|
225
|
+
_?: undefined | null;
|
|
226
|
+
})
|
|
227
|
+
| (Partial<Handlers<Result>> & {
|
|
228
|
+
_: (inner: Decoded) => Result;
|
|
229
|
+
}),
|
|
230
|
+
): Result {
|
|
231
|
+
const type = this.inner.type as Decoded["type"];
|
|
232
|
+
const handler = (handlers as Partial<Handlers<Result>>)[type];
|
|
233
|
+
|
|
234
|
+
if (handler != undefined) {
|
|
235
|
+
return handler(this.inner.value);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
return (handlers._ as (inner: Decoded) => Result)(this.inner);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return Impl;
|
|
243
|
+
}
|
|
151
244
|
}
|
|
152
245
|
|
|
153
246
|
/**
|
package/src/jsonRpc/requestor.ts
CHANGED
|
@@ -129,14 +129,19 @@ export class RequestorJsonRpc {
|
|
|
129
129
|
await pending;
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
-
|
|
133
|
-
|
|
132
|
+
const res = (await (async () => {
|
|
133
|
+
this.concurrent += 1;
|
|
134
|
+
try {
|
|
135
|
+
return await this.transport.request(payload);
|
|
136
|
+
} finally {
|
|
137
|
+
this.concurrent -= 1;
|
|
138
|
+
this.pending.shift()?.();
|
|
139
|
+
}
|
|
140
|
+
})()) as {
|
|
134
141
|
id: number;
|
|
135
142
|
error: unknown;
|
|
136
143
|
result: unknown;
|
|
137
144
|
};
|
|
138
|
-
this.concurrent -= 1;
|
|
139
|
-
this.pending.shift()?.();
|
|
140
145
|
|
|
141
146
|
if (res.id !== payload.id) {
|
|
142
147
|
throw new Error(`Id mismatched, got ${res.id}, expected ${payload.id}`);
|