@lifi/composer-sdk 0.2.0-staging.3 → 0.2.0-staging.5

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.
Files changed (40) hide show
  1. package/dist/authoring/handles.cjs.map +1 -1
  2. package/dist/authoring/handles.d.cts +13 -6
  3. package/dist/authoring/handles.d.ts +13 -6
  4. package/dist/authoring/handles.js.map +1 -1
  5. package/dist/client.cjs +1 -1
  6. package/dist/client.js +1 -1
  7. package/dist/generated/config.generated.cjs.map +1 -1
  8. package/dist/generated/config.generated.d.cts +39 -1
  9. package/dist/generated/config.generated.d.ts +39 -1
  10. package/dist/generated/operations.generated.cjs +55 -1
  11. package/dist/generated/operations.generated.cjs.map +1 -1
  12. package/dist/generated/operations.generated.d.cts +204 -2
  13. package/dist/generated/operations.generated.d.ts +204 -2
  14. package/dist/generated/operations.generated.js +55 -1
  15. package/dist/generated/operations.generated.js.map +1 -1
  16. package/dist/index.d.cts +1 -1
  17. package/dist/index.d.ts +1 -1
  18. package/package.json +3 -4
  19. package/src/authoring/handles.ts +19 -10
  20. package/src/examples/aaveRepay.ts +55 -16
  21. package/src/examples/aaveRepayWithATokens.ts +41 -30
  22. package/src/examples/aaveRounding.ts +42 -0
  23. package/src/examples/aaveSetEMode.ts +0 -1
  24. package/src/examples/config.ts +1 -1
  25. package/src/examples/emitCustomEvent.ts +75 -0
  26. package/src/examples/invariantChecks.ts +96 -0
  27. package/src/examples/run.ts +20 -18
  28. package/src/examples/staged/aaveBorrow.ts +128 -0
  29. package/src/examples/staged/aaveDebtRebalanceExactOut.ts +301 -0
  30. package/src/examples/staged/aaveHealthFactorExplode.ts +70 -0
  31. package/src/examples/staged/aaveToMorphoDebtMigration.ts +200 -0
  32. package/src/examples/staged/aaveToMorphoDebtMigrationWithSwap.ts +231 -0
  33. package/src/examples/staged/aaveToMorphoDebtMigrationWithSwapExactOut.ts +307 -0
  34. package/src/examples/staged/flashloanRepay.ts +142 -0
  35. package/src/examples/staged/morphoBlueBorrow.ts +93 -0
  36. package/src/examples/staged/morphoBlueRepay.ts +132 -0
  37. package/src/examples/staged/registry.ts +80 -0
  38. package/src/examples/untypedOpWithTypedRef.ts +26 -20
  39. package/src/generated/config.generated.ts +50 -0
  40. package/src/generated/operations.generated.ts +330 -0
