@lifi/composer-sdk 0.5.0 → 0.6.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/README.md +13 -3
- package/dist/authoring/FlowBuilderCore.cjs.map +1 -1
- package/dist/authoring/FlowBuilderCore.d.cts +11 -4
- package/dist/authoring/FlowBuilderCore.d.ts +11 -4
- package/dist/authoring/FlowBuilderCore.js.map +1 -1
- package/dist/authoring/handles.cjs.map +1 -1
- package/dist/authoring/handles.d.cts +2 -2
- package/dist/authoring/handles.d.ts +2 -2
- package/dist/authoring/handles.js.map +1 -1
- package/dist/authoring/raw.cjs +5 -3
- package/dist/authoring/raw.cjs.map +1 -1
- package/dist/authoring/raw.js +5 -3
- package/dist/authoring/raw.js.map +1 -1
- package/dist/client.cjs +94 -60
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +12 -4
- package/dist/client.d.ts +12 -4
- package/dist/client.js +98 -60
- package/dist/client.js.map +1 -1
- package/dist/errors.cjs +42 -3
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.d.cts +67 -4
- package/dist/errors.d.ts +67 -4
- package/dist/errors.js +29 -2
- package/dist/errors.js.map +1 -1
- package/dist/generated/config.generated.cjs.map +1 -1
- package/dist/generated/config.generated.d.cts +46 -5
- package/dist/generated/config.generated.d.ts +46 -5
- package/dist/generated/operations.generated.cjs +4 -0
- package/dist/generated/operations.generated.cjs.map +1 -1
- package/dist/generated/operations.generated.d.cts +16 -2
- package/dist/generated/operations.generated.d.ts +16 -2
- package/dist/generated/operations.generated.js +4 -0
- package/dist/generated/operations.generated.js.map +1 -1
- package/dist/index.cjs +8 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.js +11 -2
- package/dist/index.js.map +1 -1
- package/dist/outputs.cjs +33 -0
- package/dist/outputs.cjs.map +1 -0
- package/dist/outputs.d.cts +10 -0
- package/dist/outputs.d.ts +10 -0
- package/dist/outputs.js +9 -0
- package/dist/outputs.js.map +1 -0
- package/dist/responseSchemas.cjs +3 -0
- package/dist/responseSchemas.cjs.map +1 -1
- package/dist/responseSchemas.d.cts +7 -4
- package/dist/responseSchemas.d.ts +7 -4
- package/dist/responseSchemas.js +3 -0
- package/dist/responseSchemas.js.map +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +16 -5
- package/dist/types.d.ts +16 -5
- package/package.json +4 -3
- package/src/authoring/FlowBuilderCore.ts +12 -3
- package/src/authoring/handles.ts +2 -1
- package/src/authoring/raw.ts +4 -3
- package/src/client.ts +177 -79
- package/src/errors.ts +116 -3
- package/src/examples/flySwap.ts +3 -3
- package/src/examples/lifiZapAsync.ts +8 -7
- package/src/examples/run.ts +6 -9
- package/src/examples/swapAndZap.ts +7 -0
- package/src/examples/swapWithAllowRevert.ts +13 -3
- package/src/generated/config.generated.ts +49 -4
- package/src/generated/operations.generated.ts +25 -0
- package/src/index.ts +21 -3
- package/src/outputs.ts +16 -0
- package/src/responseSchemas.ts +10 -4
- package/src/types.ts +16 -4
|
@@ -91,18 +91,28 @@ export const handleCompileResult = async (): Promise<void> => {
|
|
|
91
91
|
|
|
92
92
|
if (result.status === 'success') {
|
|
93
93
|
// Full success — transactionRequest includes gasLimit.
|
|
94
|
-
const { transactionRequest, userProxy,
|
|
94
|
+
const { transactionRequest, userProxy, outputs } = result;
|
|
95
95
|
void transactionRequest;
|
|
96
96
|
void userProxy;
|
|
97
|
-
|
|
97
|
+
// Every linear resource output port appears in `outputs`, keyed
|
|
98
|
+
// `<nodeId>.<port>`. The swap's terminal output carries the amount.
|
|
99
|
+
const swapOut = outputs['swap.amountOut'];
|
|
100
|
+
void swapOut?.amount.estimate?.value; // simulated estimate on a 200
|
|
101
|
+
void swapOut?.amount.minimum?.value; // enforced floor, absent if none known
|
|
98
102
|
return;
|
|
99
103
|
}
|
|
100
104
|
|
|
101
105
|
// Partial result — simulation reverted but a transaction is still available.
|
|
102
106
|
// transactionRequest omits gasLimit; the caller must estimate gas themselves.
|
|
103
|
-
const { transactionRequest, simulationRevert, error } = result;
|
|
107
|
+
const { transactionRequest, outputs, simulationRevert, error } = result;
|
|
104
108
|
void transactionRequest;
|
|
105
109
|
|
|
110
|
+
// Nothing was measured, so the estimate is a quote and the minimum is
|
|
111
|
+
// op-sourced (or absent) rather than a guard floor.
|
|
112
|
+
const swapOut = outputs['swap.amountOut'];
|
|
113
|
+
void swapOut?.amount.estimate?.value; // quoted on a 206
|
|
114
|
+
void swapOut?.amount.minimum?.value; // op/declared floor, absent if none
|
|
115
|
+
|
|
106
116
|
// Inspect the revert reason.
|
|
107
117
|
void simulationRevert.code;
|
|
108
118
|
void simulationRevert.rawErrorBytes;
|
|
@@ -60,6 +60,55 @@ export interface LifiSwapConfig {
|
|
|
60
60
|
};
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
+
/**
|
|
64
|
+
* a string starting with "0x"
|
|
65
|
+
*/
|
|
66
|
+
export type StartsWith0X = string;
|
|
67
|
+
/**
|
|
68
|
+
* a number between 0 and 1
|
|
69
|
+
*/
|
|
70
|
+
export type Between01 = number;
|
|
71
|
+
|
|
72
|
+
export interface LifiBridgeConfig {
|
|
73
|
+
resourceOut:
|
|
74
|
+
| {
|
|
75
|
+
kind: 'native';
|
|
76
|
+
chainId: Positive;
|
|
77
|
+
}
|
|
78
|
+
| {
|
|
79
|
+
kind: 'erc20';
|
|
80
|
+
token: Address;
|
|
81
|
+
chainId: Positive;
|
|
82
|
+
};
|
|
83
|
+
destination: StartsWith0X;
|
|
84
|
+
slippage?: Between01;
|
|
85
|
+
timing?: {
|
|
86
|
+
swapStepTimingStrategies?: {
|
|
87
|
+
strategy: 'minWaitTime';
|
|
88
|
+
minWaitTimeMs: number;
|
|
89
|
+
startingExpectedResults: number;
|
|
90
|
+
reduceEveryMs: number;
|
|
91
|
+
}[];
|
|
92
|
+
routeTimingStrategies?: {
|
|
93
|
+
strategy: 'minWaitTime';
|
|
94
|
+
minWaitTimeMs: number;
|
|
95
|
+
startingExpectedResults: number;
|
|
96
|
+
reduceEveryMs: number;
|
|
97
|
+
}[];
|
|
98
|
+
};
|
|
99
|
+
bridges?: {
|
|
100
|
+
allow?: MaxItems50;
|
|
101
|
+
deny?: MaxItems50;
|
|
102
|
+
prefer?: MaxItems50;
|
|
103
|
+
};
|
|
104
|
+
exchanges?: {
|
|
105
|
+
allow?: MaxItems50;
|
|
106
|
+
deny?: MaxItems50;
|
|
107
|
+
prefer?: MaxItems50;
|
|
108
|
+
};
|
|
109
|
+
order?: 'FASTEST' | 'CHEAPEST';
|
|
110
|
+
}
|
|
111
|
+
|
|
63
112
|
export interface InvariantNumericConfig {
|
|
64
113
|
op: 'gte' | 'gt' | 'lte' | 'lt' | 'eq' | 'neq';
|
|
65
114
|
threshold: IntegerStringInput;
|
|
@@ -671,10 +720,6 @@ export type ContinuationAssertReadyConfig =
|
|
|
671
720
|
comparator: 'gte' | 'eq' | 'lte';
|
|
672
721
|
value: string;
|
|
673
722
|
};
|
|
674
|
-
/**
|
|
675
|
-
* a string starting with "0x"
|
|
676
|
-
*/
|
|
677
|
-
export type StartsWith0X = string;
|
|
678
723
|
|
|
679
724
|
export interface LifiZapConfig {
|
|
680
725
|
resourceOut:
|
|
@@ -44,6 +44,7 @@ import type {
|
|
|
44
44
|
InvariantNeqConfig,
|
|
45
45
|
InvariantNumericConfig,
|
|
46
46
|
InvariantNumericInRangeConfig,
|
|
47
|
+
LifiBridgeConfig,
|
|
47
48
|
LifiSwapConfig,
|
|
48
49
|
LifiZapAsyncConfig,
|
|
49
50
|
LifiZapConfig,
|
|
@@ -79,6 +80,15 @@ export interface LifiSwapArgs {
|
|
|
79
80
|
readonly guards?: readonly TypedGuard<'unspentIn'>[];
|
|
80
81
|
}
|
|
81
82
|
|
|
83
|
+
/** Bridge tokens to another chain via the LI.FI aggregator API */
|
|
84
|
+
export interface LifiBridgeArgs {
|
|
85
|
+
readonly bind: {
|
|
86
|
+
readonly amountIn: Bindable<'resource'>;
|
|
87
|
+
};
|
|
88
|
+
readonly config: LifiBridgeConfig;
|
|
89
|
+
readonly guards?: readonly TypedGuard<'unspentIn'>[];
|
|
90
|
+
}
|
|
91
|
+
|
|
82
92
|
/** Assert that an account holds at least a minimum token balance */
|
|
83
93
|
export interface InvariantBalanceAtLeastArgs {
|
|
84
94
|
readonly bind: {
|
|
@@ -574,6 +584,11 @@ export interface LifiSwapOutputs {
|
|
|
574
584
|
readonly unspentIn: OutputHandle<'resource'>;
|
|
575
585
|
}
|
|
576
586
|
|
|
587
|
+
export interface LifiBridgeOutputs {
|
|
588
|
+
readonly amountOut: OutputHandle<'resource'>;
|
|
589
|
+
readonly unspentIn: OutputHandle<'resource'>;
|
|
590
|
+
}
|
|
591
|
+
|
|
577
592
|
export interface CoreAddOutputs {
|
|
578
593
|
readonly result: OutputHandle<'uint256'>;
|
|
579
594
|
}
|
|
@@ -767,6 +782,11 @@ export type GeneratedOps = {
|
|
|
767
782
|
readonly lifi: {
|
|
768
783
|
/** Swap tokens via the LI.FI aggregator API — original id: "lifi.swap" */
|
|
769
784
|
readonly swap: (nodeId: string, args: LifiSwapArgs) => LifiSwapOutputs;
|
|
785
|
+
/** Bridge tokens to another chain via the LI.FI aggregator API — original id: "lifi.bridge" */
|
|
786
|
+
readonly bridge: (
|
|
787
|
+
nodeId: string,
|
|
788
|
+
args: LifiBridgeArgs,
|
|
789
|
+
) => LifiBridgeOutputs;
|
|
770
790
|
/** Route tokens into a DeFi protocol position via the edge catalog — original id: "lifi.zap" */
|
|
771
791
|
readonly zap: (nodeId: string, args: LifiZapArgs) => LifiZapOutputs;
|
|
772
792
|
/** Route tokens into a DeFi protocol position whose output becomes available after the initiating transaction settles — original id: "lifi.zapAsync" */
|
|
@@ -993,6 +1013,11 @@ export const bindGeneratedOps = (
|
|
|
993
1013
|
amountOut: 'resource',
|
|
994
1014
|
unspentIn: 'resource',
|
|
995
1015
|
} as const),
|
|
1016
|
+
bridge: (nodeId: string, args: LifiBridgeArgs) =>
|
|
1017
|
+
builder.call(nodeId, 'lifi.bridge', args, {
|
|
1018
|
+
amountOut: 'resource',
|
|
1019
|
+
unspentIn: 'resource',
|
|
1020
|
+
} as const),
|
|
996
1021
|
zap: (nodeId: string, args: LifiZapArgs) =>
|
|
997
1022
|
builder.call(nodeId, 'lifi.zap', args, {
|
|
998
1023
|
amountOut: 'resource',
|
package/src/index.ts
CHANGED
|
@@ -31,6 +31,8 @@ export type {
|
|
|
31
31
|
export type {
|
|
32
32
|
ComposeError,
|
|
33
33
|
ComposeErrorCode,
|
|
34
|
+
ComposeSdkOutdated,
|
|
35
|
+
ComposeServerOutdated,
|
|
34
36
|
ComposePreparationOps,
|
|
35
37
|
} from './errors.js';
|
|
36
38
|
export type {
|
|
@@ -53,16 +55,25 @@ export type {
|
|
|
53
55
|
InputSpec,
|
|
54
56
|
MaterialiserConfigOf,
|
|
55
57
|
MaterialiserInput,
|
|
58
|
+
OutputAmount,
|
|
59
|
+
Amount,
|
|
60
|
+
ConsumedOutput,
|
|
61
|
+
Delivery,
|
|
62
|
+
Estimate,
|
|
63
|
+
EstimateBasis,
|
|
64
|
+
Minimum,
|
|
65
|
+
MinimumBasis,
|
|
66
|
+
Output,
|
|
67
|
+
Outputs,
|
|
68
|
+
TerminalOutput,
|
|
56
69
|
Precondition,
|
|
57
70
|
PreconditionConfigOf,
|
|
58
71
|
PriceImpact,
|
|
59
|
-
ProducedResource,
|
|
60
72
|
Ref,
|
|
61
73
|
Resource,
|
|
62
74
|
RouteAmount,
|
|
63
75
|
RouteAmountAll,
|
|
64
76
|
RouteAmountExact,
|
|
65
|
-
SimulatedAmounts,
|
|
66
77
|
SimulationPolicy,
|
|
67
78
|
SimulationRevert,
|
|
68
79
|
SolType,
|
|
@@ -90,7 +101,12 @@ export {
|
|
|
90
101
|
SIMULATE_MAX_TRACKED_BALANCES,
|
|
91
102
|
SIMULATE_MAX_REQUIREMENTS,
|
|
92
103
|
} from '@lifi/compose-spec';
|
|
93
|
-
export {
|
|
104
|
+
export {
|
|
105
|
+
isComposeError,
|
|
106
|
+
isComposePreparationError,
|
|
107
|
+
isComposeSdkOutdatedError,
|
|
108
|
+
isComposeServerOutdatedError,
|
|
109
|
+
} from './errors.js';
|
|
94
110
|
|
|
95
111
|
export type {
|
|
96
112
|
Bindable,
|
|
@@ -113,6 +129,8 @@ export { materialiser } from './run/inputs.js';
|
|
|
113
129
|
export { buildSimulateRequest } from './run/simulate.js';
|
|
114
130
|
export type { BuildSimulateRequestInput } from './run/simulate.js';
|
|
115
131
|
|
|
132
|
+
export { terminalOutputs } from './outputs.js';
|
|
133
|
+
|
|
116
134
|
export { createComposeSdk } from './sdk.js';
|
|
117
135
|
export type { ComposeSdk, ComposeSdkOptions, FlowBuilder } from './sdk.js';
|
|
118
136
|
|
package/src/outputs.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Outputs, TerminalOutput } from '@lifi/compose-spec';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The entries of `outputs` the caller actually receives: every port no later
|
|
5
|
+
* node spends, keyed `<nodeId>.<portName>` as on the wire. Consumed ports
|
|
6
|
+
* (intermediate amounts a later op takes as input) are dropped.
|
|
7
|
+
*/
|
|
8
|
+
export const terminalOutputs = (
|
|
9
|
+
outputs: Outputs,
|
|
10
|
+
): Record<string, TerminalOutput> =>
|
|
11
|
+
Object.fromEntries(
|
|
12
|
+
Object.entries(outputs).filter(
|
|
13
|
+
(entry): entry is [string, TerminalOutput] =>
|
|
14
|
+
entry[1].role === 'terminal',
|
|
15
|
+
),
|
|
16
|
+
);
|
package/src/responseSchemas.ts
CHANGED
|
@@ -90,12 +90,12 @@ export const parseSimulateResult = (body: unknown): SimulateResult | null => {
|
|
|
90
90
|
|
|
91
91
|
/**
|
|
92
92
|
* The validated members of an HTTP 206 partial compile envelope. `data` is
|
|
93
|
-
* verified to be an object but
|
|
94
|
-
* (`ComposeCompilePartialData`) as a hand-authored type, so
|
|
95
|
-
* it. `error` is fully validated.
|
|
93
|
+
* verified to be an object at runtime but left `unknown` here — compose-spec
|
|
94
|
+
* owns its full shape (`ComposeCompilePartialData`) as a hand-authored type, so
|
|
95
|
+
* the caller narrows it in one step. `error` is fully validated.
|
|
96
96
|
*/
|
|
97
97
|
export interface CompilePartialEnvelope {
|
|
98
|
-
readonly data:
|
|
98
|
+
readonly data: unknown;
|
|
99
99
|
readonly error: { readonly kind: string; readonly message: string };
|
|
100
100
|
}
|
|
101
101
|
|
|
@@ -131,6 +131,9 @@ export interface ServerErrorBody {
|
|
|
131
131
|
readonly kind?: string;
|
|
132
132
|
readonly message?: string;
|
|
133
133
|
readonly path?: string;
|
|
134
|
+
readonly sdkVersion?: string;
|
|
135
|
+
readonly serverVersion?: string;
|
|
136
|
+
readonly minimumSdkVersion?: string;
|
|
134
137
|
readonly details?: SimulationRevert;
|
|
135
138
|
readonly failedOps?: readonly ServerFailedPreparedOp[];
|
|
136
139
|
readonly succeededOps?: readonly string[];
|
|
@@ -158,6 +161,9 @@ const serverErrorBodySchema = z.object({
|
|
|
158
161
|
kind: z.string().optional(),
|
|
159
162
|
message: z.string().optional(),
|
|
160
163
|
path: z.string().optional(),
|
|
164
|
+
sdkVersion: z.string().optional(),
|
|
165
|
+
serverVersion: z.string().optional(),
|
|
166
|
+
minimumSdkVersion: z.string().optional(),
|
|
161
167
|
details: z.custom<SimulationRevert>().optional(),
|
|
162
168
|
failedOps: z.array(failedPreparedOpSchema).readonly().optional(),
|
|
163
169
|
succeededOps: z.array(z.string()).readonly().optional(),
|
package/src/types.ts
CHANGED
|
@@ -48,14 +48,26 @@ export type AbiTypeToOutputKind<T extends string> = T extends SolType
|
|
|
48
48
|
? T
|
|
49
49
|
: SolType;
|
|
50
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Phantom brand key for {@link TypedRef}.
|
|
53
|
+
*
|
|
54
|
+
* Declared, never assigned: it exists only so the type checker can tell a
|
|
55
|
+
* typed ref from an arbitrary `{ $ref }` object. Keying it on a `unique
|
|
56
|
+
* symbol` means no caller can produce one by writing an object literal.
|
|
57
|
+
*/
|
|
58
|
+
export declare const typedRefKind: unique symbol;
|
|
59
|
+
|
|
51
60
|
/**
|
|
52
61
|
* A typed `$ref` pointer carrying a phantom type parameter.
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
62
|
+
*
|
|
63
|
+
* On the wire, and at run time, this is exactly `{ $ref: string }` — the
|
|
64
|
+
* brand is erased. The brand is *required* in the type so a plain `Ref` does
|
|
65
|
+
* not satisfy `TypedRef` structurally, which is the contract `RefBindable`
|
|
66
|
+
* advertises: an untyped `{ $ref }` never enters a typed bind slot. Build one
|
|
67
|
+
* with `raw.ref<T>()`.
|
|
56
68
|
*/
|
|
57
69
|
export interface TypedRef<T extends OutputKind = OutputKind> extends Ref {
|
|
58
|
-
readonly
|
|
70
|
+
readonly [typedRefKind]: T;
|
|
59
71
|
}
|
|
60
72
|
|
|
61
73
|
/**
|