@lifi/composer-sdk 0.6.3 → 0.7.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.
@@ -39,6 +39,73 @@ export interface OutputHandle<T extends OutputKind = OutputKind> {
39
39
  readonly __outputKind?: T;
40
40
  }
41
41
 
42
+ /**
43
+ * What an output family's sizing parameter accepts, given the config field the
44
+ * family counts from: an array of that field's elements, or a number.
45
+ */
46
+ export type FamilySource<Field> = Field extends readonly (infer E)[]
47
+ ? readonly E[]
48
+ : number;
49
+
50
+ /** Whether a number literal is a valid family count: a non-negative integer. */
51
+ type IsCountLiteral<N extends number> = `${N}` extends
52
+ `-${string}` | `${string}.${string}` | `${string}e${string}`
53
+ ? false
54
+ : true;
55
+
56
+ /**
57
+ * `N` resource handles as a tuple. A non-literal `number`, or a literal that is
58
+ * not a valid count, gives an open array; {@link FamilyCount} rejects the
59
+ * invalid literal at the call site.
60
+ */
61
+ type HandleTuple<
62
+ N extends number,
63
+ Acc extends readonly OutputHandle<'resource'>[] = readonly [],
64
+ > = number extends N
65
+ ? readonly OutputHandle<'resource'>[]
66
+ : IsCountLiteral<N> extends false
67
+ ? readonly OutputHandle<'resource'>[]
68
+ : Acc['length'] extends N
69
+ ? Acc
70
+ : HandleTuple<N, readonly [...Acc, OutputHandle<'resource'>]>;
71
+
72
+ /**
73
+ * The handles of an output family: one resource {@link OutputHandle} per
74
+ * element of the config array the family counts from, or as many as the config
75
+ * count. A literal array or count yields a tuple of that length, so indexing
76
+ * past the last instance is a type error.
77
+ */
78
+ export type OutputFamilyHandles<TCount extends readonly unknown[] | number> =
79
+ TCount extends readonly unknown[]
80
+ ? { readonly [I in keyof TCount]: OutputHandle<'resource'> }
81
+ : TCount extends number
82
+ ? HandleTuple<TCount>
83
+ : never;
84
+
85
+ /**
86
+ * Holds the config value an output family counts from to the op's own type. A
87
+ * runtime-sized array or count passes as is. A literal tuple must also satisfy
88
+ * `Shape`, so a tuple shorter than the op's `minItems` fails at the call site
89
+ * instead of at the server's bind step. A literal count must be a non-negative
90
+ * integer.
91
+ */
92
+ export type FamilyCount<
93
+ TCount extends readonly unknown[] | number,
94
+ Shape,
95
+ > = TCount extends readonly unknown[]
96
+ ? number extends TCount['length']
97
+ ? unknown
98
+ : TCount extends Shape
99
+ ? unknown
100
+ : { readonly 'output family config array has too few entries': never }
101
+ : TCount extends number
102
+ ? IsCountLiteral<TCount> extends true
103
+ ? unknown
104
+ : {
105
+ readonly 'output family count must be a non-negative integer': never;
106
+ }
107
+ : unknown;
108
+
42
109
  /** Discriminated union of all handle types that can be bound to operation arguments. */
43
110
  export type AnyHandle = InputHandle | OutputHandle;
44
111
 
@@ -18,8 +18,8 @@ const STEAKHOUSE_USDC = '0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB';
18
18
  * Split USDC 60/40 and zap each portion into a different vault.
19
19
  *
20
20
  * Demonstrates:
21
- * - core.split to divide a resource by basis-point ratio
22
- * - Threading split outputs into two independent lifi.zap nodes
21
+ * - core.partition to divide a resource into one part per basis-point share
22
+ * - Destructuring the typed `parts` tuple into two independent lifi.zap nodes
23
23
  * - Slippage guards on both zap outputs
24
24
  */
25
25
  export const buildSplitAndZapExample = (): {
@@ -35,15 +35,16 @@ export const buildSplitAndZapExample = (): {
35
35
  },
36
36
  });
37
37
 
38
- // Split USDC 60/40 — 6000 bps to `a`, remainder to `b`.
39
- const { a, b } = builder.core.split('split', {
38
+ // Partition USDC 60/40 — one part per `bps` entry. Every part but the last
39
+ // is rounded down; the last takes the remainder.
40
+ const [toAave, toMorpho] = builder.core.partition('split', {
40
41
  bind: { source: builder.inputs.amountIn },
41
- config: { bps: 6000 },
42
- });
42
+ config: { bps: [6000, 4000] },
43
+ }).parts;
43
44
 
44
45
  // Zap 60% into Aave v3 aEthUSDC.
45
46
  builder.lifi.zap('zap-aave', {
46
- bind: { amountIn: a },
47
+ bind: { amountIn: toAave },
47
48
  config: {
48
49
  resourceOut: resources.erc20(A_ETH_USDC, 1),
49
50
  },
@@ -52,7 +53,7 @@ export const buildSplitAndZapExample = (): {
52
53
 
53
54
  // Zap 40% into Steakhouse USDC (Morpho).
54
55
  builder.lifi.zap('zap-morpho', {
55
- bind: { amountIn: b },
56
+ bind: { amountIn: toMorpho },
56
57
  config: {
57
58
  resourceOut: resources.erc20(STEAKHOUSE_USDC, 1),
58
59
  },