@@ -0,0 +1,80 @@
1
+ // Registry of staged (not-yet-prod) examples for the live runner. This is data,
2
+ // not a runner: src/examples/run.ts imports it via a non-literal dynamic import
3
+ // when invoked with `--staged`, so this file (which references staged definitions)
4
+ // is never pulled into the production type-check. It IS type-checked under
5
+ // tsconfig.staged.json (see verify:staged).
6
+ //
7
+ // Running these requires the SDK regenerated with `--staged`; the example:staged
8
+ // wrapper does that and restores production afterward.
9
+ import type { ComposeCompileRequest } from '@lifi/compose-spec';
10
+
11
+ import { OWNER, RECIPIENT } from '../config.js';
12
+
13
+ import { buildAaveBorrow } from './aaveBorrow.js';
14
+ import { buildAaveDebtRebalanceExactOut } from './aaveDebtRebalanceExactOut.js';
15
+ import { buildAaveHealthFactorExplode } from './aaveHealthFactorExplode.js';
16
+ import { buildAaveToMorphoDebtMigration } from './aaveToMorphoDebtMigration.js';
17
+ import { buildAaveToMorphoDebtMigrationWithSwap } from './aaveToMorphoDebtMigrationWithSwap.js';
18
+ import { buildAaveToMorphoDebtMigrationWithSwapExactOut } from './aaveToMorphoDebtMigrationWithSwapExactOut.js';
19
+ import { buildTrivialFlashloanRepay } from './flashloanRepay.js';
20
+ import { buildMorphoBlueBorrow } from './morphoBlueBorrow.js';
21
+ import { buildMorphoBlueRepay } from './morphoBlueRepay.js';
22
+
23
+ export const STAGED_EXAMPLES: Record<string, () => ComposeCompileRequest> = {
24
+ 'aave-borrow': () =>
25
+ buildAaveBorrow({
26
+ owner: OWNER,
27
+ recipient: RECIPIENT,
28
+ collateralAmount: '1000000000',
29
+ borrowAmount: '500000000',
30
+ }).request,
31
+ 'aave-hf-explode': () =>
32
+ buildAaveHealthFactorExplode({ signer: OWNER }).request,
33
+ 'morpho-borrow': () =>
34
+ buildMorphoBlueBorrow({
35
+ owner: OWNER,
36
+ collateralAmount: '1000000000000000000',
37
+ borrowAmount: '1200000000',
38
+ }).request,
39
+ 'morpho-repay': () =>
40
+ buildMorphoBlueRepay({
41
+ owner: OWNER,
42
+ collateralAmount: '1000000000000000000',
43
+ borrowAmount: '500000000',
44
+ repayAmount: '501000000',
45
+ }).request,
46
+ 'debt-rebalance': () =>
47
+ buildAaveDebtRebalanceExactOut({
48
+ owner: OWNER,
49
+ collateralAmount: '1000000000000000000',
50
+ debtAmount: '1000000000',
51
+ newDebtBorrowAmount: '965000000',
52
+ }).request,
53
+ 'debt-migration-swap-exact-out': () =>
54
+ buildAaveToMorphoDebtMigrationWithSwapExactOut({
55
+ owner: OWNER,
56
+ collateralAmount: '1000000000000000000',
57
+ debtAmount: '1000000000',
58
+ morphoBorrowAmount: '975000000',
59
+ }).request,
60
+ 'flashloan-repay': () =>
61
+ buildTrivialFlashloanRepay({
62
+ owner: OWNER,
63
+ amount: '10000000000',
64
+ fee: '5000000',
65
+ }).request,
66
+ 'debt-migration': () =>
67
+ buildAaveToMorphoDebtMigration({
68
+ owner: OWNER,
69
+ collateralAmount: '1000000000000000000',
70
+ debtAmount: '1000000000',
71
+ debtFlashloanFee: '500000',
72
+ }).request,
73
+ 'debt-migration-swap': () =>
74
+ buildAaveToMorphoDebtMigrationWithSwap({
75
+ owner: OWNER,
76
+ collateralAmount: '1000000000000000000',
77
+ debtAmount: '1000000000',
78
+ morphoBorrowAmount: '1100000000',
79
+ }).request,
80
+ };
@@ -1,25 +1,32 @@
1
1
  import type { ComposeCompileRequest, Flow } from '@lifi/compose-spec';
2
2
 
3
- import { createComposeSdk, materialisers, raw, resources } from '../index.js';
3
+ import { createComposeSdk, raw } from '../index.js';
4
4
  import type { Address } from '../types.js';
5
5
 
6
6
  import { BASE_URL } from './config.js';
7
7
 
8
- const USDC = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48';
9
- // Example custom vault that the typed builder doesn't cover yet
10
- const CUSTOM_VAULT = '0x1111111111111111111111111111111111111111';
8
+ // Real ERC-4626 vault (Steakhouse USDC on Ethereum mainnet) queried through
9
+ // the untyped escape hatch.
10
+ const VAULT = '0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB';
11
11
 
12
12
  export interface UntypedOpWithTypedRefInput {
13
13
  readonly owner: Address;
14
14
  }
15
15
 
