@lifi/composer-sdk 0.4.0 → 0.5.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.
Files changed (106) hide show
  1. package/README.md +98 -5
  2. package/dist/authoring/FlowBuilderCore.cjs +1 -5
  3. package/dist/authoring/FlowBuilderCore.cjs.map +1 -1
  4. package/dist/authoring/FlowBuilderCore.d.cts +9 -7
  5. package/dist/authoring/FlowBuilderCore.d.ts +9 -7
  6. package/dist/authoring/FlowBuilderCore.js +2 -6
  7. package/dist/authoring/FlowBuilderCore.js.map +1 -1
  8. package/dist/authoring/handles.cjs +5 -2
  9. package/dist/authoring/handles.cjs.map +1 -1
  10. package/dist/authoring/handles.d.cts +25 -6
  11. package/dist/authoring/handles.d.ts +25 -6
  12. package/dist/authoring/handles.js +3 -1
  13. package/dist/authoring/handles.js.map +1 -1
  14. package/dist/authoring/raw.cjs +6 -1
  15. package/dist/authoring/raw.cjs.map +1 -1
  16. package/dist/authoring/raw.d.cts +33 -3
  17. package/dist/authoring/raw.d.ts +33 -3
  18. package/dist/authoring/raw.js +5 -1
  19. package/dist/authoring/raw.js.map +1 -1
  20. package/dist/authoring/signatureArgs.cjs.map +1 -1
  21. package/dist/authoring/signatureArgs.d.cts +16 -12
  22. package/dist/authoring/signatureArgs.d.ts +16 -12
  23. package/dist/authoring/signatureArgs.js.map +1 -1
  24. package/dist/client.cjs +94 -58
  25. package/dist/client.cjs.map +1 -1
  26. package/dist/client.d.cts +61 -2
  27. package/dist/client.d.ts +61 -2
  28. package/dist/client.js +94 -58
  29. package/dist/client.js.map +1 -1
  30. package/dist/discovery.cjs.map +1 -1
  31. package/dist/discovery.d.cts +31 -2
  32. package/dist/discovery.d.ts +31 -2
  33. package/dist/generated/config.generated.cjs.map +1 -1
  34. package/dist/generated/config.generated.d.cts +35 -3
  35. package/dist/generated/config.generated.d.ts +35 -3
  36. package/dist/generated/operations.generated.cjs +9 -0
  37. package/dist/generated/operations.generated.cjs.map +1 -1
  38. package/dist/generated/operations.generated.d.cts +33 -2
  39. package/dist/generated/operations.generated.d.ts +33 -2
  40. package/dist/generated/operations.generated.js +9 -0
  41. package/dist/generated/operations.generated.js.map +1 -1
  42. package/dist/index.cjs +5 -1
  43. package/dist/index.cjs.map +1 -1
  44. package/dist/index.d.cts +26 -7
  45. package/dist/index.d.ts +26 -7
  46. package/dist/index.js +4 -1
  47. package/dist/index.js.map +1 -1
  48. package/dist/{raw-IxCF_bSS.d.ts → raw-BvRghN3r.d.ts} +3 -2
  49. package/dist/{raw-Dj_2rBSQ.d.cts → raw-s1rer8X3.d.cts} +3 -2
  50. package/dist/raw.cjs +2 -0
  51. package/dist/raw.cjs.map +1 -1
  52. package/dist/raw.d.cts +1 -1
  53. package/dist/raw.d.ts +1 -1
  54. package/dist/raw.js +2 -1
  55. package/dist/raw.js.map +1 -1
  56. package/dist/routeAmount-DdbJYJyM.d.cts +55 -0
  57. package/dist/routeAmount-DdbJYJyM.d.ts +55 -0
  58. package/dist/routeAmount.cjs +38 -0
  59. package/dist/routeAmount.cjs.map +1 -0
  60. package/dist/routeAmount.d.cts +2 -0
  61. package/dist/routeAmount.d.ts +2 -0
  62. package/dist/routeAmount.js +13 -0
  63. package/dist/routeAmount.js.map +1 -0
  64. package/dist/run/inputs.cjs +14 -15
  65. package/dist/run/inputs.cjs.map +1 -1
  66. package/dist/run/inputs.d.cts +8 -0
  67. package/dist/run/inputs.d.ts +8 -0
  68. package/dist/run/inputs.js +14 -15
  69. package/dist/run/inputs.js.map +1 -1
  70. package/dist/run/simulate.cjs +5 -0
  71. package/dist/run/simulate.cjs.map +1 -1
  72. package/dist/run/simulate.d.cts +5 -2
  73. package/dist/run/simulate.d.ts +5 -2
  74. package/dist/run/simulate.js +5 -0
  75. package/dist/run/simulate.js.map +1 -1
  76. package/dist/sdk.cjs +3 -0
  77. package/dist/sdk.cjs.map +1 -1
  78. package/dist/sdk.d.cts +42 -2
  79. package/dist/sdk.d.ts +42 -2
  80. package/dist/sdk.js +3 -0
  81. package/dist/sdk.js.map +1 -1
  82. package/dist/types.cjs.map +1 -1
  83. package/dist/types.d.cts +18 -2
  84. package/dist/types.d.ts +18 -2
  85. package/package.json +6 -13
  86. package/src/authoring/FlowBuilderCore.ts +13 -15
  87. package/src/authoring/handles.ts +41 -5
  88. package/src/authoring/raw.ts +39 -4
  89. package/src/authoring/signatureArgs.ts +17 -13
  90. package/src/client.ts +204 -58
  91. package/src/discovery.ts +31 -1
  92. package/src/examples/flySwap.ts +167 -0
  93. package/src/examples/lifiZap.ts +4 -0
  94. package/src/examples/lifiZapAsync.ts +88 -0
  95. package/src/examples/routeTokenPair.ts +58 -0
  96. package/src/examples/run.ts +56 -6
  97. package/src/examples/supportedChains.ts +122 -0
  98. package/src/generated/config.generated.ts +45 -3
  99. package/src/generated/operations.generated.ts +56 -8
  100. package/src/index.ts +33 -1
  101. package/src/raw.ts +1 -1
  102. package/src/routeAmount.ts +61 -0
  103. package/src/run/inputs.ts +30 -11
  104. package/src/run/simulate.ts +14 -2
  105. package/src/sdk.ts +47 -0
  106. package/src/types.ts +20 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/run/simulate.ts"],"sourcesContent":["import type {\n ComposeCompileResult,\n SimulateRequest,\n SlotFinderRequirement,\n TrackedBalance,\n} from '@lifi/compose-spec';\n\n/**\n * Input for {@link buildSimulateRequest}: a compile result plus the fields a\n * simulation needs that a compiled flow does not carry.\n */\nexport interface BuildSimulateRequestInput {\n /**\n * A result from `builder.compile(...)` / `client.compile(...)`. Both\n * `success` and `partial` results carry a `transactionRequest`, so either is\n * valid input — the helper does not discriminate on `status`.\n */\n readonly result: ComposeCompileResult;\n /** EVM chain id. A compile result does not carry the target chain. */\n readonly chainId: number;\n /**\n * The transaction sender (`from`). A compile result does not carry the\n * signer, so it must be supplied here.\n */\n readonly signer: string;\n /**\n * Balances to watch across the simulation. These cannot be inferred from a\n * flow and must be supplied by the caller.\n */\n readonly trackedBalances: readonly TrackedBalance[];\n /** Optional funding instructions applied before simulation. */\n readonly requirements?: readonly SlotFinderRequirement[];\n /** Optional block to pin the simulation to. Omitted ⇒ chain head. */\n readonly block?: number;\n /**\n * Optional native value override. Defaults to the compiled\n * `transactionRequest.value` when omitted.\n */\n readonly value?: bigint | string;\n}\n\n/**\n * Assembles a {@link SimulateRequest} from a compile result and the\n * caller-supplied chain, signer, and tracked balances. Pure: performs no\n * network I/O, does not mutate its input, and returns a fresh object.\n *\n * Bridges the common case — simulate the transaction you just compiled —\n * without coupling raw-transaction simulation to the flow builder. The\n * `value` defaults to the compiled transaction's value unless overridden.\n *\n * @example\n * ```ts\n * const compiled = await builder.compile({ inputs: { ... }, signer: '0x1111...' });\n * const req = buildSimulateRequest({\n * result: compiled,\n * chainId: 1,\n * signer: '0x1111111111111111111111111111111111111111',\n * trackedBalances: [{ token: '0xA0b8...', owner: '0x1111...' }],\n * });\n * const sim = await sdk.client.simulate(req);\n * ```\n */\nexport const buildSimulateRequest = (\n input: BuildSimulateRequestInput,\n): SimulateRequest => {\n const { result, chainId, signer, trackedBalances, requirements, block } =\n input;\n return {\n chainId,\n from: signer,\n to: result.transactionRequest.to,\n data: result.transactionRequest.data,\n value: input.value ?? result.transactionRequest.value,\n block,\n requirements,\n trackedBalances,\n };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA8DO,MAAM,uBAAuB,CAClC,UACoB;AACpB,QAAM,EAAE,QAAQ,SAAS,QAAQ,iBAAiB,cAAc,MAAM,IACpE;AACF,SAAO;AAAA,IACL;AAAA,IACA,MAAM;AAAA,IACN,IAAI,OAAO,mBAAmB;AAAA,IAC9B,MAAM,OAAO,mBAAmB;AAAA,IAChC,OAAO,MAAM,SAAS,OAAO,mBAAmB;AAAA,IAChD;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/run/simulate.ts"],"sourcesContent":["import type {\n ComposeCompileResult,\n SimulateRequest,\n SlotFinderRequirement,\n TrackedBalance,\n} from '@lifi/compose-spec';\n\n/**\n * Input for {@link buildSimulateRequest}: a compile result plus the fields a\n * simulation needs that a compiled flow does not carry.\n */\nexport interface BuildSimulateRequestInput {\n /**\n * A result from `builder.compile(...)` / `client.compile(...)`. Both\n * `success` and `partial` results are valid input — the helper does not\n * discriminate on `status`. A success result for an empty compiled program\n * (a settle-only `funding: 'external'` flow) carries no\n * `transactionRequest`; there is nothing to simulate and this helper\n * throws — submit the result's `actions` entries directly instead.\n */\n readonly result: ComposeCompileResult;\n /** EVM chain id. A compile result does not carry the target chain. */\n readonly chainId: number;\n /**\n * The transaction sender (`from`). A compile result does not carry the\n * signer, so it must be supplied here.\n */\n readonly signer: string;\n /**\n * Balances to watch across the simulation. These cannot be inferred from a\n * flow and must be supplied by the caller.\n */\n readonly trackedBalances: readonly TrackedBalance[];\n /** Optional funding instructions applied before simulation. */\n readonly requirements?: readonly SlotFinderRequirement[];\n /** Optional block to pin the simulation to. Omitted ⇒ chain head. */\n readonly block?: number;\n /**\n * Optional native value override. Defaults to the compiled\n * `transactionRequest.value` when omitted.\n */\n readonly value?: bigint | string;\n}\n\n/**\n * Assembles a {@link SimulateRequest} from a compile result and the\n * caller-supplied chain, signer, and tracked balances. Pure: performs no\n * network I/O, does not mutate its input, and returns a fresh object.\n *\n * Bridges the common case — simulate the transaction you just compiled —\n * without coupling raw-transaction simulation to the flow builder. The\n * `value` defaults to the compiled transaction's value unless overridden.\n *\n * @example\n * ```ts\n * const compiled = await builder.compile({ inputs: { ... }, signer: '0x1111...' });\n * const req = buildSimulateRequest({\n * result: compiled,\n * chainId: 1,\n * signer: '0x1111111111111111111111111111111111111111',\n * trackedBalances: [{ token: '0xA0b8...', owner: '0x1111...' }],\n * });\n * const sim = await sdk.client.simulate(req);\n * ```\n */\nexport const buildSimulateRequest = (\n input: BuildSimulateRequestInput,\n): SimulateRequest => {\n const { result, chainId, signer, trackedBalances, requirements, block } =\n input;\n // A settle-only flow authored with `funding: 'external'` compiles to an\n // empty program: the success response carries no `transactionRequest`, so\n // there is nothing to simulate — the required submissions are the\n // `actions` entries, submitted directly.\n if (result.transactionRequest === undefined) {\n throw new Error(\n 'buildSimulateRequest: the compile result has no transactionRequest (empty compiled program — a settle-only external-funding flow); submit the `actions` entries instead of simulating',\n );\n }\n return {\n chainId,\n from: signer,\n to: result.transactionRequest.to,\n data: result.transactionRequest.data,\n value: input.value ?? result.transactionRequest.value,\n block,\n requirements,\n trackedBalances,\n };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAiEO,MAAM,uBAAuB,CAClC,UACoB;AACpB,QAAM,EAAE,QAAQ,SAAS,QAAQ,iBAAiB,cAAc,MAAM,IACpE;AAKF,MAAI,OAAO,uBAAuB,QAAW;AAC3C,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO;AAAA,IACL;AAAA,IACA,MAAM;AAAA,IACN,IAAI,OAAO,mBAAmB;AAAA,IAC9B,MAAM,OAAO,mBAAmB;AAAA,IAChC,OAAO,MAAM,SAAS,OAAO,mBAAmB;AAAA,IAChD;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":[]}
@@ -7,8 +7,11 @@ import { ComposeCompileResult, TrackedBalance, SlotFinderRequirement, SimulateRe
7
7
  interface BuildSimulateRequestInput {
8
8
  /**
9
9
  * A result from `builder.compile(...)` / `client.compile(...)`. Both
10
- * `success` and `partial` results carry a `transactionRequest`, so either is
11
- * valid input — the helper does not discriminate on `status`.
10
+ * `success` and `partial` results are valid input — the helper does not
11
+ * discriminate on `status`. A success result for an empty compiled program
12
+ * (a settle-only `funding: 'external'` flow) carries no
13
+ * `transactionRequest`; there is nothing to simulate and this helper
14
+ * throws — submit the result's `actions` entries directly instead.
12
15
  */
13
16
  readonly result: ComposeCompileResult;
14
17
  /** EVM chain id. A compile result does not carry the target chain. */
@@ -7,8 +7,11 @@ import { ComposeCompileResult, TrackedBalance, SlotFinderRequirement, SimulateRe
7
7
  interface BuildSimulateRequestInput {
8
8
  /**
9
9
  * A result from `builder.compile(...)` / `client.compile(...)`. Both
10
- * `success` and `partial` results carry a `transactionRequest`, so either is
11
- * valid input — the helper does not discriminate on `status`.
10
+ * `success` and `partial` results are valid input — the helper does not
11
+ * discriminate on `status`. A success result for an empty compiled program
12
+ * (a settle-only `funding: 'external'` flow) carries no
13
+ * `transactionRequest`; there is nothing to simulate and this helper
14
+ * throws — submit the result's `actions` entries directly instead.
12
15
  */
13
16
  readonly result: ComposeCompileResult;
14
17
  /** EVM chain id. A compile result does not carry the target chain. */
@@ -1,5 +1,10 @@
1
1
  const buildSimulateRequest = (input) => {
2
2
  const { result, chainId, signer, trackedBalances, requirements, block } = input;
3
+ if (result.transactionRequest === void 0) {
4
+ throw new Error(
5
+ "buildSimulateRequest: the compile result has no transactionRequest (empty compiled program \u2014 a settle-only external-funding flow); submit the `actions` entries instead of simulating"
6
+ );
7
+ }
3
8
  return {
4
9
  chainId,
5
10
  from: signer,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/run/simulate.ts"],"sourcesContent":["import type {\n ComposeCompileResult,\n SimulateRequest,\n SlotFinderRequirement,\n TrackedBalance,\n} from '@lifi/compose-spec';\n\n/**\n * Input for {@link buildSimulateRequest}: a compile result plus the fields a\n * simulation needs that a compiled flow does not carry.\n */\nexport interface BuildSimulateRequestInput {\n /**\n * A result from `builder.compile(...)` / `client.compile(...)`. Both\n * `success` and `partial` results carry a `transactionRequest`, so either is\n * valid input — the helper does not discriminate on `status`.\n */\n readonly result: ComposeCompileResult;\n /** EVM chain id. A compile result does not carry the target chain. */\n readonly chainId: number;\n /**\n * The transaction sender (`from`). A compile result does not carry the\n * signer, so it must be supplied here.\n */\n readonly signer: string;\n /**\n * Balances to watch across the simulation. These cannot be inferred from a\n * flow and must be supplied by the caller.\n */\n readonly trackedBalances: readonly TrackedBalance[];\n /** Optional funding instructions applied before simulation. */\n readonly requirements?: readonly SlotFinderRequirement[];\n /** Optional block to pin the simulation to. Omitted ⇒ chain head. */\n readonly block?: number;\n /**\n * Optional native value override. Defaults to the compiled\n * `transactionRequest.value` when omitted.\n */\n readonly value?: bigint | string;\n}\n\n/**\n * Assembles a {@link SimulateRequest} from a compile result and the\n * caller-supplied chain, signer, and tracked balances. Pure: performs no\n * network I/O, does not mutate its input, and returns a fresh object.\n *\n * Bridges the common case — simulate the transaction you just compiled —\n * without coupling raw-transaction simulation to the flow builder. The\n * `value` defaults to the compiled transaction's value unless overridden.\n *\n * @example\n * ```ts\n * const compiled = await builder.compile({ inputs: { ... }, signer: '0x1111...' });\n * const req = buildSimulateRequest({\n * result: compiled,\n * chainId: 1,\n * signer: '0x1111111111111111111111111111111111111111',\n * trackedBalances: [{ token: '0xA0b8...', owner: '0x1111...' }],\n * });\n * const sim = await sdk.client.simulate(req);\n * ```\n */\nexport const buildSimulateRequest = (\n input: BuildSimulateRequestInput,\n): SimulateRequest => {\n const { result, chainId, signer, trackedBalances, requirements, block } =\n input;\n return {\n chainId,\n from: signer,\n to: result.transactionRequest.to,\n data: result.transactionRequest.data,\n value: input.value ?? result.transactionRequest.value,\n block,\n requirements,\n trackedBalances,\n };\n};\n"],"mappings":"AA8DO,MAAM,uBAAuB,CAClC,UACoB;AACpB,QAAM,EAAE,QAAQ,SAAS,QAAQ,iBAAiB,cAAc,MAAM,IACpE;AACF,SAAO;AAAA,IACL;AAAA,IACA,MAAM;AAAA,IACN,IAAI,OAAO,mBAAmB;AAAA,IAC9B,MAAM,OAAO,mBAAmB;AAAA,IAChC,OAAO,MAAM,SAAS,OAAO,mBAAmB;AAAA,IAChD;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/run/simulate.ts"],"sourcesContent":["import type {\n ComposeCompileResult,\n SimulateRequest,\n SlotFinderRequirement,\n TrackedBalance,\n} from '@lifi/compose-spec';\n\n/**\n * Input for {@link buildSimulateRequest}: a compile result plus the fields a\n * simulation needs that a compiled flow does not carry.\n */\nexport interface BuildSimulateRequestInput {\n /**\n * A result from `builder.compile(...)` / `client.compile(...)`. Both\n * `success` and `partial` results are valid input — the helper does not\n * discriminate on `status`. A success result for an empty compiled program\n * (a settle-only `funding: 'external'` flow) carries no\n * `transactionRequest`; there is nothing to simulate and this helper\n * throws — submit the result's `actions` entries directly instead.\n */\n readonly result: ComposeCompileResult;\n /** EVM chain id. A compile result does not carry the target chain. */\n readonly chainId: number;\n /**\n * The transaction sender (`from`). A compile result does not carry the\n * signer, so it must be supplied here.\n */\n readonly signer: string;\n /**\n * Balances to watch across the simulation. These cannot be inferred from a\n * flow and must be supplied by the caller.\n */\n readonly trackedBalances: readonly TrackedBalance[];\n /** Optional funding instructions applied before simulation. */\n readonly requirements?: readonly SlotFinderRequirement[];\n /** Optional block to pin the simulation to. Omitted ⇒ chain head. */\n readonly block?: number;\n /**\n * Optional native value override. Defaults to the compiled\n * `transactionRequest.value` when omitted.\n */\n readonly value?: bigint | string;\n}\n\n/**\n * Assembles a {@link SimulateRequest} from a compile result and the\n * caller-supplied chain, signer, and tracked balances. Pure: performs no\n * network I/O, does not mutate its input, and returns a fresh object.\n *\n * Bridges the common case — simulate the transaction you just compiled —\n * without coupling raw-transaction simulation to the flow builder. The\n * `value` defaults to the compiled transaction's value unless overridden.\n *\n * @example\n * ```ts\n * const compiled = await builder.compile({ inputs: { ... }, signer: '0x1111...' });\n * const req = buildSimulateRequest({\n * result: compiled,\n * chainId: 1,\n * signer: '0x1111111111111111111111111111111111111111',\n * trackedBalances: [{ token: '0xA0b8...', owner: '0x1111...' }],\n * });\n * const sim = await sdk.client.simulate(req);\n * ```\n */\nexport const buildSimulateRequest = (\n input: BuildSimulateRequestInput,\n): SimulateRequest => {\n const { result, chainId, signer, trackedBalances, requirements, block } =\n input;\n // A settle-only flow authored with `funding: 'external'` compiles to an\n // empty program: the success response carries no `transactionRequest`, so\n // there is nothing to simulate — the required submissions are the\n // `actions` entries, submitted directly.\n if (result.transactionRequest === undefined) {\n throw new Error(\n 'buildSimulateRequest: the compile result has no transactionRequest (empty compiled program — a settle-only external-funding flow); submit the `actions` entries instead of simulating',\n );\n }\n return {\n chainId,\n from: signer,\n to: result.transactionRequest.to,\n data: result.transactionRequest.data,\n value: input.value ?? result.transactionRequest.value,\n block,\n requirements,\n trackedBalances,\n };\n};\n"],"mappings":"AAiEO,MAAM,uBAAuB,CAClC,UACoB;AACpB,QAAM,EAAE,QAAQ,SAAS,QAAQ,iBAAiB,cAAc,MAAM,IACpE;AAKF,MAAI,OAAO,uBAAuB,QAAW;AAC3C,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO;AAAA,IACL;AAAA,IACA,MAAM;AAAA,IACN,IAAI,OAAO,mBAAmB;AAAA,IAC9B,MAAM,OAAO,mBAAmB;AAAA,IAChC,OAAO,MAAM,SAAS,OAAO,mBAAmB;AAAA,IAChD;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":[]}
package/dist/sdk.cjs CHANGED
@@ -39,6 +39,7 @@ const createComposeSdk = (options) => {
39
39
  maxPriceImpactBps: run.maxPriceImpactBps,
40
40
  sweepTo: run.sweepTo,
41
41
  simulationPolicy: run.simulationPolicy,
42
+ simulateUserProgram: run.simulateUserProgram,
42
43
  checkOnChainAllowances: run.checkOnChainAllowances
43
44
  })
44
45
  });
@@ -55,7 +56,9 @@ const createComposeSdk = (options) => {
55
56
  return {
56
57
  client: composeClient,
57
58
  flow,
59
+ getSupportedChains: composeClient.getChains,
58
60
  request,
61
+ route: composeClient.route,
59
62
  simulate: composeClient.simulate
60
63
  };
61
64
  };
package/dist/sdk.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/sdk.ts"],"sourcesContent":["import type {\n ComposeCompileRequest,\n ComposeCompileResult,\n InputSpec,\n SimulateRequest,\n SimulateResult,\n} from '@lifi/compose-spec';\n\nimport {\n createFlowBuilderCore,\n type FlowBuilderCore,\n type FlowOptions,\n type TypedFlow,\n} from './authoring/FlowBuilderCore.js';\nimport { type ComposeClient, createComposeClient } from './client.js';\nimport {\n bindGeneratedOps,\n type GeneratedOps,\n} from './generated/operations.generated.js';\nimport { buildRun, type ComposeRunInput } from './run/inputs.js';\nimport type { InputSchema } from './types.js';\n\nexport type { ComposeRunInput };\n\n/**\n * A flow builder augmented with generated operation methods and a `compile` method\n * that submits the flow to the Compose backend for compilation.\n *\n * Created via {@link ComposeSdk.flow}.\n *\n * @typeParam T - The input schema describing the flow's required inputs.\n */\nexport type FlowBuilder<T extends InputSchema = InputSchema> =\n FlowBuilderCore<T> &\n GeneratedOps & {\n /**\n * Builds the flow document from the current builder state and submits it\n * to the Compose API for compilation.\n *\n * @param run - Runtime inputs, preconditions, and signer address.\n * @returns The compiled transaction calldata and metadata.\n * @throws {@link ComposeError} on network, validation, or server errors.\n *\n * @example\n * ```ts\n * const result = await builder.compile({\n * inputs: { token: materialisers.balanceOf({}) },\n * signer: '0xYourAddress...',\n * });\n * console.log(result.calldata);\n * ```\n */\n readonly compile: (\n run: ComposeRunInput<T>,\n ) => Promise<ComposeCompileResult>;\n };\n\n/**\n * Configuration for creating a Compose SDK instance.\n */\nexport interface ComposeSdkOptions {\n /** Base URL of the Compose API (e.g. `\"https://li.quest\"`). */\n readonly baseUrl: string;\n /** Optional custom `fetch` implementation. Defaults to `globalThis.fetch`. */\n readonly fetch?: typeof globalThis.fetch;\n /** LI.FI API key, sent as the `x-lifi-api-key` header on every request. Required — the Compose API rejects unauthenticated requests. */\n readonly apiKey: string;\n}\n\n/**\n * The top-level Compose SDK interface.\n *\n * Provides methods to build flows, compile them into executable calldata, and\n * interact with the Compose API directly.\n *\n * @example\n * ```ts\n * import { createComposeSdk, resources, materialisers } from '@lifi/composer-sdk';\n *\n * const sdk = createComposeSdk({ baseUrl: 'https://li.quest', apiKey: 'YOUR_API_KEY' });\n *\n * const builder = sdk.flow(1, {\n * inputs: { usdc: resources.erc20('0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', 1) },\n * });\n *\n * builder.lifi.swap('swap1', {\n * bind: { amountIn: builder.inputs.usdc },\n * config: { resourceOut: resources.native(1) },\n * });\n *\n * const result = await builder.compile({\n * inputs: { usdc: materialisers.balanceOf({}) },\n * signer: '0xYourAddress...',\n * });\n * ```\n */\nexport interface ComposeSdk {\n /** Low-level HTTP client for the Compose API. */\n readonly client: ComposeClient;\n /**\n * Creates a new flow builder targeting the given chain.\n * @param chainId - The EVM chain ID (e.g. `1` for Ethereum mainnet).\n * @param options - Flow configuration including input declarations.\n * @returns A {@link FlowBuilder} with generated operation methods and a `compile` method.\n * @throws Error if any resource input's `chainId` doesn't match the flow's `chainId`.\n */\n readonly flow: <T extends InputSchema>(\n chainId: number,\n options: FlowOptions<T>,\n ) => FlowBuilder<T>;\n /**\n * Builds a raw compile request without sending it. Useful for inspecting the\n * request payload or submitting it through a custom transport.\n * @param flow - A built flow document (from `builder.build()`).\n * @param run - Runtime inputs, preconditions, and signer address.\n * @returns A {@link ComposeCompileRequest} ready to send to the Compose API.\n */\n readonly request: <T extends InputSchema>(\n flow: TypedFlow<T>,\n run: ComposeRunInput<T>,\n ) => ComposeCompileRequest;\n /**\n * Simulates a raw, pre-encoded transaction. Thin pass-through to\n * {@link ComposeClient.simulate}; see it for the `ok` / `revert` / `error`\n * result discrimination and error behaviour. Pair with `buildSimulateRequest`\n * to assemble the request from a compile result.\n *\n * @param request - The raw transaction plus funding `requirements` and\n * `trackedBalances`.\n * @returns A {@link SimulateResult} (`ok` / `revert` / `error`).\n * @throws {@link ComposeError} on network, validation, or server errors.\n */\n readonly simulate: (request: SimulateRequest) => Promise<SimulateResult>;\n}\n\n/**\n * Creates a new Compose SDK instance.\n *\n * @param options - SDK configuration including the API base URL, required API key, and optional fetch implementation.\n * @returns A {@link ComposeSdk} instance.\n *\n * @example\n * ```ts\n * const sdk = createComposeSdk({ baseUrl: 'https://li.quest', apiKey: 'YOUR_API_KEY' });\n * ```\n */\nexport const createComposeSdk = (options: ComposeSdkOptions): ComposeSdk => {\n const composeClient = createComposeClient(options);\n\n const request = <T extends InputSchema>(\n flowDoc: TypedFlow<T>,\n run: ComposeRunInput<T>,\n ): ComposeCompileRequest => ({\n flow: flowDoc,\n run: buildRun({\n inputs: run.inputs as Record<string, InputSpec>,\n preconditions: run.preconditions,\n signer: run.signer,\n assumptions: run.assumptions as Record<string, bigint> | undefined,\n referrer: run.referrer,\n integratorFeeBps: run.integratorFeeBps,\n maxPriceImpactBps: run.maxPriceImpactBps,\n sweepTo: run.sweepTo,\n simulationPolicy: run.simulationPolicy,\n checkOnChainAllowances: run.checkOnChainAllowances,\n }),\n });\n\n const flow = <T extends InputSchema>(\n chainId: number,\n opts: FlowOptions<T>,\n ): FlowBuilder<T> => {\n const core = createFlowBuilderCore(chainId, opts);\n const builder = Object.assign(core, bindGeneratedOps(core));\n\n const compile = async (\n run: ComposeRunInput<T>,\n ): Promise<ComposeCompileResult> => {\n const flowDoc = builder.build();\n const req = request(flowDoc, run);\n return composeClient.compile(req);\n };\n\n return Object.assign(builder, { compile });\n };\n\n return {\n client: composeClient,\n flow,\n request,\n simulate: composeClient.simulate,\n };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA,6BAKO;AACP,oBAAwD;AACxD,kCAGO;AACP,oBAA+C;AA+HxC,MAAM,mBAAmB,CAAC,YAA2C;AAC1E,QAAM,oBAAgB,mCAAoB,OAAO;AAEjD,QAAM,UAAU,CACd,SACA,SAC2B;AAAA,IAC3B,MAAM;AAAA,IACN,SAAK,wBAAS;AAAA,MACZ,QAAQ,IAAI;AAAA,MACZ,eAAe,IAAI;AAAA,MACnB,QAAQ,IAAI;AAAA,MACZ,aAAa,IAAI;AAAA,MACjB,UAAU,IAAI;AAAA,MACd,kBAAkB,IAAI;AAAA,MACtB,mBAAmB,IAAI;AAAA,MACvB,SAAS,IAAI;AAAA,MACb,kBAAkB,IAAI;AAAA,MACtB,wBAAwB,IAAI;AAAA,IAC9B,CAAC;AAAA,EACH;AAEA,QAAM,OAAO,CACX,SACA,SACmB;AACnB,UAAM,WAAO,8CAAsB,SAAS,IAAI;AAChD,UAAM,UAAU,OAAO,OAAO,UAAM,8CAAiB,IAAI,CAAC;AAE1D,UAAM,UAAU,OACd,QACkC;AAClC,YAAM,UAAU,QAAQ,MAAM;AAC9B,YAAM,MAAM,QAAQ,SAAS,GAAG;AAChC,aAAO,cAAc,QAAQ,GAAG;AAAA,IAClC;AAEA,WAAO,OAAO,OAAO,SAAS,EAAE,QAAQ,CAAC;AAAA,EAC3C;AAEA,SAAO;AAAA,IACL,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA,UAAU,cAAc;AAAA,EAC1B;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/sdk.ts"],"sourcesContent":["import type {\n ComposeCompileRequest,\n ComposeCompileResult,\n ComposeRouteRequest,\n InputSpec,\n SimulateRequest,\n SimulateResult,\n} from '@lifi/compose-spec';\n\nimport {\n createFlowBuilderCore,\n type FlowBuilderCore,\n type FlowOptions,\n type TypedFlow,\n} from './authoring/FlowBuilderCore.js';\nimport { type ComposeClient, createComposeClient } from './client.js';\nimport type { ChainSummary } from './discovery.js';\nimport {\n bindGeneratedOps,\n type GeneratedOps,\n} from './generated/operations.generated.js';\nimport { buildRun, type ComposeRunInput } from './run/inputs.js';\nimport type { InputSchema } from './types.js';\n\nexport type { ComposeRunInput };\n\n/**\n * A flow builder augmented with generated operation methods and a `compile` method\n * that submits the flow to the Compose backend for compilation.\n *\n * Created via {@link ComposeSdk.flow}.\n *\n * @typeParam T - The input schema describing the flow's required inputs.\n */\nexport type FlowBuilder<T extends InputSchema = InputSchema> =\n FlowBuilderCore<T> &\n GeneratedOps & {\n /**\n * Builds the flow document from the current builder state and submits it\n * to the Compose API for compilation.\n *\n * @param run - Runtime inputs, preconditions, and signer address.\n * @returns The compiled transaction calldata and metadata.\n * @throws {@link ComposeError} on network, validation, or server errors.\n *\n * @example\n * ```ts\n * const result = await builder.compile({\n * inputs: { token: materialisers.balanceOf({}) },\n * signer: '0xYourAddress...',\n * });\n * console.log(result.calldata);\n * ```\n */\n readonly compile: (\n run: ComposeRunInput<T>,\n ) => Promise<ComposeCompileResult>;\n };\n\n/**\n * Configuration for creating a Compose SDK instance.\n */\nexport interface ComposeSdkOptions {\n /** Base URL of the Compose API (e.g. `\"https://li.quest\"`). */\n readonly baseUrl: string;\n /** Optional custom `fetch` implementation. Defaults to `globalThis.fetch`. */\n readonly fetch?: typeof globalThis.fetch;\n /** LI.FI API key, sent as the `x-lifi-api-key` header on every request. Required — the Compose API rejects unauthenticated requests. */\n readonly apiKey: string;\n}\n\n/**\n * The top-level Compose SDK interface.\n *\n * Provides methods to build flows, compile them into executable calldata, and\n * interact with the Compose API directly.\n *\n * @example\n * ```ts\n * import { createComposeSdk, resources, materialisers } from '@lifi/composer-sdk';\n *\n * const sdk = createComposeSdk({ baseUrl: 'https://li.quest', apiKey: 'YOUR_API_KEY' });\n *\n * const builder = sdk.flow(1, {\n * inputs: { usdc: resources.erc20('0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', 1) },\n * });\n *\n * builder.lifi.swap('swap1', {\n * bind: { amountIn: builder.inputs.usdc },\n * config: { resourceOut: resources.native(1) },\n * });\n *\n * const result = await builder.compile({\n * inputs: { usdc: materialisers.balanceOf({}) },\n * signer: '0xYourAddress...',\n * });\n * ```\n */\nexport interface ComposeSdk {\n /** Low-level HTTP client for the Compose API. */\n readonly client: ComposeClient;\n /**\n * Creates a new flow builder targeting the given chain.\n * @param chainId - The EVM chain ID (e.g. `1` for Ethereum mainnet).\n * @param options - Flow configuration including input declarations.\n * @returns A {@link FlowBuilder} with generated operation methods and a `compile` method.\n * @throws Error if any resource input's `chainId` doesn't match the flow's `chainId`.\n */\n readonly flow: <T extends InputSchema>(\n chainId: number,\n options: FlowOptions<T>,\n ) => FlowBuilder<T>;\n /**\n * Fetches the chains this Compose deployment supports, ascending by\n * `chainId`. Thin pass-through to {@link ComposeClient.getChains}; see it\n * for what \"supported\" means and for the caching caveat.\n *\n * Each entry pairs the `chainId` with a display `name`, so one call both\n * gates a chain selector and labels it. Key on `chainId`; `name` is a\n * deployment-maintained label that can change.\n *\n * Use it to fail fast before building a flow for a chain the server would\n * reject.\n *\n * @returns The supported chains, ascending by `chainId`.\n * @throws {@link ComposeError} on network or server errors.\n *\n * @example\n * ```ts\n * const chains = await sdk.getSupportedChains();\n * if (!chains.some((c) => c.chainId === 8453)) {\n * throw new Error('Base is not supported');\n * }\n * for (const { chainId, name } of chains) {\n * console.log(`${name} (${chainId})`);\n * }\n * ```\n */\n readonly getSupportedChains: () => Promise<readonly ChainSummary[]>;\n /**\n * Builds a raw compile request without sending it. Useful for inspecting the\n * request payload or submitting it through a custom transport.\n * @param flow - A built flow document (from `builder.build()`).\n * @param run - Runtime inputs, preconditions, and signer address.\n * @returns A {@link ComposeCompileRequest} ready to send to the Compose API.\n */\n readonly request: <T extends InputSchema>(\n flow: TypedFlow<T>,\n run: ComposeRunInput<T>,\n ) => ComposeCompileRequest;\n /**\n * Compiles a token pair on one chain — as of today a single zap step over\n * one routing-catalog edge. Thin pass-through to\n * {@link ComposeClient.route}; see it for the current single-step limit,\n * when to prefer `flow(...).compile(...)`, the `success` / `partial`\n * discrimination, and error behaviour. Build the `amount` with\n * `routeAmount.exact(...)` / `routeAmount.all(...)`.\n *\n * @param request - The from/to token pair, amount, signer, and route options.\n * @returns A discriminated result: `status: 'success'` or `status: 'partial'`.\n * @throws {@link ComposeError} on network, validation, or server errors.\n */\n readonly route: (\n request: ComposeRouteRequest,\n ) => Promise<ComposeCompileResult>;\n /**\n * Simulates a raw, pre-encoded transaction. Thin pass-through to\n * {@link ComposeClient.simulate}; see it for the `ok` / `revert` / `error`\n * result discrimination and error behaviour. Pair with `buildSimulateRequest`\n * to assemble the request from a compile result.\n *\n * @param request - The raw transaction plus funding `requirements` and\n * `trackedBalances`.\n * @returns A {@link SimulateResult} (`ok` / `revert` / `error`).\n * @throws {@link ComposeError} on network, validation, or server errors.\n */\n readonly simulate: (request: SimulateRequest) => Promise<SimulateResult>;\n}\n\n/**\n * Creates a new Compose SDK instance.\n *\n * @param options - SDK configuration including the API base URL, required API key, and optional fetch implementation.\n * @returns A {@link ComposeSdk} instance.\n *\n * @example\n * ```ts\n * const sdk = createComposeSdk({ baseUrl: 'https://li.quest', apiKey: 'YOUR_API_KEY' });\n * ```\n */\nexport const createComposeSdk = (options: ComposeSdkOptions): ComposeSdk => {\n const composeClient = createComposeClient(options);\n\n const request = <T extends InputSchema>(\n flowDoc: TypedFlow<T>,\n run: ComposeRunInput<T>,\n ): ComposeCompileRequest => ({\n flow: flowDoc,\n run: buildRun({\n inputs: run.inputs as Record<string, InputSpec>,\n preconditions: run.preconditions,\n signer: run.signer,\n assumptions: run.assumptions as Record<string, bigint> | undefined,\n referrer: run.referrer,\n integratorFeeBps: run.integratorFeeBps,\n maxPriceImpactBps: run.maxPriceImpactBps,\n sweepTo: run.sweepTo,\n simulationPolicy: run.simulationPolicy,\n simulateUserProgram: run.simulateUserProgram,\n checkOnChainAllowances: run.checkOnChainAllowances,\n }),\n });\n\n const flow = <T extends InputSchema>(\n chainId: number,\n opts: FlowOptions<T>,\n ): FlowBuilder<T> => {\n const core = createFlowBuilderCore(chainId, opts);\n const builder = Object.assign(core, bindGeneratedOps(core));\n\n const compile = async (\n run: ComposeRunInput<T>,\n ): Promise<ComposeCompileResult> => {\n const flowDoc = builder.build();\n const req = request(flowDoc, run);\n return composeClient.compile(req);\n };\n\n return Object.assign(builder, { compile });\n };\n\n return {\n client: composeClient,\n flow,\n getSupportedChains: composeClient.getChains,\n request,\n route: composeClient.route,\n simulate: composeClient.simulate,\n };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AASA,6BAKO;AACP,oBAAwD;AAExD,kCAGO;AACP,oBAA+C;AAyKxC,MAAM,mBAAmB,CAAC,YAA2C;AAC1E,QAAM,oBAAgB,mCAAoB,OAAO;AAEjD,QAAM,UAAU,CACd,SACA,SAC2B;AAAA,IAC3B,MAAM;AAAA,IACN,SAAK,wBAAS;AAAA,MACZ,QAAQ,IAAI;AAAA,MACZ,eAAe,IAAI;AAAA,MACnB,QAAQ,IAAI;AAAA,MACZ,aAAa,IAAI;AAAA,MACjB,UAAU,IAAI;AAAA,MACd,kBAAkB,IAAI;AAAA,MACtB,mBAAmB,IAAI;AAAA,MACvB,SAAS,IAAI;AAAA,MACb,kBAAkB,IAAI;AAAA,MACtB,qBAAqB,IAAI;AAAA,MACzB,wBAAwB,IAAI;AAAA,IAC9B,CAAC;AAAA,EACH;AAEA,QAAM,OAAO,CACX,SACA,SACmB;AACnB,UAAM,WAAO,8CAAsB,SAAS,IAAI;AAChD,UAAM,UAAU,OAAO,OAAO,UAAM,8CAAiB,IAAI,CAAC;AAE1D,UAAM,UAAU,OACd,QACkC;AAClC,YAAM,UAAU,QAAQ,MAAM;AAC9B,YAAM,MAAM,QAAQ,SAAS,GAAG;AAChC,aAAO,cAAc,QAAQ,GAAG;AAAA,IAClC;AAEA,WAAO,OAAO,OAAO,SAAS,EAAE,QAAQ,CAAC;AAAA,EAC3C;AAEA,SAAO;AAAA,IACL,QAAQ;AAAA,IACR;AAAA,IACA,oBAAoB,cAAc;AAAA,IAClC;AAAA,IACA,OAAO,cAAc;AAAA,IACrB,UAAU,cAAc;AAAA,EAC1B;AACF;","names":[]}
package/dist/sdk.d.cts CHANGED
@@ -1,11 +1,11 @@
1
- import { ComposeCompileResult, ComposeCompileRequest, SimulateRequest, SimulateResult } from '@lifi/compose-spec';
1
+ import { ComposeCompileResult, ComposeCompileRequest, ComposeRouteRequest, SimulateRequest, SimulateResult } from '@lifi/compose-spec';
2
2
  import { FlowOptions, FlowBuilderCore, TypedFlow } from './authoring/FlowBuilderCore.cjs';
3
3
  import { ComposeClient } from './client.cjs';
4
+ import { ChainSummary } from './discovery.cjs';
4
5
  import { GeneratedOps } from './generated/operations.generated.cjs';
5
6
  import { ComposeRunInput } from './run/inputs.cjs';
6
7
  import { InputSchema } from './types.cjs';
7
8
  import './authoring/handles.cjs';
8
- import './discovery.cjs';
9
9
  import './authoring/signatureArgs.cjs';
10
10
  import 'abitype';
11
11
  import './generated/config.generated.cjs';
@@ -87,6 +87,33 @@ interface ComposeSdk {
87
87
  * @throws Error if any resource input's `chainId` doesn't match the flow's `chainId`.
88
88
  */
89
89
  readonly flow: <T extends InputSchema>(chainId: number, options: FlowOptions<T>) => FlowBuilder<T>;
90
+ /**
91
+ * Fetches the chains this Compose deployment supports, ascending by
92
+ * `chainId`. Thin pass-through to {@link ComposeClient.getChains}; see it
93
+ * for what "supported" means and for the caching caveat.
94
+ *
95
+ * Each entry pairs the `chainId` with a display `name`, so one call both
96
+ * gates a chain selector and labels it. Key on `chainId`; `name` is a
97
+ * deployment-maintained label that can change.
98
+ *
99
+ * Use it to fail fast before building a flow for a chain the server would
100
+ * reject.
101
+ *
102
+ * @returns The supported chains, ascending by `chainId`.
103
+ * @throws {@link ComposeError} on network or server errors.
104
+ *
105
+ * @example
106
+ * ```ts
107
+ * const chains = await sdk.getSupportedChains();
108
+ * if (!chains.some((c) => c.chainId === 8453)) {
109
+ * throw new Error('Base is not supported');
110
+ * }
111
+ * for (const { chainId, name } of chains) {
112
+ * console.log(`${name} (${chainId})`);
113
+ * }
114
+ * ```
115
+ */
116
+ readonly getSupportedChains: () => Promise<readonly ChainSummary[]>;
90
117
  /**
91
118
  * Builds a raw compile request without sending it. Useful for inspecting the
92
119
  * request payload or submitting it through a custom transport.
@@ -95,6 +122,19 @@ interface ComposeSdk {
95
122
  * @returns A {@link ComposeCompileRequest} ready to send to the Compose API.
96
123
  */
97
124
  readonly request: <T extends InputSchema>(flow: TypedFlow<T>, run: ComposeRunInput<T>) => ComposeCompileRequest;
125
+ /**
126
+ * Compiles a token pair on one chain — as of today a single zap step over
127
+ * one routing-catalog edge. Thin pass-through to
128
+ * {@link ComposeClient.route}; see it for the current single-step limit,
129
+ * when to prefer `flow(...).compile(...)`, the `success` / `partial`
130
+ * discrimination, and error behaviour. Build the `amount` with
131
+ * `routeAmount.exact(...)` / `routeAmount.all(...)`.
132
+ *
133
+ * @param request - The from/to token pair, amount, signer, and route options.
134
+ * @returns A discriminated result: `status: 'success'` or `status: 'partial'`.
135
+ * @throws {@link ComposeError} on network, validation, or server errors.
136
+ */
137
+ readonly route: (request: ComposeRouteRequest) => Promise<ComposeCompileResult>;
98
138
  /**
99
139
  * Simulates a raw, pre-encoded transaction. Thin pass-through to
100
140
  * {@link ComposeClient.simulate}; see it for the `ok` / `revert` / `error`
package/dist/sdk.d.ts CHANGED
@@ -1,11 +1,11 @@
1
- import { ComposeCompileResult, ComposeCompileRequest, SimulateRequest, SimulateResult } from '@lifi/compose-spec';
1
+ import { ComposeCompileResult, ComposeCompileRequest, ComposeRouteRequest, SimulateRequest, SimulateResult } from '@lifi/compose-spec';
2
2
  import { FlowOptions, FlowBuilderCore, TypedFlow } from './authoring/FlowBuilderCore.js';
3
3
  import { ComposeClient } from './client.js';
4
+ import { ChainSummary } from './discovery.js';
4
5
  import { GeneratedOps } from './generated/operations.generated.js';
5
6
  import { ComposeRunInput } from './run/inputs.js';
6
7
  import { InputSchema } from './types.js';
7
8
  import './authoring/handles.js';
8
- import './discovery.js';
9
9
  import './authoring/signatureArgs.js';
10
10
  import 'abitype';
11
11
  import './generated/config.generated.js';
@@ -87,6 +87,33 @@ interface ComposeSdk {
87
87
  * @throws Error if any resource input's `chainId` doesn't match the flow's `chainId`.
88
88
  */
89
89
  readonly flow: <T extends InputSchema>(chainId: number, options: FlowOptions<T>) => FlowBuilder<T>;
90
+ /**
91
+ * Fetches the chains this Compose deployment supports, ascending by
92
+ * `chainId`. Thin pass-through to {@link ComposeClient.getChains}; see it
93
+ * for what "supported" means and for the caching caveat.
94
+ *
95
+ * Each entry pairs the `chainId` with a display `name`, so one call both
96
+ * gates a chain selector and labels it. Key on `chainId`; `name` is a
97
+ * deployment-maintained label that can change.
98
+ *
99
+ * Use it to fail fast before building a flow for a chain the server would
100
+ * reject.
101
+ *
102
+ * @returns The supported chains, ascending by `chainId`.
103
+ * @throws {@link ComposeError} on network or server errors.
104
+ *
105
+ * @example
106
+ * ```ts
107
+ * const chains = await sdk.getSupportedChains();
108
+ * if (!chains.some((c) => c.chainId === 8453)) {
109
+ * throw new Error('Base is not supported');
110
+ * }
111
+ * for (const { chainId, name } of chains) {
112
+ * console.log(`${name} (${chainId})`);
113
+ * }
114
+ * ```
115
+ */
116
+ readonly getSupportedChains: () => Promise<readonly ChainSummary[]>;
90
117
  /**
91
118
  * Builds a raw compile request without sending it. Useful for inspecting the
92
119
  * request payload or submitting it through a custom transport.
@@ -95,6 +122,19 @@ interface ComposeSdk {
95
122
  * @returns A {@link ComposeCompileRequest} ready to send to the Compose API.
96
123
  */
97
124
  readonly request: <T extends InputSchema>(flow: TypedFlow<T>, run: ComposeRunInput<T>) => ComposeCompileRequest;
125
+ /**
126
+ * Compiles a token pair on one chain — as of today a single zap step over
127
+ * one routing-catalog edge. Thin pass-through to
128
+ * {@link ComposeClient.route}; see it for the current single-step limit,
129
+ * when to prefer `flow(...).compile(...)`, the `success` / `partial`
130
+ * discrimination, and error behaviour. Build the `amount` with
131
+ * `routeAmount.exact(...)` / `routeAmount.all(...)`.
132
+ *
133
+ * @param request - The from/to token pair, amount, signer, and route options.
134
+ * @returns A discriminated result: `status: 'success'` or `status: 'partial'`.
135
+ * @throws {@link ComposeError} on network, validation, or server errors.
136
+ */
137
+ readonly route: (request: ComposeRouteRequest) => Promise<ComposeCompileResult>;
98
138
  /**
99
139
  * Simulates a raw, pre-encoded transaction. Thin pass-through to
100
140
  * {@link ComposeClient.simulate}; see it for the `ok` / `revert` / `error`
package/dist/sdk.js CHANGED
@@ -20,6 +20,7 @@ const createComposeSdk = (options) => {
20
20
  maxPriceImpactBps: run.maxPriceImpactBps,
21
21
  sweepTo: run.sweepTo,
22
22
  simulationPolicy: run.simulationPolicy,
23
+ simulateUserProgram: run.simulateUserProgram,
23
24
  checkOnChainAllowances: run.checkOnChainAllowances
24
25
  })
25
26
  });
@@ -36,7 +37,9 @@ const createComposeSdk = (options) => {
36
37
  return {
37
38
  client: composeClient,
38
39
  flow,
40
+ getSupportedChains: composeClient.getChains,
39
41
  request,
42
+ route: composeClient.route,
40
43
  simulate: composeClient.simulate
41
44
  };
42
45
  };
package/dist/sdk.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/sdk.ts"],"sourcesContent":["import type {\n ComposeCompileRequest,\n ComposeCompileResult,\n InputSpec,\n SimulateRequest,\n SimulateResult,\n} from '@lifi/compose-spec';\n\nimport {\n createFlowBuilderCore,\n type FlowBuilderCore,\n type FlowOptions,\n type TypedFlow,\n} from './authoring/FlowBuilderCore.js';\nimport { type ComposeClient, createComposeClient } from './client.js';\nimport {\n bindGeneratedOps,\n type GeneratedOps,\n} from './generated/operations.generated.js';\nimport { buildRun, type ComposeRunInput } from './run/inputs.js';\nimport type { InputSchema } from './types.js';\n\nexport type { ComposeRunInput };\n\n/**\n * A flow builder augmented with generated operation methods and a `compile` method\n * that submits the flow to the Compose backend for compilation.\n *\n * Created via {@link ComposeSdk.flow}.\n *\n * @typeParam T - The input schema describing the flow's required inputs.\n */\nexport type FlowBuilder<T extends InputSchema = InputSchema> =\n FlowBuilderCore<T> &\n GeneratedOps & {\n /**\n * Builds the flow document from the current builder state and submits it\n * to the Compose API for compilation.\n *\n * @param run - Runtime inputs, preconditions, and signer address.\n * @returns The compiled transaction calldata and metadata.\n * @throws {@link ComposeError} on network, validation, or server errors.\n *\n * @example\n * ```ts\n * const result = await builder.compile({\n * inputs: { token: materialisers.balanceOf({}) },\n * signer: '0xYourAddress...',\n * });\n * console.log(result.calldata);\n * ```\n */\n readonly compile: (\n run: ComposeRunInput<T>,\n ) => Promise<ComposeCompileResult>;\n };\n\n/**\n * Configuration for creating a Compose SDK instance.\n */\nexport interface ComposeSdkOptions {\n /** Base URL of the Compose API (e.g. `\"https://li.quest\"`). */\n readonly baseUrl: string;\n /** Optional custom `fetch` implementation. Defaults to `globalThis.fetch`. */\n readonly fetch?: typeof globalThis.fetch;\n /** LI.FI API key, sent as the `x-lifi-api-key` header on every request. Required — the Compose API rejects unauthenticated requests. */\n readonly apiKey: string;\n}\n\n/**\n * The top-level Compose SDK interface.\n *\n * Provides methods to build flows, compile them into executable calldata, and\n * interact with the Compose API directly.\n *\n * @example\n * ```ts\n * import { createComposeSdk, resources, materialisers } from '@lifi/composer-sdk';\n *\n * const sdk = createComposeSdk({ baseUrl: 'https://li.quest', apiKey: 'YOUR_API_KEY' });\n *\n * const builder = sdk.flow(1, {\n * inputs: { usdc: resources.erc20('0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', 1) },\n * });\n *\n * builder.lifi.swap('swap1', {\n * bind: { amountIn: builder.inputs.usdc },\n * config: { resourceOut: resources.native(1) },\n * });\n *\n * const result = await builder.compile({\n * inputs: { usdc: materialisers.balanceOf({}) },\n * signer: '0xYourAddress...',\n * });\n * ```\n */\nexport interface ComposeSdk {\n /** Low-level HTTP client for the Compose API. */\n readonly client: ComposeClient;\n /**\n * Creates a new flow builder targeting the given chain.\n * @param chainId - The EVM chain ID (e.g. `1` for Ethereum mainnet).\n * @param options - Flow configuration including input declarations.\n * @returns A {@link FlowBuilder} with generated operation methods and a `compile` method.\n * @throws Error if any resource input's `chainId` doesn't match the flow's `chainId`.\n */\n readonly flow: <T extends InputSchema>(\n chainId: number,\n options: FlowOptions<T>,\n ) => FlowBuilder<T>;\n /**\n * Builds a raw compile request without sending it. Useful for inspecting the\n * request payload or submitting it through a custom transport.\n * @param flow - A built flow document (from `builder.build()`).\n * @param run - Runtime inputs, preconditions, and signer address.\n * @returns A {@link ComposeCompileRequest} ready to send to the Compose API.\n */\n readonly request: <T extends InputSchema>(\n flow: TypedFlow<T>,\n run: ComposeRunInput<T>,\n ) => ComposeCompileRequest;\n /**\n * Simulates a raw, pre-encoded transaction. Thin pass-through to\n * {@link ComposeClient.simulate}; see it for the `ok` / `revert` / `error`\n * result discrimination and error behaviour. Pair with `buildSimulateRequest`\n * to assemble the request from a compile result.\n *\n * @param request - The raw transaction plus funding `requirements` and\n * `trackedBalances`.\n * @returns A {@link SimulateResult} (`ok` / `revert` / `error`).\n * @throws {@link ComposeError} on network, validation, or server errors.\n */\n readonly simulate: (request: SimulateRequest) => Promise<SimulateResult>;\n}\n\n/**\n * Creates a new Compose SDK instance.\n *\n * @param options - SDK configuration including the API base URL, required API key, and optional fetch implementation.\n * @returns A {@link ComposeSdk} instance.\n *\n * @example\n * ```ts\n * const sdk = createComposeSdk({ baseUrl: 'https://li.quest', apiKey: 'YOUR_API_KEY' });\n * ```\n */\nexport const createComposeSdk = (options: ComposeSdkOptions): ComposeSdk => {\n const composeClient = createComposeClient(options);\n\n const request = <T extends InputSchema>(\n flowDoc: TypedFlow<T>,\n run: ComposeRunInput<T>,\n ): ComposeCompileRequest => ({\n flow: flowDoc,\n run: buildRun({\n inputs: run.inputs as Record<string, InputSpec>,\n preconditions: run.preconditions,\n signer: run.signer,\n assumptions: run.assumptions as Record<string, bigint> | undefined,\n referrer: run.referrer,\n integratorFeeBps: run.integratorFeeBps,\n maxPriceImpactBps: run.maxPriceImpactBps,\n sweepTo: run.sweepTo,\n simulationPolicy: run.simulationPolicy,\n checkOnChainAllowances: run.checkOnChainAllowances,\n }),\n });\n\n const flow = <T extends InputSchema>(\n chainId: number,\n opts: FlowOptions<T>,\n ): FlowBuilder<T> => {\n const core = createFlowBuilderCore(chainId, opts);\n const builder = Object.assign(core, bindGeneratedOps(core));\n\n const compile = async (\n run: ComposeRunInput<T>,\n ): Promise<ComposeCompileResult> => {\n const flowDoc = builder.build();\n const req = request(flowDoc, run);\n return composeClient.compile(req);\n };\n\n return Object.assign(builder, { compile });\n };\n\n return {\n client: composeClient,\n flow,\n request,\n simulate: composeClient.simulate,\n };\n};\n"],"mappings":"AAQA;AAAA,EACE;AAAA,OAIK;AACP,SAA6B,2BAA2B;AACxD;AAAA,EACE;AAAA,OAEK;AACP,SAAS,gBAAsC;AA+HxC,MAAM,mBAAmB,CAAC,YAA2C;AAC1E,QAAM,gBAAgB,oBAAoB,OAAO;AAEjD,QAAM,UAAU,CACd,SACA,SAC2B;AAAA,IAC3B,MAAM;AAAA,IACN,KAAK,SAAS;AAAA,MACZ,QAAQ,IAAI;AAAA,MACZ,eAAe,IAAI;AAAA,MACnB,QAAQ,IAAI;AAAA,MACZ,aAAa,IAAI;AAAA,MACjB,UAAU,IAAI;AAAA,MACd,kBAAkB,IAAI;AAAA,MACtB,mBAAmB,IAAI;AAAA,MACvB,SAAS,IAAI;AAAA,MACb,kBAAkB,IAAI;AAAA,MACtB,wBAAwB,IAAI;AAAA,IAC9B,CAAC;AAAA,EACH;AAEA,QAAM,OAAO,CACX,SACA,SACmB;AACnB,UAAM,OAAO,sBAAsB,SAAS,IAAI;AAChD,UAAM,UAAU,OAAO,OAAO,MAAM,iBAAiB,IAAI,CAAC;AAE1D,UAAM,UAAU,OACd,QACkC;AAClC,YAAM,UAAU,QAAQ,MAAM;AAC9B,YAAM,MAAM,QAAQ,SAAS,GAAG;AAChC,aAAO,cAAc,QAAQ,GAAG;AAAA,IAClC;AAEA,WAAO,OAAO,OAAO,SAAS,EAAE,QAAQ,CAAC;AAAA,EAC3C;AAEA,SAAO;AAAA,IACL,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA,UAAU,cAAc;AAAA,EAC1B;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/sdk.ts"],"sourcesContent":["import type {\n ComposeCompileRequest,\n ComposeCompileResult,\n ComposeRouteRequest,\n InputSpec,\n SimulateRequest,\n SimulateResult,\n} from '@lifi/compose-spec';\n\nimport {\n createFlowBuilderCore,\n type FlowBuilderCore,\n type FlowOptions,\n type TypedFlow,\n} from './authoring/FlowBuilderCore.js';\nimport { type ComposeClient, createComposeClient } from './client.js';\nimport type { ChainSummary } from './discovery.js';\nimport {\n bindGeneratedOps,\n type GeneratedOps,\n} from './generated/operations.generated.js';\nimport { buildRun, type ComposeRunInput } from './run/inputs.js';\nimport type { InputSchema } from './types.js';\n\nexport type { ComposeRunInput };\n\n/**\n * A flow builder augmented with generated operation methods and a `compile` method\n * that submits the flow to the Compose backend for compilation.\n *\n * Created via {@link ComposeSdk.flow}.\n *\n * @typeParam T - The input schema describing the flow's required inputs.\n */\nexport type FlowBuilder<T extends InputSchema = InputSchema> =\n FlowBuilderCore<T> &\n GeneratedOps & {\n /**\n * Builds the flow document from the current builder state and submits it\n * to the Compose API for compilation.\n *\n * @param run - Runtime inputs, preconditions, and signer address.\n * @returns The compiled transaction calldata and metadata.\n * @throws {@link ComposeError} on network, validation, or server errors.\n *\n * @example\n * ```ts\n * const result = await builder.compile({\n * inputs: { token: materialisers.balanceOf({}) },\n * signer: '0xYourAddress...',\n * });\n * console.log(result.calldata);\n * ```\n */\n readonly compile: (\n run: ComposeRunInput<T>,\n ) => Promise<ComposeCompileResult>;\n };\n\n/**\n * Configuration for creating a Compose SDK instance.\n */\nexport interface ComposeSdkOptions {\n /** Base URL of the Compose API (e.g. `\"https://li.quest\"`). */\n readonly baseUrl: string;\n /** Optional custom `fetch` implementation. Defaults to `globalThis.fetch`. */\n readonly fetch?: typeof globalThis.fetch;\n /** LI.FI API key, sent as the `x-lifi-api-key` header on every request. Required — the Compose API rejects unauthenticated requests. */\n readonly apiKey: string;\n}\n\n/**\n * The top-level Compose SDK interface.\n *\n * Provides methods to build flows, compile them into executable calldata, and\n * interact with the Compose API directly.\n *\n * @example\n * ```ts\n * import { createComposeSdk, resources, materialisers } from '@lifi/composer-sdk';\n *\n * const sdk = createComposeSdk({ baseUrl: 'https://li.quest', apiKey: 'YOUR_API_KEY' });\n *\n * const builder = sdk.flow(1, {\n * inputs: { usdc: resources.erc20('0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', 1) },\n * });\n *\n * builder.lifi.swap('swap1', {\n * bind: { amountIn: builder.inputs.usdc },\n * config: { resourceOut: resources.native(1) },\n * });\n *\n * const result = await builder.compile({\n * inputs: { usdc: materialisers.balanceOf({}) },\n * signer: '0xYourAddress...',\n * });\n * ```\n */\nexport interface ComposeSdk {\n /** Low-level HTTP client for the Compose API. */\n readonly client: ComposeClient;\n /**\n * Creates a new flow builder targeting the given chain.\n * @param chainId - The EVM chain ID (e.g. `1` for Ethereum mainnet).\n * @param options - Flow configuration including input declarations.\n * @returns A {@link FlowBuilder} with generated operation methods and a `compile` method.\n * @throws Error if any resource input's `chainId` doesn't match the flow's `chainId`.\n */\n readonly flow: <T extends InputSchema>(\n chainId: number,\n options: FlowOptions<T>,\n ) => FlowBuilder<T>;\n /**\n * Fetches the chains this Compose deployment supports, ascending by\n * `chainId`. Thin pass-through to {@link ComposeClient.getChains}; see it\n * for what \"supported\" means and for the caching caveat.\n *\n * Each entry pairs the `chainId` with a display `name`, so one call both\n * gates a chain selector and labels it. Key on `chainId`; `name` is a\n * deployment-maintained label that can change.\n *\n * Use it to fail fast before building a flow for a chain the server would\n * reject.\n *\n * @returns The supported chains, ascending by `chainId`.\n * @throws {@link ComposeError} on network or server errors.\n *\n * @example\n * ```ts\n * const chains = await sdk.getSupportedChains();\n * if (!chains.some((c) => c.chainId === 8453)) {\n * throw new Error('Base is not supported');\n * }\n * for (const { chainId, name } of chains) {\n * console.log(`${name} (${chainId})`);\n * }\n * ```\n */\n readonly getSupportedChains: () => Promise<readonly ChainSummary[]>;\n /**\n * Builds a raw compile request without sending it. Useful for inspecting the\n * request payload or submitting it through a custom transport.\n * @param flow - A built flow document (from `builder.build()`).\n * @param run - Runtime inputs, preconditions, and signer address.\n * @returns A {@link ComposeCompileRequest} ready to send to the Compose API.\n */\n readonly request: <T extends InputSchema>(\n flow: TypedFlow<T>,\n run: ComposeRunInput<T>,\n ) => ComposeCompileRequest;\n /**\n * Compiles a token pair on one chain — as of today a single zap step over\n * one routing-catalog edge. Thin pass-through to\n * {@link ComposeClient.route}; see it for the current single-step limit,\n * when to prefer `flow(...).compile(...)`, the `success` / `partial`\n * discrimination, and error behaviour. Build the `amount` with\n * `routeAmount.exact(...)` / `routeAmount.all(...)`.\n *\n * @param request - The from/to token pair, amount, signer, and route options.\n * @returns A discriminated result: `status: 'success'` or `status: 'partial'`.\n * @throws {@link ComposeError} on network, validation, or server errors.\n */\n readonly route: (\n request: ComposeRouteRequest,\n ) => Promise<ComposeCompileResult>;\n /**\n * Simulates a raw, pre-encoded transaction. Thin pass-through to\n * {@link ComposeClient.simulate}; see it for the `ok` / `revert` / `error`\n * result discrimination and error behaviour. Pair with `buildSimulateRequest`\n * to assemble the request from a compile result.\n *\n * @param request - The raw transaction plus funding `requirements` and\n * `trackedBalances`.\n * @returns A {@link SimulateResult} (`ok` / `revert` / `error`).\n * @throws {@link ComposeError} on network, validation, or server errors.\n */\n readonly simulate: (request: SimulateRequest) => Promise<SimulateResult>;\n}\n\n/**\n * Creates a new Compose SDK instance.\n *\n * @param options - SDK configuration including the API base URL, required API key, and optional fetch implementation.\n * @returns A {@link ComposeSdk} instance.\n *\n * @example\n * ```ts\n * const sdk = createComposeSdk({ baseUrl: 'https://li.quest', apiKey: 'YOUR_API_KEY' });\n * ```\n */\nexport const createComposeSdk = (options: ComposeSdkOptions): ComposeSdk => {\n const composeClient = createComposeClient(options);\n\n const request = <T extends InputSchema>(\n flowDoc: TypedFlow<T>,\n run: ComposeRunInput<T>,\n ): ComposeCompileRequest => ({\n flow: flowDoc,\n run: buildRun({\n inputs: run.inputs as Record<string, InputSpec>,\n preconditions: run.preconditions,\n signer: run.signer,\n assumptions: run.assumptions as Record<string, bigint> | undefined,\n referrer: run.referrer,\n integratorFeeBps: run.integratorFeeBps,\n maxPriceImpactBps: run.maxPriceImpactBps,\n sweepTo: run.sweepTo,\n simulationPolicy: run.simulationPolicy,\n simulateUserProgram: run.simulateUserProgram,\n checkOnChainAllowances: run.checkOnChainAllowances,\n }),\n });\n\n const flow = <T extends InputSchema>(\n chainId: number,\n opts: FlowOptions<T>,\n ): FlowBuilder<T> => {\n const core = createFlowBuilderCore(chainId, opts);\n const builder = Object.assign(core, bindGeneratedOps(core));\n\n const compile = async (\n run: ComposeRunInput<T>,\n ): Promise<ComposeCompileResult> => {\n const flowDoc = builder.build();\n const req = request(flowDoc, run);\n return composeClient.compile(req);\n };\n\n return Object.assign(builder, { compile });\n };\n\n return {\n client: composeClient,\n flow,\n getSupportedChains: composeClient.getChains,\n request,\n route: composeClient.route,\n simulate: composeClient.simulate,\n };\n};\n"],"mappings":"AASA;AAAA,EACE;AAAA,OAIK;AACP,SAA6B,2BAA2B;AAExD;AAAA,EACE;AAAA,OAEK;AACP,SAAS,gBAAsC;AAyKxC,MAAM,mBAAmB,CAAC,YAA2C;AAC1E,QAAM,gBAAgB,oBAAoB,OAAO;AAEjD,QAAM,UAAU,CACd,SACA,SAC2B;AAAA,IAC3B,MAAM;AAAA,IACN,KAAK,SAAS;AAAA,MACZ,QAAQ,IAAI;AAAA,MACZ,eAAe,IAAI;AAAA,MACnB,QAAQ,IAAI;AAAA,MACZ,aAAa,IAAI;AAAA,MACjB,UAAU,IAAI;AAAA,MACd,kBAAkB,IAAI;AAAA,MACtB,mBAAmB,IAAI;AAAA,MACvB,SAAS,IAAI;AAAA,MACb,kBAAkB,IAAI;AAAA,MACtB,qBAAqB,IAAI;AAAA,MACzB,wBAAwB,IAAI;AAAA,IAC9B,CAAC;AAAA,EACH;AAEA,QAAM,OAAO,CACX,SACA,SACmB;AACnB,UAAM,OAAO,sBAAsB,SAAS,IAAI;AAChD,UAAM,UAAU,OAAO,OAAO,MAAM,iBAAiB,IAAI,CAAC;AAE1D,UAAM,UAAU,OACd,QACkC;AAClC,YAAM,UAAU,QAAQ,MAAM;AAC9B,YAAM,MAAM,QAAQ,SAAS,GAAG;AAChC,aAAO,cAAc,QAAQ,GAAG;AAAA,IAClC;AAEA,WAAO,OAAO,OAAO,SAAS,EAAE,QAAQ,CAAC;AAAA,EAC3C;AAEA,SAAO;AAAA,IACL,QAAQ;AAAA,IACR;AAAA,IACA,oBAAoB,cAAc;AAAA,IAClC;AAAA,IACA,OAAO,cAAc;AAAA,IACrB,UAAU,cAAc;AAAA,EAC1B;AACF;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types.ts"],"sourcesContent":["import type { Ref } from '@lifi/compose-spec';\nimport {\n InputSpec,\n MaterialiserInput,\n Resource,\n SolType,\n} from '@lifi/compose-spec';\n\n/**\n * A string that represents a non-negative integer (e.g. \"1000000000\").\n * Uses a template literal type so that only numeric-looking strings\n * are assignable at compile time.\n */\nexport type IntegerString = `${bigint}`;\n\n/**\n * Accepted input for integer-string config fields.\n * Callers may pass either a numeric string (\"1000000000\") or a native bigint\n * (1000000000n). Bigint values are stringified automatically during JSON\n * serialization via the SDK's `bigintReplacer`.\n */\nexport type IntegerStringInput = IntegerString | bigint;\n\n/**\n * A `0x`-prefixed hex string representing an Ethereum address.\n * Template literal type catches obviously wrong values at compile time.\n */\nexport type Address = `0x${string}`;\n\n/** The universe of output port kinds: Solidity scalar types plus `'resource'`. */\nexport type OutputKind = SolType | 'resource';\n\n/**\n * Maps an ABI parameter type string (from abitype's `ParseAbiItem`) to the\n * closest `OutputKind`. When the ABI type is one of the supported `SolType`\n * scalars, the mapping is exact; for all other Solidity types (e.g. tuples,\n * fixed-point decimals) it falls back to `SolType` — accepting any scalar\n * handle but not `'resource'` handles.\n *\n * The fallback excludes `'resource'` because every Solidity type is a scalar;\n * resource handles carry token-amount semantics that should only flow into\n * slots explicitly declared as resources.\n *\n * Extending `SolType` with new members automatically widens the exact-match\n * branch — no changes needed here.\n */\nexport type AbiTypeToOutputKind<T extends string> = T extends SolType\n ? T\n : SolType;\n\n/**\n * A typed `$ref` pointer carrying a phantom type parameter.\n * Extends `Ref` so it is accepted anywhere a plain `Ref` is.\n * The `__outputKind` field is never set at runtime — it exists only\n * for TypeScript's structural type checker to distinguish typed refs.\n */\nexport interface TypedRef<T extends OutputKind = OutputKind> extends Ref {\n readonly __outputKind?: T;\n}\n\n/**\n * An input declaration in a flow schema.\n * `Resource` values become resource inputs (token amounts);\n * `SolType` strings become handle inputs (scalars like addresses).\n */\nexport type InputDecl = Resource | SolType;\n\n/**\n * A record mapping input names to their declarations.\n * Used as the type parameter for generic flow builders and requests.\n */\nexport type InputSchema = Record<string, InputDecl>;\n\n/**\n * Maps an input declaration to the allowed runtime value type.\n * Resource inputs accept materialisers or literal amounts.\n * Handle inputs accept the scalar type matching their SolType.\n */\nexport type InputSpecOf<D> = D extends Resource\n ? MaterialiserInput | IntegerStringInput\n : D extends 'address'\n ? Address\n : D extends 'bool'\n ? boolean\n : D extends `${'u' | ''}int${string}`\n ? IntegerStringInput\n : D extends `bytes${string}`\n ? `0x${string}`\n : D extends 'string'\n ? string\n : InputSpec;\n\n/**\n * A guard applied to an operation, with the `port` field constrained\n * to a specific set of output port names.\n */\nexport interface TypedGuard<Port extends string = string> {\n readonly kind: string;\n readonly port: Port;\n readonly [key: string]: unknown;\n}\n"],"mappings":";;;;;;;;;;;;;;AAAA;AAAA;","names":[]}
1
+ {"version":3,"sources":["../src/types.ts"],"sourcesContent":["import type { LiteralBinding, Ref } from '@lifi/compose-spec';\nimport {\n InputSpec,\n MaterialiserInput,\n Resource,\n SolType,\n} from '@lifi/compose-spec';\n\n/**\n * A string that represents a non-negative integer (e.g. \"1000000000\").\n * Uses a template literal type so that only numeric-looking strings\n * are assignable at compile time.\n */\nexport type IntegerString = `${bigint}`;\n\n/**\n * Accepted input for integer-string config fields.\n * Callers may pass either a numeric string (\"1000000000\") or a native bigint\n * (1000000000n). Bigint values are stringified automatically during JSON\n * serialization via the SDK's `bigintReplacer`.\n */\nexport type IntegerStringInput = IntegerString | bigint;\n\n/**\n * A `0x`-prefixed hex string representing an Ethereum address.\n * Template literal type catches obviously wrong values at compile time.\n */\nexport type Address = `0x${string}`;\n\n/** The universe of output port kinds: Solidity scalar types plus `'resource'`. */\nexport type OutputKind = SolType | 'resource';\n\n/**\n * Maps an ABI parameter type string (from abitype's `ParseAbiItem`) to the\n * closest `OutputKind`. When the ABI type is one of the supported `SolType`\n * scalars, the mapping is exact; for all other Solidity types (e.g. tuples,\n * fixed-point decimals) it falls back to `SolType` — accepting any scalar\n * handle but not `'resource'` handles.\n *\n * The fallback excludes `'resource'` because every Solidity type is a scalar;\n * resource handles carry token-amount semantics that should only flow into\n * slots explicitly declared as resources.\n *\n * Extending `SolType` with new members automatically widens the exact-match\n * branch — no changes needed here.\n */\nexport type AbiTypeToOutputKind<T extends string> = T extends SolType\n ? T\n : SolType;\n\n/**\n * A typed `$ref` pointer carrying a phantom type parameter.\n * Extends `Ref` so it is accepted anywhere a plain `Ref` is.\n * The `__outputKind` field is never set at runtime — it exists only\n * for TypeScript's structural type checker to distinguish typed refs.\n */\nexport interface TypedRef<T extends OutputKind = OutputKind> extends Ref {\n readonly __outputKind?: T;\n}\n\n/**\n * A literal bind value carrying a phantom type parameter.\n *\n * The wire format accepts a constant in a bind slot as\n * `{ kind: <solType>, value: <string> }`, alongside `$ref` pointers. Use it\n * for a value that must be baked into the flow document rather than supplied\n * at run time — the destination of a flow the backend stores and re-runs\n * later (a `continuation.settle` node's `continuationFlow`) has no run to\n * take an input from.\n *\n * @typeParam T - The Solidity type of the literal (e.g. `'address'`).\n */\nexport interface TypedLiteral<\n T extends SolType = SolType,\n> extends LiteralBinding {\n readonly kind: T;\n readonly __outputKind?: T;\n}\n\n/**\n * An input declaration in a flow schema.\n * `Resource` values become resource inputs (token amounts);\n * `SolType` strings become handle inputs (scalars like addresses).\n */\nexport type InputDecl = Resource | SolType;\n\n/**\n * A record mapping input names to their declarations.\n * Used as the type parameter for generic flow builders and requests.\n */\nexport type InputSchema = Record<string, InputDecl>;\n\n/**\n * Maps an input declaration to the allowed runtime value type.\n * Resource inputs accept materialisers or literal amounts.\n * Handle inputs accept the scalar type matching their SolType.\n */\nexport type InputSpecOf<D> = D extends Resource\n ? MaterialiserInput | IntegerStringInput\n : D extends 'address'\n ? Address\n : D extends 'bool'\n ? boolean\n : D extends `${'u' | ''}int${string}`\n ? IntegerStringInput\n : D extends `bytes${string}`\n ? `0x${string}`\n : D extends 'string'\n ? string\n : InputSpec;\n\n/**\n * A guard applied to an operation, with the `port` field constrained\n * to a specific set of output port names.\n */\nexport interface TypedGuard<Port extends string = string> {\n readonly kind: string;\n readonly port: Port;\n readonly [key: string]: unknown;\n}\n"],"mappings":";;;;;;;;;;;;;;AAAA;AAAA;","names":[]}
package/dist/types.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { SolType, Ref, Resource, MaterialiserInput, InputSpec } from '@lifi/compose-spec';
1
+ import { SolType, Ref, LiteralBinding, Resource, MaterialiserInput, InputSpec } from '@lifi/compose-spec';
2
2
 
3
3
  /**
4
4
  * A string that represents a non-negative integer (e.g. "1000000000").
@@ -44,6 +44,22 @@ type AbiTypeToOutputKind<T extends string> = T extends SolType ? T : SolType;
44
44
  interface TypedRef<T extends OutputKind = OutputKind> extends Ref {
45
45
  readonly __outputKind?: T;
46
46
  }
47
+ /**
48
+ * A literal bind value carrying a phantom type parameter.
49
+ *
50
+ * The wire format accepts a constant in a bind slot as
51
+ * `{ kind: <solType>, value: <string> }`, alongside `$ref` pointers. Use it
52
+ * for a value that must be baked into the flow document rather than supplied
53
+ * at run time — the destination of a flow the backend stores and re-runs
54
+ * later (a `continuation.settle` node's `continuationFlow`) has no run to
55
+ * take an input from.
56
+ *
57
+ * @typeParam T - The Solidity type of the literal (e.g. `'address'`).
58
+ */
59
+ interface TypedLiteral<T extends SolType = SolType> extends LiteralBinding {
60
+ readonly kind: T;
61
+ readonly __outputKind?: T;
62
+ }
47
63
  /**
48
64
  * An input declaration in a flow schema.
49
65
  * `Resource` values become resource inputs (token amounts);
@@ -71,4 +87,4 @@ interface TypedGuard<Port extends string = string> {
71
87
  readonly [key: string]: unknown;
72
88
  }
73
89
 
74
- export type { AbiTypeToOutputKind, Address, InputDecl, InputSchema, InputSpecOf, IntegerString, IntegerStringInput, OutputKind, TypedGuard, TypedRef };
90
+ export type { AbiTypeToOutputKind, Address, InputDecl, InputSchema, InputSpecOf, IntegerString, IntegerStringInput, OutputKind, TypedGuard, TypedLiteral, TypedRef };
package/dist/types.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { SolType, Ref, Resource, MaterialiserInput, InputSpec } from '@lifi/compose-spec';
1
+ import { SolType, Ref, LiteralBinding, Resource, MaterialiserInput, InputSpec } from '@lifi/compose-spec';
2
2
 
3
3
  /**
4
4
  * A string that represents a non-negative integer (e.g. "1000000000").
@@ -44,6 +44,22 @@ type AbiTypeToOutputKind<T extends string> = T extends SolType ? T : SolType;
44
44
  interface TypedRef<T extends OutputKind = OutputKind> extends Ref {
45
45
  readonly __outputKind?: T;
46
46
  }
47
+ /**
48
+ * A literal bind value carrying a phantom type parameter.
49
+ *
50
+ * The wire format accepts a constant in a bind slot as
51
+ * `{ kind: <solType>, value: <string> }`, alongside `$ref` pointers. Use it
52
+ * for a value that must be baked into the flow document rather than supplied
53
+ * at run time — the destination of a flow the backend stores and re-runs
54
+ * later (a `continuation.settle` node's `continuationFlow`) has no run to
55
+ * take an input from.
56
+ *
57
+ * @typeParam T - The Solidity type of the literal (e.g. `'address'`).
58
+ */
59
+ interface TypedLiteral<T extends SolType = SolType> extends LiteralBinding {
60
+ readonly kind: T;
61
+ readonly __outputKind?: T;
62
+ }
47
63
  /**
48
64
  * An input declaration in a flow schema.
49
65
  * `Resource` values become resource inputs (token amounts);
@@ -71,4 +87,4 @@ interface TypedGuard<Port extends string = string> {
71
87
  readonly [key: string]: unknown;
72
88
  }
73
89
 
74
- export type { AbiTypeToOutputKind, Address, InputDecl, InputSchema, InputSpecOf, IntegerString, IntegerStringInput, OutputKind, TypedGuard, TypedRef };
90
+ export type { AbiTypeToOutputKind, Address, InputDecl, InputSchema, InputSpecOf, IntegerString, IntegerStringInput, OutputKind, TypedGuard, TypedLiteral, TypedRef };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lifi/composer-sdk",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Public Composer SDK for building and submitting flows",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -28,9 +28,6 @@
28
28
  "publishConfig": {
29
29
  "access": "public"
30
30
  },
31
- "prettier": {
32
- "singleQuote": true
33
- },
34
31
  "scripts": {
35
32
  "build": "tsc --noEmit && tsup",
36
33
  "clean": "rm -rf dist out",
@@ -40,18 +37,16 @@
40
37
  "test": "vitest run --config vitest.config.ts",
41
38
  "check:types": "tsc --noEmit",
42
39
  "check:sdk-drift": "vitest run --config vitest.drift.config.ts",
43
- "fix": "run-s fix:lint fix:prettier",
40
+ "fix": "yarn fix:lint",
44
41
  "fix:lint": "eslint src --fix",
45
- "fix:prettier": "prettier \"src/**/*.ts\" \"scripts/**/*.ts\" --write",
46
42
  "lint": "eslint src",
47
43
  "test:lint": "eslint src",
48
- "test:prettier": "prettier \"src/**/*.ts\" \"scripts/**/*.ts\" --list-different",
49
44
  "verify:staged": "bash scripts/verify-staged.sh",
50
45
  "example": "tsx src/examples/run.ts",
51
46
  "example:staged": "tsx src/examples/run.ts --staged"
52
47
  },
53
48
  "peerDependencies": {
54
- "@lifi/compose-spec": "0.4.0"
49
+ "@lifi/compose-spec": "0.5.0"
55
50
  },
56
51
  "dependencies": {
57
52
  "abitype": "^1.2.3",
@@ -62,19 +57,17 @@
62
57
  "@eslint/compat": "^1.4.0",
63
58
  "@lifi/compose-spec": "workspace:^",
64
59
  "@types/node": "^25.6.0",
65
- "@typescript-eslint/eslint-plugin": "^8.44.1",
66
- "@typescript-eslint/parser": "^8.44.1",
60
+ "@typescript-eslint/eslint-plugin": "^8.68.0",
61
+ "@typescript-eslint/parser": "^8.68.0",
67
62
  "eslint": "^9.36.0",
68
63
  "eslint-config-prettier": "^9.0.0",
69
64
  "eslint-plugin-eslint-comments": "^3.2.0",
70
65
  "eslint-plugin-import": "^2.22.0",
71
66
  "eslint-plugin-require-extensions": "^0.1.3",
72
67
  "json-schema-to-typescript": "^15.0.4",
73
- "npm-run-all": "^4.1.5",
74
- "prettier": "^3.9.4",
75
68
  "tsup": "^8.5.1",
76
69
  "tsx": "^4.20.4",
77
- "typescript": "^5.9.2",
70
+ "typescript": "^6.0.3",
78
71
  "vitest": "^3.2.4"
79
72
  },
80
73
  "files": [
@@ -1,9 +1,9 @@
1
1
  import type {
2
2
  AppliedGuard,
3
+ BindValue,
3
4
  Call,
4
5
  Flow,
5
6
  FlowInput,
6
- Ref,
7
7
  Resource,
8
8
  SolType,
9
9
  } from '@lifi/compose-spec';
@@ -13,6 +13,7 @@ import type {
13
13
  InputSchema,
14
14
  OutputKind,
15
15
  TypedGuard,
16
+ TypedLiteral,
16
17
  TypedRef,
17
18
  } from '../types.js';
18
19
 
@@ -21,7 +22,7 @@ import type {
21
22
  OutputHandle,
22
23
  ResourceInputHandle,
23
24
  } from './handles.js';
24
- import { handleToRef } from './handles.js';
25
+ import { toBindValue } from './handles.js';
25
26
  import { ref } from './raw.js';
26
27
 
27
28
  /**
@@ -37,17 +38,14 @@ export interface CallArgs {
37
38
  }
38
39
 
39
40
  /**
40
- * Any value that can be bound to an operation parameter: an input handle,
41
- * an output handle from a previous operation, or a typed `$ref` pointer.
41
+ * Any value that can be bound to an operation parameter: an input handle, an
42
+ * output handle from a previous operation, a typed `$ref` pointer, or a typed
43
+ * literal.
42
44
  *
43
- * Use `raw.ref<T>()` to create a typed ref from a raw path string.
45
+ * Use `raw.ref<T>()` to create a typed ref from a raw path string, and
46
+ * `raw.literal<T>()` to bake in a constant.
44
47
  */
45
- export type AnyBindable = InputHandle | OutputHandle | TypedRef;
46
-
47
- const toRef = (bindable: AnyBindable): Ref => {
48
- if ('_tag' in bindable) return handleToRef(bindable);
49
- return bindable;
50
- };
48
+ export type AnyBindable = InputHandle | OutputHandle | TypedRef | TypedLiteral;
51
49
 
52
50
  /**
53
51
  * Provides references to runtime context values available inside a flow.
@@ -127,7 +125,7 @@ export interface FlowBuilderCore<T extends InputSchema = InputSchema> {
127
125
  id: string,
128
126
  op: string,
129
127
  args: {
130
- readonly bind: Record<string, Ref>;
128
+ readonly bind: Record<string, BindValue>;
131
129
  readonly config: Record<string, unknown>;
132
130
  readonly guards?: readonly AppliedGuard[];
133
131
  },
@@ -196,9 +194,9 @@ export const createFlowBuilderCore = <T extends InputSchema>(
196
194
  if (nodeIds.has(nodeId)) throw new Error(`Duplicate node id: "${nodeId}"`);
197
195
  nodeIds.add(nodeId);
198
196
 
199
- const bind: Record<string, Ref> = {};
197
+ const bind: Record<string, BindValue> = {};
200
198
  for (const [key, val] of Object.entries(args.bind)) {
201
- bind[key] = toRef(val);
199
+ bind[key] = toBindValue(val);
202
200
  }
203
201
 
204
202
  const node: Call = {
@@ -230,7 +228,7 @@ export const createFlowBuilderCore = <T extends InputSchema>(
230
228
  nodeId: string,
231
229
  op: string,
232
230
  args: {
233
- readonly bind: Record<string, Ref>;
231
+ readonly bind: Record<string, BindValue>;
234
232
  readonly config: Record<string, unknown>;
235
233
  readonly guards?: readonly AppliedGuard[];
236
234
  },