@aboutcircles/sdk-pathfinder 0.1.5 → 0.1.6
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/flowMatrix.d.ts +19 -1
- package/dist/flowMatrix.d.ts.map +1 -1
- package/dist/flowMatrix.js +80 -13
- package/dist/index.js +2 -3823
- package/dist/packing.js +1 -1
- package/dist/path.d.ts.map +1 -1
- package/dist/path.js +1 -1
- package/package.json +3 -4
package/dist/flowMatrix.d.ts
CHANGED
|
@@ -1,6 +1,24 @@
|
|
|
1
|
-
import type { FlowMatrix, TransferStep, Address } from '@aboutcircles/sdk-types';
|
|
1
|
+
import type { FlowMatrix, TransferStep, Address, Hex } from '@aboutcircles/sdk-types';
|
|
2
2
|
/**
|
|
3
3
|
* Create an ABI‑ready FlowMatrix object from a list of TransferSteps.
|
|
4
|
+
*
|
|
5
|
+
* @param from - Sender address
|
|
6
|
+
* @param to - Receiver address
|
|
7
|
+
* @param value - Total value to transfer
|
|
8
|
+
* @param transfers - List of transfer steps
|
|
4
9
|
*/
|
|
5
10
|
export declare function createFlowMatrix(from: Address, to: Address, value: bigint, transfers: TransferStep[]): FlowMatrix;
|
|
11
|
+
/**
|
|
12
|
+
* Prepare flow matrix streams with hex-encoded data for ABI encoding
|
|
13
|
+
* Converts Uint8Array data to hex strings and adds optional txData to the first stream
|
|
14
|
+
*
|
|
15
|
+
* @param flowMatrix - The flow matrix to prepare
|
|
16
|
+
* @param txData - Optional transaction data to attach to the first stream
|
|
17
|
+
* @returns Array of streams with hex-encoded data ready for contract calls
|
|
18
|
+
*/
|
|
19
|
+
export declare function prepareFlowMatrixStreams(flowMatrix: FlowMatrix, txData?: Hex | Uint8Array): Array<{
|
|
20
|
+
sourceCoordinate: number;
|
|
21
|
+
flowEdgeIds: readonly number[];
|
|
22
|
+
data: Hex;
|
|
23
|
+
}>;
|
|
6
24
|
//# sourceMappingURL=flowMatrix.d.ts.map
|
package/dist/flowMatrix.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flowMatrix.d.ts","sourceRoot":"","sources":["../src/flowMatrix.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,EAAgC,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"flowMatrix.d.ts","sourceRoot":"","sources":["../src/flowMatrix.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,EAAgC,GAAG,EAAE,MAAM,yBAAyB,CAAC;AAsDpH;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,OAAO,EACb,EAAE,EAAE,OAAO,EACX,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,YAAY,EAAE,GACxB,UAAU,CAiEZ;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,UAAU,EACtB,MAAM,CAAC,EAAE,GAAG,GAAG,UAAU,GACxB,KAAK,CAAC;IAAE,gBAAgB,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,IAAI,EAAE,GAAG,CAAA;CAAE,CAAC,CAiBhF"}
|
package/dist/flowMatrix.js
CHANGED
|
@@ -1,30 +1,73 @@
|
|
|
1
1
|
import { packCoordinates, transformToFlowVertices } from './packing';
|
|
2
|
+
import { bytesToHex } from '@aboutcircles/sdk-utils/bytes';
|
|
3
|
+
/**
|
|
4
|
+
* Detect terminal edges using graph analysis
|
|
5
|
+
*
|
|
6
|
+
* Terminal edge detection algorithm:
|
|
7
|
+
* 1. Identify all edges that deliver value to the receiver
|
|
8
|
+
* 2. Check if there's a self-loop at the receiver (aggregate pattern)
|
|
9
|
+
* 3. If self-loop exists: it's the ONLY terminal edge (aggregates all incoming flows)
|
|
10
|
+
* 4. If no self-loop: all edges TO receiver are terminal (standard multi-path flow)
|
|
11
|
+
*
|
|
12
|
+
* This handles:
|
|
13
|
+
* - Aggregate mode: receiver collects tokens, then self-transfers to consolidate
|
|
14
|
+
* - Standard mode: multiple paths deliver directly to receiver
|
|
15
|
+
* - Mixed scenarios: correctly identifies final delivery point
|
|
16
|
+
*/
|
|
17
|
+
function detectTerminalEdges(transfers, receiver) {
|
|
18
|
+
const terminalEdges = new Set();
|
|
19
|
+
// Build adjacency info: track edges TO receiver and self-loops
|
|
20
|
+
const edgesToReceiver = [];
|
|
21
|
+
let selfLoopIndex = null;
|
|
22
|
+
transfers.forEach((t, index) => {
|
|
23
|
+
const fromLower = t.from.toLowerCase();
|
|
24
|
+
const toLower = t.to.toLowerCase();
|
|
25
|
+
// Check if this is a self-loop at the receiver
|
|
26
|
+
if (fromLower === receiver && toLower === receiver) {
|
|
27
|
+
selfLoopIndex = index;
|
|
28
|
+
}
|
|
29
|
+
// Check if this edge delivers to receiver
|
|
30
|
+
else if (toLower === receiver) {
|
|
31
|
+
edgesToReceiver.push(index);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
// Decision logic:
|
|
35
|
+
// If self-loop exists, it's the aggregation edge (ONLY terminal)
|
|
36
|
+
// Otherwise, all edges delivering to receiver are terminal
|
|
37
|
+
if (selfLoopIndex !== null) {
|
|
38
|
+
terminalEdges.add(selfLoopIndex);
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
edgesToReceiver.forEach(idx => terminalEdges.add(idx));
|
|
42
|
+
}
|
|
43
|
+
return terminalEdges;
|
|
44
|
+
}
|
|
2
45
|
/**
|
|
3
46
|
* Create an ABI‑ready FlowMatrix object from a list of TransferSteps.
|
|
47
|
+
*
|
|
48
|
+
* @param from - Sender address
|
|
49
|
+
* @param to - Receiver address
|
|
50
|
+
* @param value - Total value to transfer
|
|
51
|
+
* @param transfers - List of transfer steps
|
|
4
52
|
*/
|
|
5
53
|
export function createFlowMatrix(from, to, value, transfers) {
|
|
6
54
|
const sender = from.toLowerCase();
|
|
7
55
|
const receiver = to.toLowerCase();
|
|
8
56
|
const { sorted: flowVertices, idx } = transformToFlowVertices(transfers, sender, receiver);
|
|
9
|
-
|
|
10
|
-
|
|
57
|
+
// Use graph analysis to detect terminal edges
|
|
58
|
+
const terminalEdgeIndices = detectTerminalEdges(transfers, receiver);
|
|
59
|
+
const flowEdges = transfers.map((t, index) => {
|
|
60
|
+
const isTerminal = terminalEdgeIndices.has(index);
|
|
11
61
|
return {
|
|
12
62
|
streamSinkId: isTerminal ? 1 : 0,
|
|
13
63
|
amount: t.value
|
|
14
64
|
};
|
|
15
65
|
});
|
|
16
|
-
//
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const lastEdgeIndex = transfers
|
|
20
|
-
.map((t) => t.to.toLowerCase())
|
|
21
|
-
.lastIndexOf(receiver);
|
|
22
|
-
const fallbackIndex = lastEdgeIndex === -1 ? flowEdges.length - 1 : lastEdgeIndex;
|
|
23
|
-
flowEdges[fallbackIndex].streamSinkId = 1;
|
|
66
|
+
// Validation: ensure at least one terminal edge exists
|
|
67
|
+
if (terminalEdgeIndices.size === 0) {
|
|
68
|
+
throw new Error(`No terminal edges detected. Flow must have at least one edge delivering to receiver ${receiver}`);
|
|
24
69
|
}
|
|
25
|
-
const termEdgeIds =
|
|
26
|
-
.map((e, i) => (e.streamSinkId === 1 ? i : -1))
|
|
27
|
-
.filter((i) => i !== -1);
|
|
70
|
+
const termEdgeIds = Array.from(terminalEdgeIndices);
|
|
28
71
|
const streams = [
|
|
29
72
|
{
|
|
30
73
|
sourceCoordinate: idx[sender],
|
|
@@ -55,3 +98,27 @@ export function createFlowMatrix(from, to, value, transfers) {
|
|
|
55
98
|
sourceCoordinate: idx[sender]
|
|
56
99
|
};
|
|
57
100
|
}
|
|
101
|
+
/**
|
|
102
|
+
* Prepare flow matrix streams with hex-encoded data for ABI encoding
|
|
103
|
+
* Converts Uint8Array data to hex strings and adds optional txData to the first stream
|
|
104
|
+
*
|
|
105
|
+
* @param flowMatrix - The flow matrix to prepare
|
|
106
|
+
* @param txData - Optional transaction data to attach to the first stream
|
|
107
|
+
* @returns Array of streams with hex-encoded data ready for contract calls
|
|
108
|
+
*/
|
|
109
|
+
export function prepareFlowMatrixStreams(flowMatrix, txData) {
|
|
110
|
+
const streams = flowMatrix.streams.map((stream) => ({
|
|
111
|
+
sourceCoordinate: stream.sourceCoordinate,
|
|
112
|
+
flowEdgeIds: stream.flowEdgeIds,
|
|
113
|
+
data: stream.data instanceof Uint8Array
|
|
114
|
+
? bytesToHex(stream.data)
|
|
115
|
+
: stream.data,
|
|
116
|
+
}));
|
|
117
|
+
// Attach txData to the first stream if provided
|
|
118
|
+
if (txData && streams.length > 0) {
|
|
119
|
+
streams[0].data = txData instanceof Uint8Array
|
|
120
|
+
? bytesToHex(txData)
|
|
121
|
+
: txData;
|
|
122
|
+
}
|
|
123
|
+
return streams;
|
|
124
|
+
}
|