16
16
  /**
17
- * Insert an untyped operation node for an unsupported operation, then feed
18
- * its output into typed builder methods using `raw.ref<T>()`.
17
+ * Insert an untyped operation node, then feed its output into typed builder
18
+ * methods using `raw.ref<T>()`.
19
+ *
20
+ * `untypedOp` is the escape hatch for ops the installed SDK's typed surface
21
+ * doesn't cover — typically backend ops newer than your SDK version. The op
22
+ * id is passed as a plain string and its bind/config shapes are not
23
+ * type-checked, so the backend validates them at compile time instead.
24
+ *
25
+ * This example routes a real op (`core.staticCall`) through the untyped path
26
+ * so the flow compiles end-to-end; the mechanism is identical for any op id.
19
27
  *
20
28
  * Demonstrates:
21
- * - `builder.untypedOp()` to add a node the typed API doesn't cover
22
- * (e.g. a custom vault query).
29
+ * - `builder.untypedOp()` to add a node the typed API doesn't cover.
23
30
  * - `raw.ref<'uint256'>()` to reference the untyped node's output in a typed
24
31
  * `Bindable<'uint256'>` slot — the explicit type parameter is required
25
32
  * so the compiler verifies the ref is used in a compatible slot.
@@ -35,16 +42,17 @@ export const buildUntypedOpWithTypedRef = ({
35
42
 
36
43
  const builder = sdk.flow(1, {
37
44
  name: 'untyped-op-with-typed-ref',
38
- inputs: {
39
- amountIn: resources.erc20(USDC, 1),
40
- },
45
+ inputs: {},
41
46
  });
42
47
 
43
- // Insert an untyped node for a custom vault query. untypedOp returns void —
48
+ // Insert an untyped node querying the vault. untypedOp returns void —
44
49
  // the typed builder has no knowledge of this node's outputs.
45
- builder.untypedOp('vault-query', 'custom.vaultQuery', {
46
- bind: { amount: { $ref: 'input.amountIn' } },
47
- config: { target: CUSTOM_VAULT },
50
+ builder.untypedOp('vault-query', 'core.staticCall', {
51
+ bind: {},
52
+ config: {
53
+ target: VAULT,
54
+ functionSignature: 'function totalAssets() view returns (uint256)',
55
+ },
48
56
  });
49
57
 
50
58
  // Use raw.ref to bridge the untyped node's output into a typed operation.
@@ -60,17 +68,15 @@ export const buildUntypedOpWithTypedRef = ({
60
68
 
61
69
  // Continue with fully typed operations downstream.
62
70
  builder.core.assertGte('check-min', {
63
- bind: { a: scaled.result, b: builder.inputs.amountIn },
71
+ bind: { a: scaled.result, b: vaultResult },
64
72
  });
65
73
 
66
74
  const flow = builder.build();
67
75
 
76
+ // No sweepTo: the flow reads state and asserts — it produces no resources.
68
77
  const request = sdk.request(flow, {
69
78
  signer: owner,
70
- inputs: {
71
- amountIn: materialisers.directDeposit({ amount: '1000000' }),
72
- },
73
- sweepTo: builder.context.sender,
79
+ inputs: {},
74
80
  });
75
81
 
76
82
  return { flow, request };
@@ -55,6 +55,40 @@ export interface LifiSwapConfig {
55
55
  };
56
56
  }
57
57
 
58
+ export interface InvariantNumericConfig {
59
+ op: 'gte' | 'gt' | 'lte' | 'lt' | 'eq' | 'neq';
60
+ threshold: IntegerStringInput;
61
+ }
62
+
63
+ export interface InvariantNumericInRangeConfig {
64
+ min: IntegerStringInput;
65
+ max: IntegerStringInput;
66
+ }
67
+
68
+ export interface InvariantGteConfig {
69
+ threshold: IntegerStringInput;
70
+ }
71
+
72
+ export interface InvariantGtConfig {
73
+ threshold: IntegerStringInput;
74
+ }
75
+
76
+ export interface InvariantLteConfig {
77
+ threshold: IntegerStringInput;
78
+ }
79
+
80
+ export interface InvariantLtConfig {
81
+ threshold: IntegerStringInput;
82
+ }
83
+
84
+ export interface InvariantEqConfig {
85
+ threshold: IntegerStringInput;
86
+ }
87
+
88
+ export interface InvariantNeqConfig {
89
+ threshold: IntegerStringInput;
90
+ }
91
+
58
92
  export interface CoreBpsDownConfig {
59
93
  bps: number;
60
94
  }
@@ -76,6 +110,22 @@ export interface CoreTransferConfig {
76
110
  amount?: IntegerStringInput;
77
111
  }
78
112
 
113
+ export interface CoreEmitEvent1Config {
114
+ signature: string;
115
+ }
116
+
117
+ export interface CoreEmitEvent2Config {
118
+ signature: string;
119
+ }
120
+
121
+ export interface CoreEmitEvent3Config {
122
+ signature: string;
123
+ }
124
+
125
+ export interface CoreEmitEvent4Config {
126
+ signature: string;
127
+ }
128
+
79
129
  export interface CoreCallConfig {
80
130
  target: Address;
81
131
  functionSignature: string;
@@ -30,11 +30,23 @@ import type {
30
30
  CoreBpsDownConfig,
31
31
  CoreBpsUpConfig,
32
32
  CoreCallConfig,
33
+ CoreEmitEvent1Config,
34
+ CoreEmitEvent2Config,
35
+ CoreEmitEvent3Config,
36
+ CoreEmitEvent4Config,
33
37
  CorePeekConfig,
34
38
  CoreRawCallConfig,
35
39
  CoreSplitConfig,
36
40
  CoreStaticCallConfig,
37
41
  CoreTransferConfig,
42
+ InvariantEqConfig,
43
+ InvariantGtConfig,
44
+ InvariantGteConfig,
45
+ InvariantLtConfig,
46
+ InvariantLteConfig,
47
+ InvariantNeqConfig,
48
+ InvariantNumericConfig,
49
+ InvariantNumericInRangeConfig,
38
50
  LifiFlashloanRepayConfig,
39
51
  LifiSwapConfig,
40
52
  LifiZapConfig,
@@ -84,6 +96,147 @@ export interface InvariantBalanceAtLeastArgs {
84
96
  readonly guards?: readonly TypedGuard<never>[];
85
97
  }
86
98
 
99
+ /** Assert that an account holds exactly an expected token balance */
100
+ export interface InvariantBalanceEqualsArgs {
101
+ readonly bind: {
102
+ readonly expectedAmount: Bindable<'resource'>;
103
+ readonly account: Bindable<'address'>;
104
+ };
105
+ readonly guards?: readonly TypedGuard<never>[];
106
+ }
107
+
108
+ /** Assert that an account holds at most a maximum token balance */
109
+ export interface InvariantBalanceAtMostArgs {
110
+ readonly bind: {
111
+ readonly maximumAmount: Bindable<'resource'>;
112
+ readonly account: Bindable<'address'>;
113
+ };
114
+ readonly guards?: readonly TypedGuard<never>[];
115
+ }
116
+
117
+ /** Assert that an account's token balance is between a minimum and a maximum (inclusive) */
118
+ export interface InvariantBalanceInRangeArgs {
119
+ readonly bind: {
120
+ readonly minimumAmount: Bindable<'resource'>;
121
+ readonly maximumAmount: Bindable<'uint256'>;
122
+ readonly account: Bindable<'address'>;
123
+ };
124
+ readonly guards?: readonly TypedGuard<never>[];
125
+ }
126
+
127
+ /** Assert that a spender is permitted to move at least a minimum allowance on behalf of an owner */
128
+ export interface InvariantAllowanceAtLeastArgs {
129
+ readonly bind: {
130
+ readonly minimumAmount: Bindable<'resource'>;
131
+ readonly owner: Bindable<'address'>;
132
+ readonly spender: Bindable<'address'>;
133
+ };
134
+ readonly guards?: readonly TypedGuard<never>[];
135
+ }
136
+
137
+ /** Assert that a spender's allowance on behalf of an owner exactly equals an expected amount */
138
+ export interface InvariantAllowanceEqualsArgs {
139
+ readonly bind: {
140
+ readonly expectedAmount: Bindable<'resource'>;
141
+ readonly owner: Bindable<'address'>;
142
+ readonly spender: Bindable<'address'>;
143
+ };
144
+ readonly guards?: readonly TypedGuard<never>[];
145
+ }
146
+
147
+ /** Assert that a spender is permitted to move at most a maximum allowance on behalf of an owner */
148
+ export interface InvariantAllowanceAtMostArgs {
149
+ readonly bind: {
150
+ readonly maximumAmount: Bindable<'resource'>;
151
+ readonly owner: Bindable<'address'>;
152
+ readonly spender: Bindable<'address'>;
153
+ };
154
+ readonly guards?: readonly TypedGuard<never>[];
155
+ }
156
+
157
+ /** Assert that a spender's allowance on behalf of an owner is between a minimum and a maximum (inclusive) */
158
+ export interface InvariantAllowanceInRangeArgs {
159
+ readonly bind: {
160
+ readonly minimumAmount: Bindable<'resource'>;
161
+ readonly maximumAmount: Bindable<'uint256'>;
162
+ readonly owner: Bindable<'address'>;
163
+ readonly spender: Bindable<'address'>;
164
+ };
165
+ readonly guards?: readonly TypedGuard<never>[];
166
+ }
167
+
168
+ /** Assert a uint256 value satisfies a comparison against a constant threshold; reverts on violation */
169
+ export interface InvariantNumericArgs {
170
+ readonly bind: {
171
+ readonly value: Bindable<'uint256'>;
172
+ };
173
+ readonly config: InvariantNumericConfig;
174
+ readonly guards?: readonly TypedGuard<never>[];
175
+ }
176
+
177
+ /** Assert min <= value <= max against constant bounds; reverts if outside the range */
178
+ export interface InvariantNumericInRangeArgs {
179
+ readonly bind: {
180
+ readonly value: Bindable<'uint256'>;
181
+ };
182
+ readonly config: InvariantNumericInRangeConfig;
183
+ readonly guards?: readonly TypedGuard<never>[];
184
+ }
185
+
186
+ /** Assert a uint256 value is greater than or equal to a constant threshold; reverts on violation */
187
+ export interface InvariantGteArgs {
188
+ readonly bind: {
189
+ readonly value: Bindable<'uint256'>;
190
+ };
191
+ readonly config: InvariantGteConfig;
192
+ readonly guards?: readonly TypedGuard<never>[];
193
+ }
194
+
195
+ /** Assert a uint256 value is strictly greater than a constant threshold; reverts on violation */
196
+ export interface InvariantGtArgs {
197
+ readonly bind: {
198
+ readonly value: Bindable<'uint256'>;
199
+ };
200
+ readonly config: InvariantGtConfig;
201
+ readonly guards?: readonly TypedGuard<never>[];
202
+ }
203
+
204
+ /** Assert a uint256 value is less than or equal to a constant threshold; reverts on violation */
205
+ export interface InvariantLteArgs {
206
+ readonly bind: {
207
+ readonly value: Bindable<'uint256'>;
208
+ };
209
+ readonly config: InvariantLteConfig;
210
+ readonly guards?: readonly TypedGuard<never>[];
211
+ }
212
+
213
+ /** Assert a uint256 value is strictly less than a constant threshold; reverts on violation */
214
+ export interface InvariantLtArgs {
215
+ readonly bind: {
216
+ readonly value: Bindable<'uint256'>;
217
+ };
218
+ readonly config: InvariantLtConfig;
219
+ readonly guards?: readonly TypedGuard<never>[];
220
+ }
221
+
222
+ /** Assert a uint256 value equals a constant threshold; reverts on violation */
223
+ export interface InvariantEqArgs {
224
+ readonly bind: {
225
+ readonly value: Bindable<'uint256'>;
226
+ };
227
+ readonly config: InvariantEqConfig;
228
+ readonly guards?: readonly TypedGuard<never>[];
229
+ }
230
+
231
+ /** Assert a uint256 value does not equal a constant threshold; reverts on violation */
232
+ export interface InvariantNeqArgs {
233
+ readonly bind: {
234
+ readonly value: Bindable<'uint256'>;
235
+ };
236
+ readonly config: InvariantNeqConfig;
237
+ readonly guards?: readonly TypedGuard<never>[];
238
+ }
239
+
87
240
  /** Add two unsigned integers (a + b) */
