@ckb-ccc/core 0.0.13-alpha.0 → 0.0.13-alpha.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/CHANGELOG.md +14 -0
- package/dist/ckb/transaction.d.ts.map +1 -1
- package/dist/ckb/transaction.js +17 -10
- package/dist/client/advanced.d.ts +2 -1
- package/dist/client/advanced.d.ts.map +1 -1
- package/dist/client/advanced.js +2 -1
- package/dist/client/cache/advanced.d.ts +2 -0
- package/dist/client/cache/advanced.d.ts.map +1 -0
- package/dist/client/cache/advanced.js +1 -0
- package/dist/client/cache/cache.d.ts +14 -0
- package/dist/client/cache/cache.d.ts.map +1 -0
- package/dist/client/cache/cache.js +1 -0
- package/dist/client/cache/index.d.ts +3 -0
- package/dist/client/cache/index.d.ts.map +1 -0
- package/dist/client/cache/index.js +2 -0
- package/dist/client/{client.advanced.d.ts → cache/memory.advanced.d.ts} +5 -5
- package/dist/client/cache/memory.advanced.d.ts.map +1 -0
- package/dist/client/{client.advanced.js → cache/memory.advanced.js} +6 -6
- package/dist/client/cache/memory.d.ts +19 -0
- package/dist/client/cache/memory.d.ts.map +1 -0
- package/dist/client/cache/memory.js +54 -0
- package/dist/client/client.d.ts +4 -7
- package/dist/client/client.d.ts.map +1 -1
- package/dist/client/client.js +22 -39
- package/dist/client/clientPublicMainnet.d.ts.map +1 -1
- package/dist/client/clientPublicMainnet.js +5 -2
- package/dist/client/clientPublicTestnet.d.ts.map +1 -1
- package/dist/client/clientPublicTestnet.js +5 -2
- package/dist/client/clientTypes.d.ts +1 -1
- package/dist/client/clientTypes.d.ts.map +1 -1
- package/dist/client/index.d.ts +1 -0
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +1 -0
- package/dist/client/jsonRpc/index.d.ts +5 -4
- package/dist/client/jsonRpc/index.d.ts.map +1 -1
- package/dist/client/jsonRpc/index.js +5 -15
- package/dist/client/jsonRpc/types.d.ts +0 -6
- package/dist/client/jsonRpc/types.d.ts.map +1 -1
- package/dist/client/transports/advanced.d.ts +9 -0
- package/dist/client/transports/advanced.d.ts.map +1 -0
- package/dist/client/transports/advanced.js +11 -0
- package/dist/client/transports/http.d.ts +8 -0
- package/dist/client/transports/http.d.ts.map +1 -0
- package/dist/client/transports/http.js +20 -0
- package/dist/client/transports/transport.d.ts +10 -0
- package/dist/client/transports/transport.d.ts.map +1 -0
- package/dist/client/transports/transport.js +1 -0
- package/dist/client/transports/webSocket.d.ts +10 -0
- package/dist/client/transports/webSocket.d.ts.map +1 -0
- package/dist/client/transports/webSocket.js +61 -0
- package/dist.commonjs/ckb/transaction.d.ts.map +1 -1
- package/dist.commonjs/ckb/transaction.js +17 -10
- package/dist.commonjs/client/advanced.d.ts +2 -1
- package/dist.commonjs/client/advanced.d.ts.map +1 -1
- package/dist.commonjs/client/advanced.js +2 -1
- package/dist.commonjs/client/cache/advanced.d.ts +2 -0
- package/dist.commonjs/client/cache/advanced.d.ts.map +1 -0
- package/dist.commonjs/client/cache/advanced.js +17 -0
- package/dist.commonjs/client/cache/cache.d.ts +14 -0
- package/dist.commonjs/client/cache/cache.d.ts.map +1 -0
- package/dist.commonjs/client/cache/cache.js +2 -0
- package/dist.commonjs/client/cache/index.d.ts +3 -0
- package/dist.commonjs/client/cache/index.d.ts.map +1 -0
- package/dist.commonjs/client/cache/index.js +18 -0
- package/dist.commonjs/client/{client.advanced.d.ts → cache/memory.advanced.d.ts} +5 -5
- package/dist.commonjs/client/cache/memory.advanced.d.ts.map +1 -0
- package/dist.commonjs/client/{client.advanced.js → cache/memory.advanced.js} +6 -6
- package/dist.commonjs/client/cache/memory.d.ts +19 -0
- package/dist.commonjs/client/cache/memory.d.ts.map +1 -0
- package/dist.commonjs/client/cache/memory.js +58 -0
- package/dist.commonjs/client/client.d.ts +4 -7
- package/dist.commonjs/client/client.d.ts.map +1 -1
- package/dist.commonjs/client/client.js +22 -39
- package/dist.commonjs/client/clientPublicMainnet.d.ts.map +1 -1
- package/dist.commonjs/client/clientPublicMainnet.js +5 -2
- package/dist.commonjs/client/clientPublicTestnet.d.ts.map +1 -1
- package/dist.commonjs/client/clientPublicTestnet.js +5 -2
- package/dist.commonjs/client/clientTypes.d.ts +1 -1
- package/dist.commonjs/client/clientTypes.d.ts.map +1 -1
- package/dist.commonjs/client/index.d.ts +1 -0
- package/dist.commonjs/client/index.d.ts.map +1 -1
- package/dist.commonjs/client/index.js +1 -0
- package/dist.commonjs/client/jsonRpc/index.d.ts +5 -4
- package/dist.commonjs/client/jsonRpc/index.d.ts.map +1 -1
- package/dist.commonjs/client/jsonRpc/index.js +15 -28
- package/dist.commonjs/client/jsonRpc/types.d.ts +0 -6
- package/dist.commonjs/client/jsonRpc/types.d.ts.map +1 -1
- package/dist.commonjs/client/transports/advanced.d.ts +9 -0
- package/dist.commonjs/client/transports/advanced.d.ts.map +1 -0
- package/dist.commonjs/client/transports/advanced.js +29 -0
- package/dist.commonjs/client/transports/http.d.ts +8 -0
- package/dist.commonjs/client/transports/http.d.ts.map +1 -0
- package/dist.commonjs/client/transports/http.js +24 -0
- package/dist.commonjs/client/transports/transport.d.ts +10 -0
- package/dist.commonjs/client/transports/transport.d.ts.map +1 -0
- package/dist.commonjs/client/transports/transport.js +2 -0
- package/dist.commonjs/client/transports/webSocket.d.ts +10 -0
- package/dist.commonjs/client/transports/webSocket.d.ts.map +1 -0
- package/dist.commonjs/client/transports/webSocket.js +65 -0
- package/package.json +1 -1
- package/src/ckb/transaction.ts +24 -16
- package/src/client/advanced.ts +2 -1
- package/src/client/cache/advanced.ts +1 -0
- package/src/client/cache/cache.ts +25 -0
- package/src/client/cache/index.ts +2 -0
- package/src/client/{client.advanced.ts → cache/memory.advanced.ts} +6 -6
- package/src/client/cache/memory.ts +75 -0
- package/src/client/client.ts +23 -44
- package/src/client/clientPublicMainnet.ts +8 -2
- package/src/client/clientPublicTestnet.ts +8 -2
- package/src/client/clientTypes.ts +1 -0
- package/src/client/index.ts +1 -0
- package/src/client/jsonRpc/index.ts +13 -19
- package/src/client/jsonRpc/types.ts +0 -7
- package/src/client/transports/advanced.ts +14 -0
- package/src/client/transports/http.ts +26 -0
- package/src/client/transports/transport.ts +10 -0
- package/src/client/transports/webSocket.ts +81 -0
- package/dist/client/client.advanced.d.ts.map +0 -1
- package/dist.commonjs/client/client.advanced.d.ts.map +0 -1
package/src/ckb/transaction.ts
CHANGED
|
@@ -1538,8 +1538,9 @@ export class Transaction {
|
|
|
1538
1538
|
}> {
|
|
1539
1539
|
const scripts = (await from.getAddressObjs()).map(({ script }) => script);
|
|
1540
1540
|
const collectedCells = [];
|
|
1541
|
-
let acc: T = init;
|
|
1542
1541
|
|
|
1542
|
+
let acc: T = init;
|
|
1543
|
+
let fulfilled = false;
|
|
1543
1544
|
for (const script of scripts) {
|
|
1544
1545
|
for await (const cell of from.client.findCellsByCollectableSearchKey({
|
|
1545
1546
|
script,
|
|
@@ -1556,26 +1557,33 @@ export class Transaction {
|
|
|
1556
1557
|
continue;
|
|
1557
1558
|
}
|
|
1558
1559
|
const i = collectedCells.push(cell);
|
|
1559
|
-
const next
|
|
1560
|
+
const next = await Promise.resolve(
|
|
1560
1561
|
accumulator(acc, cell, i - 1, collectedCells),
|
|
1561
1562
|
);
|
|
1562
1563
|
if (next === undefined) {
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
CellInput.from({
|
|
1566
|
-
previousOutput: outPoint,
|
|
1567
|
-
since: 0,
|
|
1568
|
-
outputData,
|
|
1569
|
-
cellOutput,
|
|
1570
|
-
}),
|
|
1571
|
-
),
|
|
1572
|
-
);
|
|
1573
|
-
return {
|
|
1574
|
-
addedCount: collectedCells.length,
|
|
1575
|
-
};
|
|
1564
|
+
fulfilled = true;
|
|
1565
|
+
break;
|
|
1576
1566
|
}
|
|
1577
|
-
acc = next;
|
|
1578
1567
|
}
|
|
1568
|
+
if (fulfilled) {
|
|
1569
|
+
break;
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1572
|
+
|
|
1573
|
+
this.inputs.push(
|
|
1574
|
+
...collectedCells.map(({ outPoint, outputData, cellOutput }) =>
|
|
1575
|
+
CellInput.from({
|
|
1576
|
+
previousOutput: outPoint,
|
|
1577
|
+
since: 0,
|
|
1578
|
+
outputData,
|
|
1579
|
+
cellOutput,
|
|
1580
|
+
}),
|
|
1581
|
+
),
|
|
1582
|
+
);
|
|
1583
|
+
if (fulfilled) {
|
|
1584
|
+
return {
|
|
1585
|
+
addedCount: collectedCells.length,
|
|
1586
|
+
};
|
|
1579
1587
|
}
|
|
1580
1588
|
|
|
1581
1589
|
return {
|
package/src/client/advanced.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export * from "./
|
|
1
|
+
export * from "./cache/advanced.js";
|
|
2
2
|
export * from "./clientPublicMainnet.advanced.js";
|
|
3
3
|
export * from "./clientPublicTestnet.advanced.js";
|
|
4
4
|
export * from "./clientTypes.advanced.js";
|
|
5
5
|
export * from "./jsonRpc/advanced.js";
|
|
6
|
+
export * from "./transports/advanced.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./memory.advanced.js";
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Cell,
|
|
3
|
+
CellLike,
|
|
4
|
+
OutPointLike,
|
|
5
|
+
Transaction,
|
|
6
|
+
TransactionLike,
|
|
7
|
+
} from "../../ckb/index.js";
|
|
8
|
+
import { HexLike } from "../../hex/index.js";
|
|
9
|
+
import { ClientCollectableSearchKeyLike } from "../clientTypes.advanced.js";
|
|
10
|
+
|
|
11
|
+
export interface ClientCache {
|
|
12
|
+
markUsable(cellLike: CellLike): Promise<void>;
|
|
13
|
+
markUnusable(outPointLike: OutPointLike): Promise<void>;
|
|
14
|
+
|
|
15
|
+
isUnusable(outPointLike: OutPointLike): Promise<boolean>;
|
|
16
|
+
|
|
17
|
+
recordTransactions(
|
|
18
|
+
...transactions: (TransactionLike | TransactionLike[])[]
|
|
19
|
+
): Promise<void>;
|
|
20
|
+
getTransaction(txHash: HexLike): Promise<Transaction | undefined>;
|
|
21
|
+
|
|
22
|
+
recordCells(...cells: (CellLike | CellLike[])[]): Promise<void>;
|
|
23
|
+
getCell(outPoint: OutPointLike): Promise<Cell | undefined>;
|
|
24
|
+
findCells(filter: ClientCollectableSearchKeyLike): AsyncGenerator<Cell>;
|
|
25
|
+
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { bytesFrom } from "
|
|
2
|
-
import { Cell, CellLike, Script, ScriptLike } from "
|
|
3
|
-
import { HexLike, hexFrom } from "
|
|
4
|
-
import { NumLike, numFrom } from "
|
|
1
|
+
import { bytesFrom } from "../../bytes/index.js";
|
|
2
|
+
import { Cell, CellLike, Script, ScriptLike } from "../../ckb/index.js";
|
|
3
|
+
import { HexLike, hexFrom } from "../../hex/index.js";
|
|
4
|
+
import { NumLike, numFrom } from "../../num/index.js";
|
|
5
5
|
import {
|
|
6
6
|
ClientCollectableSearchKeyLike,
|
|
7
7
|
clientSearchKeyRangeFrom,
|
|
8
|
-
} from "
|
|
9
|
-
import { ClientIndexerSearchKey } from "
|
|
8
|
+
} from "../clientTypes.advanced.js";
|
|
9
|
+
import { ClientIndexerSearchKey } from "../clientTypes.js";
|
|
10
10
|
|
|
11
11
|
export function filterData(
|
|
12
12
|
dataLike: HexLike,
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Cell,
|
|
3
|
+
CellLike,
|
|
4
|
+
OutPoint,
|
|
5
|
+
OutPointLike,
|
|
6
|
+
Transaction,
|
|
7
|
+
TransactionLike,
|
|
8
|
+
} from "../../ckb/index.js";
|
|
9
|
+
import { HexLike, hexFrom } from "../../hex/index.js";
|
|
10
|
+
import { ClientCollectableSearchKeyLike } from "../clientTypes.advanced.js";
|
|
11
|
+
import { ClientCache } from "./cache.js";
|
|
12
|
+
import { filterCell } from "./memory.advanced.js";
|
|
13
|
+
|
|
14
|
+
export class ClientCacheMemory implements ClientCache {
|
|
15
|
+
private readonly cachedTransactions: Transaction[] = [];
|
|
16
|
+
private readonly unusableOutPoints: OutPoint[] = [];
|
|
17
|
+
private readonly usableCells: Cell[] = [];
|
|
18
|
+
private readonly knownCells: Cell[] = [];
|
|
19
|
+
|
|
20
|
+
async markUsable(cellLike: CellLike): Promise<void> {
|
|
21
|
+
const cell = Cell.from(cellLike).clone();
|
|
22
|
+
this.usableCells.push(cell);
|
|
23
|
+
this.knownCells.push(cell);
|
|
24
|
+
|
|
25
|
+
const index = this.unusableOutPoints.findIndex((o) => cell.outPoint.eq(o));
|
|
26
|
+
if (index !== -1) {
|
|
27
|
+
this.unusableOutPoints.splice(index, 1);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async markUnusable(outPointLike: OutPointLike): Promise<void> {
|
|
32
|
+
const outPoint = OutPoint.from(outPointLike);
|
|
33
|
+
this.unusableOutPoints.push(outPoint.clone());
|
|
34
|
+
|
|
35
|
+
const index = this.usableCells.findIndex((c) => c.outPoint.eq(outPoint));
|
|
36
|
+
if (index !== -1) {
|
|
37
|
+
this.usableCells.splice(index, 1);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async isUnusable(outPointLike: OutPointLike): Promise<boolean> {
|
|
42
|
+
const outPoint = OutPoint.from(outPointLike);
|
|
43
|
+
return this.unusableOutPoints.find((o) => o.eq(outPoint)) !== undefined;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async recordTransactions(
|
|
47
|
+
...transactions: (TransactionLike | TransactionLike[])[]
|
|
48
|
+
): Promise<void> {
|
|
49
|
+
this.cachedTransactions.push(...transactions.flat().map(Transaction.from));
|
|
50
|
+
}
|
|
51
|
+
async getTransaction(txHashLike: HexLike): Promise<Transaction | undefined> {
|
|
52
|
+
const txHash = hexFrom(txHashLike);
|
|
53
|
+
return this.cachedTransactions.find((tx) => tx.hash() === txHash);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async recordCells(...cells: (CellLike | CellLike[])[]): Promise<void> {
|
|
57
|
+
this.usableCells.push(...cells.flat().map(Cell.from));
|
|
58
|
+
}
|
|
59
|
+
async getCell(outPointLike: OutPointLike): Promise<Cell | undefined> {
|
|
60
|
+
const outPoint = OutPoint.from(outPointLike);
|
|
61
|
+
return this.usableCells.find((cell) => cell.outPoint.eq(outPoint));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async *findCells(
|
|
65
|
+
keyLike: ClientCollectableSearchKeyLike,
|
|
66
|
+
): AsyncGenerator<Cell> {
|
|
67
|
+
for (const cell of this.usableCells) {
|
|
68
|
+
if (!filterCell(keyLike, cell)) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
yield cell;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
package/src/client/client.ts
CHANGED
|
@@ -2,7 +2,6 @@ import {
|
|
|
2
2
|
Cell,
|
|
3
3
|
CellDep,
|
|
4
4
|
CellDepLike,
|
|
5
|
-
CellLike,
|
|
6
5
|
OutPoint,
|
|
7
6
|
OutPointLike,
|
|
8
7
|
Script,
|
|
@@ -14,7 +13,8 @@ import { Zero } from "../fixedPoint/index.js";
|
|
|
14
13
|
import { Hex, HexLike, hexFrom } from "../hex/index.js";
|
|
15
14
|
import { Num, NumLike, numFrom } from "../num/index.js";
|
|
16
15
|
import { apply, reduceAsync } from "../utils/index.js";
|
|
17
|
-
import {
|
|
16
|
+
import { ClientCache } from "./cache/index.js";
|
|
17
|
+
import { ClientCacheMemory } from "./cache/memory.js";
|
|
18
18
|
import { ClientCollectableSearchKeyLike } from "./clientTypes.advanced.js";
|
|
19
19
|
import {
|
|
20
20
|
ClientBlock,
|
|
@@ -76,10 +76,7 @@ export class CellDepInfo {
|
|
|
76
76
|
* @public
|
|
77
77
|
*/
|
|
78
78
|
export abstract class Client {
|
|
79
|
-
|
|
80
|
-
private readonly unusableOutPoints: OutPoint[] = [];
|
|
81
|
-
private readonly usableCells: Cell[] = [];
|
|
82
|
-
private readonly knownCells: Cell[] = [];
|
|
79
|
+
constructor(public cache: ClientCache = new ClientCacheMemory()) {}
|
|
83
80
|
|
|
84
81
|
abstract get url(): string;
|
|
85
82
|
abstract get addressPrefix(): string;
|
|
@@ -102,27 +99,6 @@ export abstract class Client {
|
|
|
102
99
|
withCycles?: boolean | null,
|
|
103
100
|
): Promise<ClientBlock | undefined>;
|
|
104
101
|
|
|
105
|
-
async markUsable(cellLike: CellLike): Promise<void> {
|
|
106
|
-
const cell = Cell.from(cellLike).clone();
|
|
107
|
-
this.usableCells.push(cell);
|
|
108
|
-
this.knownCells.push(cell);
|
|
109
|
-
|
|
110
|
-
const index = this.unusableOutPoints.findIndex((o) => cell.outPoint.eq(o));
|
|
111
|
-
if (index !== -1) {
|
|
112
|
-
this.unusableOutPoints.splice(index, 1);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
async markUnusable(outPointLike: OutPointLike): Promise<void> {
|
|
117
|
-
const outPoint = OutPoint.from(outPointLike);
|
|
118
|
-
this.unusableOutPoints.push(outPoint.clone());
|
|
119
|
-
|
|
120
|
-
const index = this.usableCells.findIndex((c) => c.outPoint.eq(outPoint));
|
|
121
|
-
if (index !== -1) {
|
|
122
|
-
this.usableCells.splice(index, 1);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
102
|
abstract sendTransactionNoCache(
|
|
127
103
|
transaction: TransactionLike,
|
|
128
104
|
validator?: OutputsValidator,
|
|
@@ -133,10 +109,10 @@ export abstract class Client {
|
|
|
133
109
|
|
|
134
110
|
async getCell(outPointLike: OutPointLike): Promise<Cell | undefined> {
|
|
135
111
|
const outPoint = OutPoint.from(outPointLike);
|
|
136
|
-
const cached = this.
|
|
112
|
+
const cached = await this.cache.getCell(outPoint);
|
|
137
113
|
|
|
138
114
|
if (cached) {
|
|
139
|
-
return cached
|
|
115
|
+
return cached;
|
|
140
116
|
}
|
|
141
117
|
|
|
142
118
|
const transaction = await this.getTransactionNoCache(outPoint.txHash);
|
|
@@ -154,8 +130,8 @@ export abstract class Client {
|
|
|
154
130
|
cellOutput: transaction.transaction.outputs[index],
|
|
155
131
|
outputData: transaction.transaction.outputsData[index] ?? "0x",
|
|
156
132
|
});
|
|
157
|
-
this.
|
|
158
|
-
return cell
|
|
133
|
+
await this.cache.recordCells(cell);
|
|
134
|
+
return cell;
|
|
159
135
|
}
|
|
160
136
|
|
|
161
137
|
abstract findCellsPagedNoCache(
|
|
@@ -171,7 +147,7 @@ export abstract class Client {
|
|
|
171
147
|
after?: string,
|
|
172
148
|
): Promise<ClientFindCellsResponse> {
|
|
173
149
|
const res = await this.findCellsPagedNoCache(key, order, limit, after);
|
|
174
|
-
this.
|
|
150
|
+
await this.cache.recordCells(res.cells);
|
|
175
151
|
return res;
|
|
176
152
|
}
|
|
177
153
|
|
|
@@ -213,18 +189,14 @@ export abstract class Client {
|
|
|
213
189
|
const key = ClientIndexerSearchKey.from(keyLike);
|
|
214
190
|
const foundedOutPoints = [];
|
|
215
191
|
|
|
216
|
-
for (const cell of this.
|
|
217
|
-
if (!filterCell(key, cell)) {
|
|
218
|
-
continue;
|
|
219
|
-
}
|
|
220
|
-
|
|
192
|
+
for await (const cell of this.cache.findCells(key)) {
|
|
221
193
|
foundedOutPoints.push(cell.outPoint);
|
|
222
194
|
yield cell;
|
|
223
195
|
}
|
|
224
196
|
|
|
225
197
|
for await (const cell of this.findCells(key, order, limit)) {
|
|
226
198
|
if (
|
|
227
|
-
this.
|
|
199
|
+
(await this.cache.isUnusable(cell.outPoint)) ||
|
|
228
200
|
foundedOutPoints.some((founded) => founded.eq(cell.outPoint))
|
|
229
201
|
) {
|
|
230
202
|
continue;
|
|
@@ -506,13 +478,13 @@ export abstract class Client {
|
|
|
506
478
|
|
|
507
479
|
const txHash = await this.sendTransactionNoCache(tx, validator);
|
|
508
480
|
|
|
509
|
-
this.
|
|
481
|
+
await this.cache.recordTransactions(tx);
|
|
510
482
|
await Promise.all(
|
|
511
|
-
tx.inputs.map((i) => this.markUnusable(i.previousOutput)),
|
|
483
|
+
tx.inputs.map((i) => this.cache.markUnusable(i.previousOutput)),
|
|
512
484
|
);
|
|
513
485
|
await Promise.all(
|
|
514
486
|
tx.outputs.map((o, i) =>
|
|
515
|
-
this.markUsable({
|
|
487
|
+
this.cache.markUsable({
|
|
516
488
|
cellOutput: o,
|
|
517
489
|
outputData: tx.outputsData[i],
|
|
518
490
|
outPoint: {
|
|
@@ -530,18 +502,25 @@ export abstract class Client {
|
|
|
530
502
|
): Promise<ClientTransactionResponse | undefined> {
|
|
531
503
|
const txHash = hexFrom(txHashLike);
|
|
532
504
|
const res = await this.getTransactionNoCache(txHash);
|
|
533
|
-
if (res
|
|
505
|
+
if (res?.transaction) {
|
|
534
506
|
return res;
|
|
535
507
|
}
|
|
536
508
|
|
|
537
|
-
const tx = this.
|
|
509
|
+
const tx = await this.cache.getTransaction(txHash);
|
|
538
510
|
if (!tx) {
|
|
539
511
|
return;
|
|
540
512
|
}
|
|
541
513
|
|
|
514
|
+
if (!res) {
|
|
515
|
+
return {
|
|
516
|
+
transaction: tx,
|
|
517
|
+
status: "sent",
|
|
518
|
+
};
|
|
519
|
+
}
|
|
520
|
+
|
|
542
521
|
return {
|
|
522
|
+
...res,
|
|
543
523
|
transaction: tx,
|
|
544
|
-
status: "proposed",
|
|
545
524
|
};
|
|
546
525
|
}
|
|
547
526
|
}
|
|
@@ -8,11 +8,17 @@ import { ClientJsonRpc } from "./jsonRpc/index.js";
|
|
|
8
8
|
*/
|
|
9
9
|
export class ClientPublicMainnet extends ClientJsonRpc {
|
|
10
10
|
constructor(
|
|
11
|
-
url
|
|
11
|
+
url?: string,
|
|
12
12
|
timeout?: number,
|
|
13
13
|
private readonly scripts = MAINNET_SCRIPTS,
|
|
14
14
|
) {
|
|
15
|
-
super(
|
|
15
|
+
super(
|
|
16
|
+
url ??
|
|
17
|
+
(typeof WebSocket !== "undefined"
|
|
18
|
+
? "wss://mainnet.ckb.dev/ws"
|
|
19
|
+
: "https://mainnet.ckb.dev/"),
|
|
20
|
+
timeout,
|
|
21
|
+
);
|
|
16
22
|
}
|
|
17
23
|
|
|
18
24
|
get addressPrefix(): string {
|
|
@@ -8,11 +8,17 @@ import { ClientJsonRpc } from "./jsonRpc/index.js";
|
|
|
8
8
|
*/
|
|
9
9
|
export class ClientPublicTestnet extends ClientJsonRpc {
|
|
10
10
|
constructor(
|
|
11
|
-
url
|
|
11
|
+
url?: string,
|
|
12
12
|
timeout?: number,
|
|
13
13
|
private readonly scripts = TESTNET_SCRIPTS,
|
|
14
14
|
) {
|
|
15
|
-
super(
|
|
15
|
+
super(
|
|
16
|
+
url ??
|
|
17
|
+
(typeof WebSocket !== "undefined"
|
|
18
|
+
? "wss://testnet.ckb.dev/ws"
|
|
19
|
+
: "https://testnet.ckb.dev/"),
|
|
20
|
+
timeout,
|
|
21
|
+
);
|
|
16
22
|
}
|
|
17
23
|
|
|
18
24
|
get addressPrefix(): string {
|
package/src/client/index.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import fetch from "cross-fetch";
|
|
2
1
|
import { apply } from "../../barrel.js";
|
|
3
2
|
import { TransactionLike } from "../../ckb/index.js";
|
|
4
3
|
import { Hex, HexLike, hexFrom } from "../../hex/index.js";
|
|
@@ -10,7 +9,12 @@ import {
|
|
|
10
9
|
ClientTransactionResponse,
|
|
11
10
|
OutputsValidator,
|
|
12
11
|
} from "../clientTypes.js";
|
|
13
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
JsonRpcPayload,
|
|
14
|
+
Transport,
|
|
15
|
+
transportFromUri,
|
|
16
|
+
} from "../transports/advanced.js";
|
|
17
|
+
import { JsonRpcTransformers } from "./advanced.js";
|
|
14
18
|
|
|
15
19
|
/**
|
|
16
20
|
* Applies a transformation function to a value if the transformer is provided.
|
|
@@ -42,18 +46,22 @@ async function transform(
|
|
|
42
46
|
*/
|
|
43
47
|
|
|
44
48
|
export abstract class ClientJsonRpc extends Client {
|
|
49
|
+
private readonly transport: Transport;
|
|
50
|
+
|
|
45
51
|
/**
|
|
46
52
|
* Creates an instance of ClientJsonRpc.
|
|
47
53
|
*
|
|
48
54
|
* @param url_ - The URL of the JSON-RPC server.
|
|
49
|
-
* @param timeout - The timeout for requests in milliseconds
|
|
55
|
+
* @param timeout - The timeout for requests in milliseconds
|
|
50
56
|
*/
|
|
51
57
|
|
|
52
58
|
constructor(
|
|
53
59
|
private readonly url_: string,
|
|
54
|
-
private readonly timeout
|
|
60
|
+
private readonly timeout?: number,
|
|
55
61
|
) {
|
|
56
62
|
super();
|
|
63
|
+
|
|
64
|
+
this.transport = transportFromUri(url_);
|
|
57
65
|
}
|
|
58
66
|
|
|
59
67
|
/**
|
|
@@ -232,22 +240,8 @@ export abstract class ClientJsonRpc extends Client {
|
|
|
232
240
|
*
|
|
233
241
|
* @throws Will throw an error if the response ID does not match the request ID, or if the response contains an error.
|
|
234
242
|
*/
|
|
235
|
-
|
|
236
243
|
async send(payload: JsonRpcPayload): Promise<unknown> {
|
|
237
|
-
const
|
|
238
|
-
const abortTimer = setTimeout(() => aborter.abort(), this.timeout);
|
|
239
|
-
|
|
240
|
-
const raw = await fetch(this.url, {
|
|
241
|
-
method: "POST",
|
|
242
|
-
headers: {
|
|
243
|
-
"content-type": "application/json",
|
|
244
|
-
},
|
|
245
|
-
body: JSON.stringify(payload),
|
|
246
|
-
signal: aborter.signal,
|
|
247
|
-
});
|
|
248
|
-
clearTimeout(abortTimer);
|
|
249
|
-
|
|
250
|
-
const res = (await raw.json()) as {
|
|
244
|
+
const res = (await this.transport.request(payload)) as {
|
|
251
245
|
id: number;
|
|
252
246
|
error: unknown;
|
|
253
247
|
result: unknown;
|
|
@@ -1,12 +1,5 @@
|
|
|
1
1
|
import { Hex } from "../../hex/index.js";
|
|
2
2
|
|
|
3
|
-
export type JsonRpcPayload = {
|
|
4
|
-
id: number;
|
|
5
|
-
jsonrpc: "2.0";
|
|
6
|
-
method: string;
|
|
7
|
-
params: unknown[] | Record<string, unknown>;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
3
|
export type JsonRpcHashType = "type" | "data" | "data1" | "data2";
|
|
11
4
|
export type JsonRpcDepType = "dep_group" | "code";
|
|
12
5
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { TransportHttp } from "./http.js";
|
|
2
|
+
import { TransportWebSocket } from "./webSocket.js";
|
|
3
|
+
|
|
4
|
+
export * from "./http.js";
|
|
5
|
+
export * from "./transport.js";
|
|
6
|
+
export * from "./webSocket.js";
|
|
7
|
+
|
|
8
|
+
export function transportFromUri(uri: string, config?: { timeout?: number }) {
|
|
9
|
+
if (uri.startsWith("wss://")) {
|
|
10
|
+
return new TransportWebSocket(uri, config?.timeout);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return new TransportHttp(uri, config?.timeout);
|
|
14
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { JsonRpcPayload, Transport } from "./transport.js";
|
|
2
|
+
|
|
3
|
+
export class TransportHttp implements Transport {
|
|
4
|
+
constructor(
|
|
5
|
+
private readonly url: string,
|
|
6
|
+
private readonly timeout = 30000,
|
|
7
|
+
) {}
|
|
8
|
+
|
|
9
|
+
async request(payload: JsonRpcPayload) {
|
|
10
|
+
const aborter = new AbortController();
|
|
11
|
+
const abortTimer = setTimeout(() => aborter.abort(), this.timeout);
|
|
12
|
+
|
|
13
|
+
const raw = await (
|
|
14
|
+
await fetch(this.url, {
|
|
15
|
+
method: "POST",
|
|
16
|
+
headers: {
|
|
17
|
+
"content-type": "application/json",
|
|
18
|
+
},
|
|
19
|
+
body: JSON.stringify(payload),
|
|
20
|
+
signal: aborter.signal,
|
|
21
|
+
})
|
|
22
|
+
).json();
|
|
23
|
+
clearTimeout(abortTimer);
|
|
24
|
+
return raw;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { JsonRpcPayload, Transport } from "./transport.js";
|
|
2
|
+
|
|
3
|
+
export class TransportWebSocket implements Transport {
|
|
4
|
+
private ongoing: Map<
|
|
5
|
+
number,
|
|
6
|
+
[
|
|
7
|
+
(response: unknown) => unknown,
|
|
8
|
+
(error: unknown) => unknown,
|
|
9
|
+
ReturnType<typeof setTimeout>,
|
|
10
|
+
]
|
|
11
|
+
> = new Map();
|
|
12
|
+
private socket?: Promise<WebSocket>;
|
|
13
|
+
|
|
14
|
+
constructor(
|
|
15
|
+
private readonly url: string,
|
|
16
|
+
private readonly timeout = 30000,
|
|
17
|
+
) {}
|
|
18
|
+
|
|
19
|
+
async request(data: JsonRpcPayload) {
|
|
20
|
+
const socket = (() => {
|
|
21
|
+
if (this.socket) {
|
|
22
|
+
return this.socket;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const socket = new WebSocket(this.url);
|
|
26
|
+
const onMessage = ({ data }: { data: string }) => {
|
|
27
|
+
const res = JSON.parse(data);
|
|
28
|
+
if (typeof res !== "object" || res === null) {
|
|
29
|
+
throw new Error(`Unknown response ${data}`);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const req = this.ongoing.get(res.id);
|
|
33
|
+
if (!req) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
clearTimeout(req[2]);
|
|
37
|
+
this.ongoing.delete(res.id);
|
|
38
|
+
|
|
39
|
+
req[0](res);
|
|
40
|
+
};
|
|
41
|
+
const onClose = (error?: unknown) => {
|
|
42
|
+
this.socket = undefined;
|
|
43
|
+
this.ongoing.forEach(([_, onError]) =>
|
|
44
|
+
onError(error ?? new Error("Connection closed")),
|
|
45
|
+
);
|
|
46
|
+
this.ongoing.clear();
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
socket.onclose = onClose;
|
|
50
|
+
socket.onerror = onClose;
|
|
51
|
+
socket.onmessage = onMessage;
|
|
52
|
+
|
|
53
|
+
this.socket = new Promise((resolve) => {
|
|
54
|
+
if (socket.readyState === socket.CONNECTING) {
|
|
55
|
+
socket.onopen = resolve;
|
|
56
|
+
} else {
|
|
57
|
+
resolve(undefined);
|
|
58
|
+
}
|
|
59
|
+
}).then(() => socket);
|
|
60
|
+
return this.socket;
|
|
61
|
+
})();
|
|
62
|
+
|
|
63
|
+
return new Promise((resolve, reject) => {
|
|
64
|
+
this.ongoing.set(data.id, [
|
|
65
|
+
resolve,
|
|
66
|
+
reject,
|
|
67
|
+
setTimeout(() => reject(new Error("Request timeout")), this.timeout),
|
|
68
|
+
]);
|
|
69
|
+
socket.then((socket) => {
|
|
70
|
+
if (
|
|
71
|
+
socket.readyState === socket.CLOSED ||
|
|
72
|
+
socket.readyState === socket.CLOSING
|
|
73
|
+
) {
|
|
74
|
+
reject(new Error("Connection closed"));
|
|
75
|
+
} else {
|
|
76
|
+
socket.send(JSON.stringify(data));
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client.advanced.d.ts","sourceRoot":"","sources":["../../src/client/client.advanced.ts"],"names":[],"mappings":"AACA,OAAO,EAAQ,QAAQ,EAAU,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACrE,OAAO,EAAE,OAAO,EAAW,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,OAAO,EAAW,MAAM,iBAAiB,CAAC;AACnD,OAAO,EACL,8BAA8B,EAE/B,MAAM,2BAA2B,CAAC;AAGnC,wBAAgB,UAAU,CACxB,QAAQ,EAAE,OAAO,EACjB,UAAU,EAAE,OAAO,GAAG,SAAS,EAC/B,UAAU,EAAE,OAAO,GAAG,QAAQ,GAAG,SAAS,GACzC,OAAO,CAgBT;AAED,wBAAgB,YAAY,CAC1B,SAAS,EAAE,UAAU,GAAG,SAAS,EACjC,UAAU,EAAE,UAAU,GAAG,SAAS,EAClC,UAAU,EAAE,QAAQ,GAAG,OAAO,GAAG,SAAS,GACzC,OAAO,CAkBT;AAED,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,OAAO,EACnB,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,SAAS,GACpC,OAAO,CAQT;AAED,wBAAgB,sBAAsB,CACpC,SAAS,CAAC,EAAE,UAAU,EACtB,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,GAClC,OAAO,CAYT;AAED,wBAAgB,UAAU,CACxB,aAAa,EAAE,8BAA8B,EAC7C,QAAQ,EAAE,QAAQ,GACjB,OAAO,CA4CT"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client.advanced.d.ts","sourceRoot":"","sources":["../../src/client/client.advanced.ts"],"names":[],"mappings":"AACA,OAAO,EAAQ,QAAQ,EAAU,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACrE,OAAO,EAAE,OAAO,EAAW,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,OAAO,EAAW,MAAM,iBAAiB,CAAC;AACnD,OAAO,EACL,8BAA8B,EAE/B,MAAM,2BAA2B,CAAC;AAGnC,wBAAgB,UAAU,CACxB,QAAQ,EAAE,OAAO,EACjB,UAAU,EAAE,OAAO,GAAG,SAAS,EAC/B,UAAU,EAAE,OAAO,GAAG,QAAQ,GAAG,SAAS,GACzC,OAAO,CAgBT;AAED,wBAAgB,YAAY,CAC1B,SAAS,EAAE,UAAU,GAAG,SAAS,EACjC,UAAU,EAAE,UAAU,GAAG,SAAS,EAClC,UAAU,EAAE,QAAQ,GAAG,OAAO,GAAG,SAAS,GACzC,OAAO,CAkBT;AAED,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,OAAO,EACnB,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,SAAS,GACpC,OAAO,CAQT;AAED,wBAAgB,sBAAsB,CACpC,SAAS,CAAC,EAAE,UAAU,EACtB,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,GAClC,OAAO,CAYT;AAED,wBAAgB,UAAU,CACxB,aAAa,EAAE,8BAA8B,EAC7C,QAAQ,EAAE,QAAQ,GACjB,OAAO,CA4CT"}
|