88
241
  export interface CoreAddArgs {
89
242
  readonly bind: {
@@ -237,6 +390,48 @@ export interface CoreTransferArgs {
237
390
  readonly guards?: readonly TypedGuard<'transferred' | 'remainder'>[];
238
391
  }
239
392
 
393
+ /** Emit a custom on-chain event carrying 1 32-byte payload value. The value becomes a non-indexed data word in a fixed VM log event; the signature is hashed into a discriminator word (it is NOT an indexed EVM topic). */
394
+ export interface CoreEmitEvent1Args {
395
+ readonly bind: {
396
+ readonly value0: Bindable<'bytes32'>;
397
+ };
398
+ readonly config: CoreEmitEvent1Config;
399
+ readonly guards?: readonly TypedGuard<never>[];
400
+ }
401
+
402
+ /** Emit a custom on-chain event carrying 2 32-byte payload values. The values become non-indexed data words in a fixed VM log event; the signature is hashed into a discriminator word (it is NOT an indexed EVM topic). */
403
+ export interface CoreEmitEvent2Args {
404
+ readonly bind: {
405
+ readonly value0: Bindable<'bytes32'>;
406
+ readonly value1: Bindable<'bytes32'>;
407
+ };
408
+ readonly config: CoreEmitEvent2Config;
409
+ readonly guards?: readonly TypedGuard<never>[];
410
+ }
411
+
412
+ /** Emit a custom on-chain event carrying 3 32-byte payload values. The values become non-indexed data words in a fixed VM log event; the signature is hashed into a discriminator word (it is NOT an indexed EVM topic). */
413
+ export interface CoreEmitEvent3Args {
414
+ readonly bind: {
415
+ readonly value0: Bindable<'bytes32'>;
416
+ readonly value1: Bindable<'bytes32'>;
417
+ readonly value2: Bindable<'bytes32'>;
418
+ };
419
+ readonly config: CoreEmitEvent3Config;
420
+ readonly guards?: readonly TypedGuard<never>[];
421
+ }
422
+
423
+ /** Emit a custom on-chain event carrying 4 32-byte payload values. The values become non-indexed data words in a fixed VM log event; the signature is hashed into a discriminator word (it is NOT an indexed EVM topic). */
424
+ export interface CoreEmitEvent4Args {
425
+ readonly bind: {
426
+ readonly value0: Bindable<'bytes32'>;
427
+ readonly value1: Bindable<'bytes32'>;
428
+ readonly value2: Bindable<'bytes32'>;
429
+ readonly value3: Bindable<'bytes32'>;
430
+ };
431
+ readonly config: CoreEmitEvent4Config;
432
+ readonly guards?: readonly TypedGuard<never>[];
433
+ }
434
+
240
435
  /** Invoke a smart contract function, optionally spending a token resource */
241
436
  export interface CoreCallArgs<TSig extends string = string> {
242
437
  readonly resource?: Bindable<'resource'>;
@@ -616,6 +811,14 @@ export type GeneratedOps = {
616
811
  nodeId: string,
617
812
  args: CoreTransferArgs,
618
813
  ) => CoreTransferOutputs;
814
+ /** Emit a custom on-chain event carrying 1 32-byte payload value. The value becomes a non-indexed data word in a fixed VM log event; the signature is hashed into a discriminator word (it is NOT an indexed EVM topic). — original id: "core.emitEvent1" */
815
+ readonly emitEvent1: (nodeId: string, args: CoreEmitEvent1Args) => void;
816
+ /** Emit a custom on-chain event carrying 2 32-byte payload values. The values become non-indexed data words in a fixed VM log event; the signature is hashed into a discriminator word (it is NOT an indexed EVM topic). — original id: "core.emitEvent2" */
817
+ readonly emitEvent2: (nodeId: string, args: CoreEmitEvent2Args) => void;
818
+ /** Emit a custom on-chain event carrying 3 32-byte payload values. The values become non-indexed data words in a fixed VM log event; the signature is hashed into a discriminator word (it is NOT an indexed EVM topic). — original id: "core.emitEvent3" */
819
+ readonly emitEvent3: (nodeId: string, args: CoreEmitEvent3Args) => void;
820
+ /** Emit a custom on-chain event carrying 4 32-byte payload values. The values become non-indexed data words in a fixed VM log event; the signature is hashed into a discriminator word (it is NOT an indexed EVM topic). — original id: "core.emitEvent4" */
821
+ readonly emitEvent4: (nodeId: string, args: CoreEmitEvent4Args) => void;
619
822
  /** Invoke a smart contract function, optionally spending a token resource — original id: "core.call" */
620
823
  readonly call: <TSig extends string>(
621
824
  nodeId: string,
@@ -656,6 +859,60 @@ export type GeneratedOps = {
656
859
  nodeId: string,
657
860
  args: InvariantBalanceAtLeastArgs,
658
861
  ) => void;
862
+ /** Assert that an account holds exactly an expected token balance — original id: "invariant.balanceEquals" */
863
+ readonly balanceEquals: (
864
+ nodeId: string,
865
+ args: InvariantBalanceEqualsArgs,
866
+ ) => void;
867
+ /** Assert that an account holds at most a maximum token balance — original id: "invariant.balanceAtMost" */
868
+ readonly balanceAtMost: (
869
+ nodeId: string,
870
+ args: InvariantBalanceAtMostArgs,
871
+ ) => void;
872
+ /** Assert that an account's token balance is between a minimum and a maximum (inclusive) — original id: "invariant.balanceInRange" */
873
+ readonly balanceInRange: (
874
+ nodeId: string,
875
+ args: InvariantBalanceInRangeArgs,
876
+ ) => void;
877
+ /** Assert that a spender is permitted to move at least a minimum allowance on behalf of an owner — original id: "invariant.allowanceAtLeast" */
878
+ readonly allowanceAtLeast: (
879
+ nodeId: string,
880
+ args: InvariantAllowanceAtLeastArgs,
881
+ ) => void;
882
+ /** Assert that a spender's allowance on behalf of an owner exactly equals an expected amount — original id: "invariant.allowanceEquals" */
883
+ readonly allowanceEquals: (
884
+ nodeId: string,
885
+ args: InvariantAllowanceEqualsArgs,
886
+ ) => void;
887
+ /** Assert that a spender is permitted to move at most a maximum allowance on behalf of an owner — original id: "invariant.allowanceAtMost" */
888
+ readonly allowanceAtMost: (
889
+ nodeId: string,
890
+ args: InvariantAllowanceAtMostArgs,
891
+ ) => void;
892
+ /** Assert that a spender's allowance on behalf of an owner is between a minimum and a maximum (inclusive) — original id: "invariant.allowanceInRange" */
893
+ readonly allowanceInRange: (
894
+ nodeId: string,
895
+ args: InvariantAllowanceInRangeArgs,
896
+ ) => void;
897
+ /** Assert a uint256 value satisfies a comparison against a constant threshold; reverts on violation — original id: "invariant.numeric" */
898
+ readonly numeric: (nodeId: string, args: InvariantNumericArgs) => void;
899
+ /** Assert min <= value <= max against constant bounds; reverts if outside the range — original id: "invariant.numericInRange" */
900
+ readonly numericInRange: (
901
+ nodeId: string,
902
+ args: InvariantNumericInRangeArgs,
903
+ ) => void;
904
+ /** Assert a uint256 value is greater than or equal to a constant threshold; reverts on violation — original id: "invariant.gte" */
905
+ readonly gte: (nodeId: string, args: InvariantGteArgs) => void;
906
+ /** Assert a uint256 value is strictly greater than a constant threshold; reverts on violation — original id: "invariant.gt" */
907
+ readonly gt: (nodeId: string, args: InvariantGtArgs) => void;
908
+ /** Assert a uint256 value is less than or equal to a constant threshold; reverts on violation — original id: "invariant.lte" */
909
+ readonly lte: (nodeId: string, args: InvariantLteArgs) => void;
910
+ /** Assert a uint256 value is strictly less than a constant threshold; reverts on violation — original id: "invariant.lt" */
911
+ readonly lt: (nodeId: string, args: InvariantLtArgs) => void;
912
+ /** Assert a uint256 value equals a constant threshold; reverts on violation — original id: "invariant.eq" */
913
+ readonly eq: (nodeId: string, args: InvariantEqArgs) => void;
914
+ /** Assert a uint256 value does not equal a constant threshold; reverts on violation — original id: "invariant.neq" */
915
+ readonly neq: (nodeId: string, args: InvariantNeqArgs) => void;
659
916
  };
660
917
  readonly aave: {
661
918
  /** Borrow an asset from an Aave v3 pool against existing collateral, exposing the borrowed asset as a Resource — original id: "aave.borrow" */
@@ -790,6 +1047,14 @@ export const bindGeneratedOps = (
790
1047
  transferred: 'resource',
791
1048
  remainder: 'resource',
792
1049
  } as const),
1050
+ emitEvent1: (nodeId: string, args: CoreEmitEvent1Args) =>
1051
+ builder.call(nodeId, 'core.emitEvent1', args, {}),
1052
+ emitEvent2: (nodeId: string, args: CoreEmitEvent2Args) =>
1053
+ builder.call(nodeId, 'core.emitEvent2', args, {}),
1054
+ emitEvent3: (nodeId: string, args: CoreEmitEvent3Args) =>
1055
+ builder.call(nodeId, 'core.emitEvent3', args, {}),
1056
+ emitEvent4: (nodeId: string, args: CoreEmitEvent4Args) =>
1057
+ builder.call(nodeId, 'core.emitEvent4', args, {}),
793
1058
  call: <TSig extends string>(nodeId: string, args: CoreCallArgs<TSig>) => {
794
1059
  const wire = buildCallWireFormat({
795
1060
  resource: args.resource,
@@ -847,6 +1112,71 @@ export const bindGeneratedOps = (
847
1112
  { ...args, config: {} },
848
1113
  {},
849
1114
  ),
1115
+ balanceEquals: (nodeId: string, args: InvariantBalanceEqualsArgs) =>
1116
+ builder.call(
1117
+ nodeId,
1118
+ 'invariant.balanceEquals',
1119
+ { ...args, config: {} },
1120
+ {},
1121
+ ),
1122
+ balanceAtMost: (nodeId: string, args: InvariantBalanceAtMostArgs) =>
1123
+ builder.call(
1124
+ nodeId,
1125
+ 'invariant.balanceAtMost',
1126
+ { ...args, config: {} },
1127
+ {},
1128
+ ),
1129
+ balanceInRange: (nodeId: string, args: InvariantBalanceInRangeArgs) =>
1130
+ builder.call(
1131
+ nodeId,
1132
+ 'invariant.balanceInRange',
1133
+ { ...args, config: {} },
1134
+ {},
1135
+ ),
1136
+ allowanceAtLeast: (nodeId: string, args: InvariantAllowanceAtLeastArgs) =>
1137
+ builder.call(
1138
+ nodeId,
1139
+ 'invariant.allowanceAtLeast',
1140
+ { ...args, config: {} },
1141
+ {},
1142
+ ),
1143
+ allowanceEquals: (nodeId: string, args: InvariantAllowanceEqualsArgs) =>
1144
+ builder.call(
1145
+ nodeId,
1146
+ 'invariant.allowanceEquals',
1147
+ { ...args, config: {} },
1148
+ {},
1149
+ ),
1150
+ allowanceAtMost: (nodeId: string, args: InvariantAllowanceAtMostArgs) =>
1151
+ builder.call(
1152
+ nodeId,
1153
+ 'invariant.allowanceAtMost',
1154
+ { ...args, config: {} },
1155
+ {},
1156
+ ),
1157
+ allowanceInRange: (nodeId: string, args: InvariantAllowanceInRangeArgs) =>
1158
+ builder.call(
1159
+ nodeId,
1160
+ 'invariant.allowanceInRange',
1161
+ { ...args, config: {} },
1162
+ {},
1163
+ ),
1164
+ numeric: (nodeId: string, args: InvariantNumericArgs) =>
1165
+ builder.call(nodeId, 'invariant.numeric', args, {}),
1166
+ numericInRange: (nodeId: string, args: InvariantNumericInRangeArgs) =>
1167
+ builder.call(nodeId, 'invariant.numericInRange', args, {}),
1168
+ gte: (nodeId: string, args: InvariantGteArgs) =>
1169
+ builder.call(nodeId, 'invariant.gte', args, {}),
1170
+ gt: (nodeId: string, args: InvariantGtArgs) =>
1171
+ builder.call(nodeId, 'invariant.gt', args, {}),
1172
+ lte: (nodeId: string, args: InvariantLteArgs) =>
1173
+ builder.call(nodeId, 'invariant.lte', args, {}),
1174
+ lt: (nodeId: string, args: InvariantLtArgs) =>
1175
+ builder.call(nodeId, 'invariant.lt', args, {}),
1176
+ eq: (nodeId: string, args: InvariantEqArgs) =>
1177
+ builder.call(nodeId, 'invariant.eq', args, {}),
1178
+ neq: (nodeId: string, args: InvariantNeqArgs) =>
1179
+ builder.call(nodeId, 'invariant.neq', args, {}),
850
1180
  },
851
1181
  aave: {
852
1182
  borrow: (nodeId: string, args: AaveBorrowArgs) =>