@eco-incorp/sauce 0.99.1 → 0.99.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +29 -0
- package/README.md +69 -249
- package/actions/dist/to-sauce.d.ts.map +1 -1
- package/actions/dist/to-sauce.js +4 -5
- package/dev-tools/README.md +11 -170
- package/docs/README.md +39 -0
- package/docs/api/README.md +71 -0
- package/docs/api/compiler.md +234 -0
- package/docs/api/coverage.md +117 -0
- package/docs/api/routes.md +110 -0
- package/docs/concepts/architecture.md +134 -0
- package/docs/concepts/saucescript.md +172 -0
- package/docs/examples/README.md +34 -0
- package/docs/examples/compile-program.ts +20 -0
- package/docs/examples/evm-execution.ts +59 -0
- package/docs/examples/first-intent.ts +56 -0
- package/docs/examples/protocol-approval.ts +33 -0
- package/docs/guides/builders-and-actions.md +108 -0
- package/docs/guides/compiling.md +264 -0
- package/docs/guides/intents.md +158 -0
- package/docs/guides/nested-intents.md +79 -0
- package/docs/guides/protocols-and-tokens.md +116 -0
- package/docs/guides/quick-start.md +64 -0
- package/docs/guides/solana.md +199 -0
- package/docs/guides/verification.md +253 -0
- package/package.json +9 -4
- package/sdk/dist/artifacts/V12Deployments.json +23 -5
- package/sdk/dist/artifacts/V12RuntimeBytecode.json +1 -1
- package/sdk/dist/artifacts/svm/engine-devnet.so +0 -0
- package/sdk/dist/artifacts/svm/engine-mainnet.so +0 -0
- package/sdk/dist/artifacts/svm/engine-wire-devnet.json +18 -3
- package/sdk/dist/artifacts/svm/engine-wire-mainnet.json +18 -3
- package/sdk/dist/deployments/index.d.ts +14 -46
- package/sdk/dist/deployments/index.d.ts.map +1 -1
- package/sdk/dist/deployments/index.js +22 -47
- package/sdk/dist/deployments/index.js.map +1 -1
- package/sdk/dist/deployments/v12-addresses.d.ts +9 -5
- package/sdk/dist/deployments/v12-addresses.d.ts.map +1 -1
- package/sdk/dist/deployments/v12-addresses.js +5 -6
- package/sdk/dist/deployments/v12-addresses.js.map +1 -1
- package/sdk/dist/deployments/v12.generated.d.ts +3 -3
- package/sdk/dist/deployments/v12.generated.d.ts.map +1 -1
- package/sdk/dist/deployments/v12.generated.js +3 -3
- package/sdk/dist/deployments/v12.generated.js.map +1 -1
- package/sdk/dist/deposit/index.d.ts +28 -102
- package/sdk/dist/deposit/index.d.ts.map +1 -1
- package/sdk/dist/deposit/index.js.map +1 -1
- package/sdk/dist/deposit/params.d.ts +1 -1
- package/sdk/dist/deposit/params.js +2 -2
- package/sdk/dist/deposit/params.js.map +1 -1
- package/sdk/dist/deposit/source.d.ts +1 -1
- package/sdk/dist/deposit/source.d.ts.map +1 -1
- package/sdk/dist/deposit/source.js +18 -33
- package/sdk/dist/deposit/source.js.map +1 -1
- package/sdk/dist/deposit/types.d.ts +5 -4
- package/sdk/dist/deposit/types.d.ts.map +1 -1
- package/sdk/dist/evm/engine.d.ts +32 -0
- package/sdk/dist/evm/engine.d.ts.map +1 -1
- package/sdk/dist/evm/engine.js +2 -0
- package/sdk/dist/evm/engine.js.map +1 -1
- package/sdk/dist/index.d.ts +1 -0
- package/sdk/dist/index.d.ts.map +1 -1
- package/sdk/dist/index.js +2 -0
- package/sdk/dist/index.js.map +1 -1
- package/sdk/dist/plugin/index.d.ts +16 -41
- package/sdk/dist/plugin/index.d.ts.map +1 -1
- package/sdk/dist/plugin/index.js +2 -6
- package/sdk/dist/plugin/index.js.map +1 -1
- package/sdk/dist/recipes/index.js +2 -2
- package/sdk/dist/recipes/settle.sauce.ts +1 -1
- package/sdk/dist/routes/index.d.ts +3 -3
- package/sdk/dist/routes/index.js +3 -3
- package/sdk/dist/routes/intent-dsl.d.ts +23 -10
- package/sdk/dist/routes/intent-dsl.d.ts.map +1 -1
- package/sdk/dist/routes/intent-dsl.js +19 -2
- package/sdk/dist/routes/intent-dsl.js.map +1 -1
- package/sdk/dist/routes/nest.d.ts +23 -0
- package/sdk/dist/routes/nest.d.ts.map +1 -1
- package/sdk/dist/routes/nest.js +2 -4
- package/sdk/dist/routes/nest.js.map +1 -1
- package/sdk/dist/routes/protocol-rewrite.d.ts +2 -2
- package/sdk/dist/routes/protocol-rewrite.d.ts.map +1 -1
- package/sdk/dist/routes/protocol-rewrite.js +19 -35
- package/sdk/dist/routes/protocol-rewrite.js.map +1 -1
- package/sdk/dist/routes/sauce-calls.d.ts +7 -13
- package/sdk/dist/routes/sauce-calls.d.ts.map +1 -1
- package/sdk/dist/routes/sauce-calls.js +6 -11
- package/sdk/dist/routes/sauce-calls.js.map +1 -1
- package/sdk/dist/routes/sauce-route.d.ts +24 -53
- package/sdk/dist/routes/sauce-route.d.ts.map +1 -1
- package/sdk/dist/routes/sauce-route.js +5 -6
- package/sdk/dist/routes/sauce-route.js.map +1 -1
- package/sdk/dist/routes/source-globals.generated.d.ts +931 -0
- package/sdk/dist/routes/source-globals.generated.d.ts.map +1 -0
- package/sdk/dist/routes/source-globals.generated.js +7 -0
- package/sdk/dist/routes/source-globals.generated.js.map +1 -0
- package/sdk/dist/std/token/token.svm.js +19 -14
- package/sdk/dist/svm/cpi-probe.d.ts +1 -1
- package/sdk/dist/svm/cpi-probe.d.ts.map +1 -1
- package/sdk/dist/svm/cpi-probe.js +5 -2
- package/sdk/dist/svm/cpi-probe.js.map +1 -1
- package/sdk/dist/svm/engine.d.ts +4 -3
- package/sdk/dist/svm/engine.d.ts.map +1 -1
- package/sdk/dist/svm/engine.js +4 -3
- package/sdk/dist/svm/engine.js.map +1 -1
- package/sdk/dist/svm/intent.d.ts +12 -40
- package/sdk/dist/svm/intent.d.ts.map +1 -1
- package/sdk/dist/svm/intent.js +22 -66
- package/sdk/dist/svm/intent.js.map +1 -1
- package/sdk/dist/svm/kitchen.d.ts.map +1 -1
- package/sdk/dist/svm/kitchen.js +3 -4
- package/sdk/dist/svm/kitchen.js.map +1 -1
- package/sdk/dist/svm/venues/byreal/index.d.ts.map +1 -1
- package/sdk/dist/svm/venues/byreal/index.js +4 -1
- package/sdk/dist/svm/venues/byreal/index.js.map +1 -1
- package/sdk/dist/svm/venues/carrot/index.d.ts.map +1 -1
- package/sdk/dist/svm/venues/carrot/index.js +4 -0
- package/sdk/dist/svm/venues/carrot/index.js.map +1 -1
- package/sdk/dist/svm/venues/cropper/index.d.ts +1 -1
- package/sdk/dist/svm/venues/cropper/index.js +1 -1
- package/sdk/dist/svm/venues/huma/index.d.ts.map +1 -1
- package/sdk/dist/svm/venues/huma/index.js +4 -1
- package/sdk/dist/svm/venues/huma/index.js.map +1 -1
- package/sdk/dist/svm/venues/index.d.ts +1 -0
- package/sdk/dist/svm/venues/index.d.ts.map +1 -1
- package/sdk/dist/svm/venues/index.js +1 -0
- package/sdk/dist/svm/venues/index.js.map +1 -1
- package/sdk/dist/svm/venues/math.d.ts +4 -1
- package/sdk/dist/svm/venues/math.d.ts.map +1 -1
- package/sdk/dist/svm/venues/math.js +4 -1
- package/sdk/dist/svm/venues/math.js.map +1 -1
- package/sdk/dist/svm/venues/meteora-damm-v1-stable/index.d.ts.map +1 -1
- package/sdk/dist/svm/venues/meteora-damm-v1-stable/index.js +4 -1
- package/sdk/dist/svm/venues/meteora-damm-v1-stable/index.js.map +1 -1
- package/sdk/dist/svm/venues/meteora-damm-v2/index.d.ts.map +1 -1
- package/sdk/dist/svm/venues/meteora-damm-v2/index.js +5 -2
- package/sdk/dist/svm/venues/meteora-damm-v2/index.js.map +1 -1
- package/sdk/dist/svm/venues/obric-v2/index.d.ts.map +1 -1
- package/sdk/dist/svm/venues/obric-v2/index.js +16 -5
- package/sdk/dist/svm/venues/obric-v2/index.js.map +1 -1
- package/sdk/dist/svm/venues/oracle-exponent.d.ts +82 -0
- package/sdk/dist/svm/venues/oracle-exponent.d.ts.map +1 -0
- package/sdk/dist/svm/venues/oracle-exponent.js +97 -0
- package/sdk/dist/svm/venues/oracle-exponent.js.map +1 -0
- package/sdk/dist/svm/venues/orca-legacy-token-swap/index.d.ts.map +1 -1
- package/sdk/dist/svm/venues/orca-legacy-token-swap/index.js +4 -1
- package/sdk/dist/svm/venues/orca-legacy-token-swap/index.js.map +1 -1
- package/sdk/dist/svm/venues/pumpswap/index.d.ts.map +1 -1
- package/sdk/dist/svm/venues/pumpswap/index.js +19 -13
- package/sdk/dist/svm/venues/pumpswap/index.js.map +1 -1
- package/sdk/dist/svm/venues/raydium-amm-v4/index.d.ts.map +1 -1
- package/sdk/dist/svm/venues/raydium-amm-v4/index.js +4 -1
- package/sdk/dist/svm/venues/raydium-amm-v4/index.js.map +1 -1
- package/sdk/dist/svm/venues/raydium-clmm/index.d.ts.map +1 -1
- package/sdk/dist/svm/venues/raydium-clmm/index.js +4 -1
- package/sdk/dist/svm/venues/raydium-clmm/index.js.map +1 -1
- package/sdk/dist/svm/venues/raydium-cp-swap/index.d.ts.map +1 -1
- package/sdk/dist/svm/venues/raydium-cp-swap/index.js +4 -1
- package/sdk/dist/svm/venues/raydium-cp-swap/index.js.map +1 -1
- package/sdk/dist/svm/venues/scorch/index.d.ts.map +1 -1
- package/sdk/dist/svm/venues/scorch/index.js +4 -1
- package/sdk/dist/svm/venues/scorch/index.js.map +1 -1
- package/sdk/dist/svm/venues/stabble-common.d.ts +1 -1
- package/sdk/dist/svm/venues/stabble-common.js +1 -1
- package/sdk/dist/svm/venues/types.d.ts +4 -1
- package/sdk/dist/svm/venues/types.d.ts.map +1 -1
- package/sdk/dist/svm/venues/woofi/index.d.ts.map +1 -1
- package/sdk/dist/svm/venues/woofi/index.js +4 -0
- package/sdk/dist/svm/venues/woofi/index.js.map +1 -1
- package/sdk/dist/svm/verify.d.ts +27 -133
- package/sdk/dist/svm/verify.d.ts.map +1 -1
- package/sdk/dist/svm/verify.js +72 -139
- package/sdk/dist/svm/verify.js.map +1 -1
- package/sdk/dist/swap/index.d.ts +16 -59
- package/sdk/dist/swap/index.d.ts.map +1 -1
- package/sdk/dist/swap/index.js +16 -59
- package/sdk/dist/swap/index.js.map +1 -1
- package/sdk/dist/token/source.d.ts.map +1 -1
- package/sdk/dist/token/source.js +4 -1
- package/sdk/dist/token/source.js.map +1 -1
- package/sdk/dist/verify/decode.d.ts +6 -6
- package/sdk/dist/verify/decode.js +7 -7
- package/sdk/dist/verify/index.js +2 -2
- package/sdk/dist/verify/intent.js +2 -2
- package/sdk/dist/verify/vectors.d.ts +1 -1
- package/sdk/dist/verify/vectors.d.ts.map +1 -1
- package/sdk/dist/verify/vectors.js +2 -2
- package/sdk/dist/verify/vectors.js.map +1 -1
- package/sdk/dist/verify/wire.d.ts +5 -4
- package/sdk/dist/verify/wire.d.ts.map +1 -1
- package/sdk/dist/verify/wire.js +5 -4
- package/sdk/dist/verify/wire.js.map +1 -1
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Quick start
|
|
2
|
+
|
|
3
|
+
[Documentation](../README.md) · [Protocols and tokens](protocols-and-tokens.md) · [Intents](intents.md)
|
|
4
|
+
|
|
5
|
+
Use Node.js 24 or newer and install the single public package:
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
pnpm add @eco-incorp/sauce
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
The Sauce compiler is a dependency of that package. You do not need a compiler checkout or a separate compiler install.
|
|
12
|
+
|
|
13
|
+
## Compile your first intent
|
|
14
|
+
|
|
15
|
+
This complete TypeScript example builds an approval intent offline. Addresses and the fee are fixtures; the zero reward demonstrates construction only. Before submission, [read the current Kitchen fee and prepare an Executor-owned Pot](intents.md#prepare-the-destination-pot).
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import "@eco-incorp/sauce";
|
|
19
|
+
import type { routes } from "@eco-incorp/sauce";
|
|
20
|
+
|
|
21
|
+
const executionFee = 1_000n; // Fixture: read the destination Kitchen's executionFee() before use.
|
|
22
|
+
const options: routes.IntentOptions = {
|
|
23
|
+
execution: {
|
|
24
|
+
pot: "0x1111111111111111111111111111111111111111",
|
|
25
|
+
engine: "0x2222222222222222222222222222222222222222",
|
|
26
|
+
value: executionFee,
|
|
27
|
+
},
|
|
28
|
+
nativeAmount: executionFee,
|
|
29
|
+
portal: "0x3333333333333333333333333333333333333333",
|
|
30
|
+
deadline: 2_000_000_000n,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const built = Base(() => {
|
|
34
|
+
USDC.approve(Uniswap.UniversalRouter, 1_000_000n);
|
|
35
|
+
}, options).reward({
|
|
36
|
+
source: "ethereum",
|
|
37
|
+
creator: "0x4444444444444444444444444444444444444444",
|
|
38
|
+
prover: "0x5555555555555555555555555555555555555555",
|
|
39
|
+
deadline: 2_000_003_600n,
|
|
40
|
+
nativeAmount: 0n,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
console.log(built.hash().intentHash);
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Importing the root package installs `Base` and the other chain globals. Inside the callback, the SDK resolves `USDC` and `Uniswap.UniversalRouter` for Base, compiles the body with Sauce, and encodes a Pot `cook(engine, program)` call. `.reward(...)` completes the Eco intent. Nothing is submitted to a chain.
|
|
47
|
+
|
|
48
|
+
For execution, deploy the Pot with the destination `Portal.executor()` as owner and pay the current Kitchen fee on every cook. [Intent setup](intents.md#prepare-the-destination-pot) shows the reads and deployment call. Fund and empty that shared Pot within the fulfillment.
|
|
49
|
+
|
|
50
|
+
`USDC` and protocol names have generated TypeScript declarations but are source syntax, not JavaScript clients. The router is registered as `UniswapV4.UniversalRouter`, with `Uniswap.UniversalRouter` as a family alias. `UniswapV3.UniversalRouter` is not a registered name. See [coverage](../api/coverage.md) for which protocols expose these namespaces.
|
|
51
|
+
|
|
52
|
+
The callback captures no outer variables. Pass dynamic scalars through `defines`, or use explicit source strings; see the complete [transfer example](../examples/first-intent.ts). Callbacks must remain recognizable synchronous source after your build tooling transforms them.
|
|
53
|
+
|
|
54
|
+
## Deliver assets and fund the reward
|
|
55
|
+
|
|
56
|
+
In a transfer intent, the destination assets and source reward are separate. Destination `tokens` reach the Portal Executor. Add a transfer precall to deliver tokens into the Pot before Sauce spends them. Source reward tokens are approved to the source Portal and escrowed through its funding call.
|
|
57
|
+
|
|
58
|
+
The [first-intent.ts example](../examples/first-intent.ts) constructs both sides and returns source transaction requests. Read [creating intents](intents.md) before submitting those requests, and [nested intents](nested-intents.md) to compose subsequent routes.
|
|
59
|
+
|
|
60
|
+
## Compile a standalone program
|
|
61
|
+
|
|
62
|
+
Use `@eco-incorp/sauce/compiler` when you need raw bytecode, entry schemas, or an SVM account manifest. It exposes the published Rust/Wasm compiler through `compile(options)`; it does not install SDK protocol namespaces into arbitrary compiler input.
|
|
63
|
+
|
|
64
|
+
The [compiler example](../examples/compile-program.ts) compiles a typed SauceScript entry point and appends compact arguments. [Compiling](compiling.md) explains module resolution and the distinction between raw compiler output and the route wrapper.
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
# Solana programs and execution
|
|
2
|
+
|
|
3
|
+
[Documentation](../README.md) · [Compiler](../api/compiler.md) · [Coverage](../api/coverage.md)
|
|
4
|
+
|
|
5
|
+
Solana programs use the `svm` compiler target, explicit account parameters, and a Kitchen that invokes the engine. EVM token/protocol member rewrites such as `USDC.transfer(...)` do not apply to SVM routes.
|
|
6
|
+
|
|
7
|
+
Use `@eco-incorp/sauce/compiler` to retain the compiler's account manifest. `routes.compileSauceRoute()` returns execution calls and a `compiled.bytecode` segment list, but does not expose that manifest; applications resolving account slots should use the direct compiler result.
|
|
8
|
+
|
|
9
|
+
## Compile an SPL transfer
|
|
10
|
+
|
|
11
|
+
The universal token builder emits account parameters and an SPL `TransferChecked` CPI. Its source needs no imports, so a single-module resolver is sufficient:
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { token } from "@eco-incorp/sauce";
|
|
15
|
+
import { compile } from "@eco-incorp/sauce/compiler";
|
|
16
|
+
|
|
17
|
+
export function compileSplTransfer(amount: bigint) {
|
|
18
|
+
const source = token.Token.transfer({
|
|
19
|
+
amount,
|
|
20
|
+
svm: {
|
|
21
|
+
source: "sourceAta",
|
|
22
|
+
mint: "mint",
|
|
23
|
+
dest: "destinationAta",
|
|
24
|
+
owner: "owner",
|
|
25
|
+
tokenProgram: "tokenProgram",
|
|
26
|
+
},
|
|
27
|
+
}).source("svm");
|
|
28
|
+
|
|
29
|
+
return compile({
|
|
30
|
+
target: "svm",
|
|
31
|
+
entry: "main.ts",
|
|
32
|
+
resolve: (id) => (id === "main.ts" ? new TextEncoder().encode(source) : null),
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
The account references are names, not addresses. `manifest.accounts` records their order and required roles. Resolve them to the mint, source token account, destination token account, authority, and token program before execution. Amounts are smallest-unit integers. The builder reads mint decimals for the checked instruction and defaults to the classic SPL Token program. Set the builder's top-level `tokenProgram: "token-2022"` for a supported Token-2022 operation; `svm.tokenProgram` names the account reference and must resolve to that token program.
|
|
38
|
+
|
|
39
|
+
## Execute through the Kitchen
|
|
40
|
+
|
|
41
|
+
`createSauceSvmClient` requires an RPC URL, engine program ID, Kitchen program ID, and a Kit transaction signer. Its inline execution path constructs a Kitchen `cook`, includes the required heap-frame instruction, resolves accounts, and builds/signs transactions.
|
|
42
|
+
|
|
43
|
+
Use `v12SvmEngineProgramId()` and `v12SvmKitchenProgramId()` from
|
|
44
|
+
`@eco-incorp/sauce/deployments` for the released program identities, and confirm
|
|
45
|
+
they are deployed on your cluster. The older `v12SvmProgramId` constant identifies
|
|
46
|
+
a legacy engine. The client derives a Pot owned by its `payer` signer; select it
|
|
47
|
+
with `potSalt` when configuring the client.
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
import {
|
|
51
|
+
createSauceSvmClient,
|
|
52
|
+
type AccountResolution,
|
|
53
|
+
type SauceSvmClientConfig,
|
|
54
|
+
} from "@eco-incorp/sauce/svm";
|
|
55
|
+
import type { CompileResult } from "@eco-incorp/sauce/compiler";
|
|
56
|
+
|
|
57
|
+
export async function simulateProgram(
|
|
58
|
+
config: SauceSvmClientConfig,
|
|
59
|
+
compiled: CompileResult,
|
|
60
|
+
accounts: AccountResolution,
|
|
61
|
+
) {
|
|
62
|
+
if (!compiled.manifest) throw new Error("Expected an SVM account manifest");
|
|
63
|
+
const client = await createSauceSvmClient(config);
|
|
64
|
+
return client.simulate(compiled.bytecode, compiled.manifest, accounts);
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
For the transfer above, the resolution keys are `sourceAta`, `mint`, `destinationAta`, `owner`, and `tokenProgram`. A non-payer transaction authority should be supplied as `{ address, signer: transactionSigner }`; an address alone cannot provide its signature. A Pot PDA that the Kitchen signs for must be attached with `signer: false` in the transaction resolution. That override represents a signature supplied during invocation, not permission to bypass the program's authority requirement.
|
|
69
|
+
|
|
70
|
+
After successful simulation, `client.execute(bytecode, manifest, resolution, { computeUnitLimit: "auto" })` simulates for compute budgeting and sends the transaction. `maxExecutionFee` in client configuration is the lamport fee ceiling accepted for each cook; its default is zero and fails when the Kitchen charges a positive fee. Lookup-table helpers can create or extend an address lookup table and wait until it is usable.
|
|
71
|
+
|
|
72
|
+
### Select the released programs and quote the fee
|
|
73
|
+
|
|
74
|
+
The pinned SVM engine **1.1.0** is `7MetdnWSaEsowvUmVyvwrbAeUW9xXFpVWXUXw4MxZ5CG`;
|
|
75
|
+
Kitchen **1.0.0** is `SauceYLdWyabKFwtevSAgsSDoMjCoTKtx1HTb63eJot`.
|
|
76
|
+
These are release addresses; confirm deployment on your cluster before use.
|
|
77
|
+
Engine 1.1.0 adds direct paid calls. The SDK clients use Kitchen-mediated cooks;
|
|
78
|
+
builders for the direct paid instructions are not yet exposed.
|
|
79
|
+
Use the deployment helpers and read the Kitchen's fee configuration on the selected
|
|
80
|
+
cluster. This example checks a caller-selected lamport budget before signing:
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
import { createHash } from "node:crypto";
|
|
84
|
+
import {
|
|
85
|
+
address,
|
|
86
|
+
assertAccountExists,
|
|
87
|
+
createSolanaRpc,
|
|
88
|
+
fetchEncodedAccount,
|
|
89
|
+
type TransactionSigner,
|
|
90
|
+
} from "@solana/kit";
|
|
91
|
+
import { v12SvmEngineProgramId, v12SvmKitchenProgramId } from "@eco-incorp/sauce/deployments";
|
|
92
|
+
import { createSauceSvmClient, deriveExecutionFeeConfigPda } from "@eco-incorp/sauce/svm";
|
|
93
|
+
|
|
94
|
+
export async function createReleasedClient(
|
|
95
|
+
rpcUrl: string,
|
|
96
|
+
payer: TransactionSigner,
|
|
97
|
+
feeBudgetLamports: bigint,
|
|
98
|
+
) {
|
|
99
|
+
const kitchen = address(v12SvmKitchenProgramId());
|
|
100
|
+
const { address: feeConfig } = await deriveExecutionFeeConfigPda(kitchen);
|
|
101
|
+
const account = await fetchEncodedAccount(createSolanaRpc(rpcUrl), feeConfig);
|
|
102
|
+
assertAccountExists(account);
|
|
103
|
+
const discriminator = createHash("sha256")
|
|
104
|
+
.update("account:ExecutionFeeConfig")
|
|
105
|
+
.digest()
|
|
106
|
+
.subarray(0, 8);
|
|
107
|
+
if (
|
|
108
|
+
account.programAddress !== kitchen ||
|
|
109
|
+
account.data.length !== 16 ||
|
|
110
|
+
!discriminator.every((value, index) => account.data[index] === value)
|
|
111
|
+
)
|
|
112
|
+
throw new Error("Unexpected Kitchen fee account");
|
|
113
|
+
const fee = new DataView(
|
|
114
|
+
account.data.buffer,
|
|
115
|
+
account.data.byteOffset,
|
|
116
|
+
account.data.byteLength,
|
|
117
|
+
).getBigUint64(8, true);
|
|
118
|
+
if (fee > feeBudgetLamports) throw new Error("Kitchen fee exceeds the approved budget");
|
|
119
|
+
return createSauceSvmClient({
|
|
120
|
+
rpcUrl,
|
|
121
|
+
payer,
|
|
122
|
+
kitchen,
|
|
123
|
+
programId: address(v12SvmEngineProgramId()),
|
|
124
|
+
maxExecutionFee: fee,
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
The payer needs SOL for this per-cook fee, transaction fees, and any rent or program
|
|
130
|
+
spending. The Kitchen charges its current fee up to the signed cap; a fee increase
|
|
131
|
+
above the quoted amount makes the cook fail. Requote before signing a retry.
|
|
132
|
+
|
|
133
|
+
`resolveAccounts` preserves manifest order. The reserved `payer` reference resolves to the fee payer. A manifest ending with `remaining` leaves the final account tail to the caller; do not insert accounts that shift that tail's indices.
|
|
134
|
+
|
|
135
|
+
## Stage a larger program
|
|
136
|
+
|
|
137
|
+
Staging belongs to the Kitchen. There is no `client.stageBuffer()` convenience method. Build and submit Kitchen instructions in this order:
|
|
138
|
+
|
|
139
|
+
1. Derive metadata and code addresses with `deriveCodeBufferPda(kitchen, owner, nonce)` and `deriveCodePda(kitchen, codeBuffer)`.
|
|
140
|
+
2. Allocate with `buildCreateCodeBufferInstruction`. Capacities above `GROWTH_STEP` require additional `buildGrowCodeBufferInstruction` calls.
|
|
141
|
+
3. Write the bytecode in appropriately sized chunks using `buildWriteCodeBufferInstruction`.
|
|
142
|
+
4. Finalize with `buildFinalizeCodeBufferInstruction`, supplying the byte length and its SHA-256 digest. Finalization verifies the digest and shrinks the code account to that length.
|
|
143
|
+
5. Execute with a Kitchen `buildCookFromAccountInstruction`, or the client's `simulateStaged`/`executeStaged` methods.
|
|
144
|
+
|
|
145
|
+
The low-level instruction builders return instructions; the application groups, signs, submits, and confirms them. The two Kitchen cook paths require `buildHeapFramePrepend()` when assembling transactions yourself. A staged client's first argument is the **code-buffer metadata address**; it derives the associated code account.
|
|
146
|
+
|
|
147
|
+
`buildCookFromAccountInstruction` supports a `pin` that the Kitchen checks at execution. The client's `expectedSha256` option is currently rejected; it is not a supported substitute for that low-level `pin`. A finalized buffer's digest and an execution-time caller-selected digest are different guarantees.
|
|
148
|
+
|
|
149
|
+
## SVM destinations in Eco intents
|
|
150
|
+
|
|
151
|
+
**The SDK's SVM route helpers are incompatible with the released gated engine.**
|
|
152
|
+
For an SVM destination, `Solana(body, { execution, ... }).reward(...)`,
|
|
153
|
+
`routes.compileSauceRoute()`, `buildSauceSvmCall()`, and `buildSauceSvmCalls()` emit
|
|
154
|
+
a legacy `execute_from_account` instruction containing only its 8-byte
|
|
155
|
+
discriminator. Engine 1.1.0 still requires another 65 bytes of Pot derivation material
|
|
156
|
+
and a trailing Pot signer supplied by the Kitchen.
|
|
157
|
+
|
|
158
|
+
The [SVM Portal fulfillment implementation](https://github.com/eco/eco-routes-svm/blob/5e544b72d368d9d1f0ee5269e2a1a5d2a9f8c2f2/programs/portal/src/instructions/fulfill.rs#L139-L192)
|
|
159
|
+
forwards the route's instruction bytes to its target unchanged. It signs for its
|
|
160
|
+
Executor PDA; it does not construct a Kitchen call or sign for a Sauce Pot.
|
|
161
|
+
Changing only the helper's engine program ID therefore does not make these routes
|
|
162
|
+
executable. Do not distribute them as executable intents against the pinned release.
|
|
163
|
+
|
|
164
|
+
A Kitchen-targeted Portal integration needs separately constructed cook data and
|
|
165
|
+
accounts, including the owner signature, Pot, fee configuration and payer, engine,
|
|
166
|
+
and staged metadata/code where applicable. The SDK does not currently build or
|
|
167
|
+
validate that complete integration. For standalone execution, use the client or
|
|
168
|
+
Kitchen instruction builders described above.
|
|
169
|
+
|
|
170
|
+
The legacy route's `execution.code` means the finalized **code account**, not its
|
|
171
|
+
metadata address. The helper neither stages nor checks that code against its newly
|
|
172
|
+
compiled bytes, and it drops the compiler account manifest. Keep the direct
|
|
173
|
+
compilation result when inspecting historical routes. EVM-source Portal helpers
|
|
174
|
+
can encode an SVM destination; they do not provide Solana-origin submission.
|
|
175
|
+
|
|
176
|
+
## Venue accessors
|
|
177
|
+
|
|
178
|
+
The `Solana` global includes the venues registered for runtime access. A venue accessor exposes a program ID, pool configuration loading, quote-source generation, swap CPI construction, and a TypeScript reference quote:
|
|
179
|
+
|
|
180
|
+
```ts
|
|
181
|
+
import { venue } from "@eco-incorp/sauce/svm";
|
|
182
|
+
import type { AccountLoader, SwapUser } from "@eco-incorp/sauce/svm";
|
|
183
|
+
import type { Address } from "@solana/kit";
|
|
184
|
+
|
|
185
|
+
export async function buildRaydiumSwap(
|
|
186
|
+
load: AccountLoader,
|
|
187
|
+
pool: Address,
|
|
188
|
+
user: SwapUser,
|
|
189
|
+
amount: bigint,
|
|
190
|
+
) {
|
|
191
|
+
const raydium = venue("raydium-cp-swap");
|
|
192
|
+
const config = await raydium.poolConfig(load, pool);
|
|
193
|
+
return raydium.swap(config, user, amount);
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
`Solana.RaydiumCpSwap` exposes the same accessor when globals are installed. `poolConfig` uses the account loader you supply; it does not create an RPC client or discover pools. `quoteSource` returns SauceScript source, and `.swap` returns CPI data plus account references, not a transaction.
|
|
198
|
+
|
|
199
|
+
Venue swap builders use a venue-level minimum output of one; the composed program must enforce the user's actual minimum with a post-swap output balance delta. Runtime accessors cover the registered venue set. Other adapters exported from `/svm` do not automatically appear as `Solana.<Venue>`; consult [coverage](../api/coverage.md).
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
# Verifying settlement programs
|
|
2
|
+
|
|
3
|
+
[Documentation](../README.md) · [Intents](intents.md) · [Compiler API](../api/compiler.md)
|
|
4
|
+
|
|
5
|
+
The SDK verifies its canonical settlement programs on EVM and SVM. These helpers
|
|
6
|
+
answer which settlement logic and parameters a payload contains. Applications
|
|
7
|
+
still check the destination, execution target, account identities, and remaining
|
|
8
|
+
intent calls against the operation they intend to authorize.
|
|
9
|
+
|
|
10
|
+
| Surface | Mechanism | Environment |
|
|
11
|
+
| ------------------------------ | -------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
|
|
12
|
+
| `@eco-incorp/sauce/verify` | Validate the EVM program hash and decode its canonical runtime argument tail | Node, browsers, and edge runtimes; depends on `viem`, not the compiler |
|
|
13
|
+
| `@eco-incorp/sauce/svm/verify` | Recompile SVM settlement with expected parameters, compare bytecode, and inspect attached accounts | Node; loads the compiler |
|
|
14
|
+
|
|
15
|
+
## Settlement behavior
|
|
16
|
+
|
|
17
|
+
The EVM recipe sweeps the Pot's entire current balance of every listed token to
|
|
18
|
+
one recipient. It checks `minOut` against the balance of `tokens[0]` before the
|
|
19
|
+
first transfer; `minOut: 0n` disables that floor. Existing or donated balances
|
|
20
|
+
count toward the floor and are swept as well. The floor is a balance check, not a
|
|
21
|
+
measurement of the amount produced by an earlier swap.
|
|
22
|
+
|
|
23
|
+
The SVM recipe applies the same pattern to escrow token accounts. It takes an
|
|
24
|
+
escrow count and compile-time `minOut`/`splCount`, then attaches token programs,
|
|
25
|
+
escrows, mints, destination token accounts, and the owner. `splCount` selects how
|
|
26
|
+
the escrows are split between the two token-program slots.
|
|
27
|
+
|
|
28
|
+
## EVM: validate a complete payload
|
|
29
|
+
|
|
30
|
+
For EVM, a payload is the reusable compiled program followed by ABI-v1 runtime
|
|
31
|
+
arguments. The compiler never sees the argument values.
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
import {
|
|
35
|
+
SETTLE_PROGRAM,
|
|
36
|
+
encodeSettleProgram,
|
|
37
|
+
validateSettleProgram,
|
|
38
|
+
} from "@eco-incorp/sauce/verify";
|
|
39
|
+
|
|
40
|
+
const payload = encodeSettleProgram(
|
|
41
|
+
["0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"], // Base USDC
|
|
42
|
+
1_000_000n,
|
|
43
|
+
"0x1111111111111111111111111111111111111111", // Example recipient
|
|
44
|
+
SETTLE_PROGRAM,
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
const settlement = validateSettleProgram(payload);
|
|
48
|
+
console.log(settlement.tokens, settlement.minOut, settlement.recipient);
|
|
49
|
+
console.log(settlement.floorToken, settlement.programHash);
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
`validateSettleProgram()` checks the full program hash and the argument encoding.
|
|
53
|
+
The current `SETTLE_WIRE` pin records compiler **2.3.0** and a **356-byte** program.
|
|
54
|
+
Payloads produced before that recompile are 362 bytes under a different hash; verify them by
|
|
55
|
+
passing their historical `{ hash, bytes: 362 }` pin to `validateSettleProgram`.
|
|
56
|
+
Import `SETTLE_WIRE` when code needs those values; avoid copying them into a
|
|
57
|
+
second constant table.
|
|
58
|
+
|
|
59
|
+
The tail contains three 32-byte head words—token-array offset, minimum output,
|
|
60
|
+
recipient—followed by the token count and token addresses in source order. The
|
|
61
|
+
verifier requires the canonical offset, a nonempty token list, a nonzero
|
|
62
|
+
recipient, clean address words, and no trailing data. Some alternate encodings
|
|
63
|
+
execute on an engine but are deliberately rejected here, so a successful decode
|
|
64
|
+
has a unique byte representation.
|
|
65
|
+
|
|
66
|
+
This surface verifies the pinned **ABI-v1** settlement artifact. Recompiling the
|
|
67
|
+
recipe with `compactArgs: true` changes that contract and is not accepted by the
|
|
68
|
+
existing settlement decoder.
|
|
69
|
+
|
|
70
|
+
### Inspection levels
|
|
71
|
+
|
|
72
|
+
| Helper | Result |
|
|
73
|
+
| --------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
|
|
74
|
+
| `validateSettleProgram(payload, accepted?)` | Hash-pinned program identity and strict argument decode; preferred for validation |
|
|
75
|
+
| `decodeSettleProgram(payload)` | Strict argument shape at the expected program length; does not authenticate program bytes |
|
|
76
|
+
| `parseSettleProgram(payload)` | A non-throwing structural report, including a `fatal` failure when present |
|
|
77
|
+
| `bestEffortDecode(parse)` | Best-effort inspection or `null` when reporting values would be misleading |
|
|
78
|
+
| `encodeSettleProgram(tokens, minOut, recipient, program)` | Canonical payload construction |
|
|
79
|
+
|
|
80
|
+
An arbitrary prefix of the expected length can pass structural decoding. Only a
|
|
81
|
+
hash-pinned validation establishes that it contains the recognized settlement
|
|
82
|
+
program. Validation failures use `SettleDecodeError.code`, including
|
|
83
|
+
`PROGRAM_HASH`, `TOKENS_OFFSET`, `DIRTY_ADDRESS_WORD`, and `ARGS_OVERLONG`.
|
|
84
|
+
|
|
85
|
+
### Extract a settlement from an intent
|
|
86
|
+
|
|
87
|
+
The intent helpers unwrap `cook` calldata and validate the program they find.
|
|
88
|
+
This reusable check expects exactly one current Pot settlement call:
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
import { extractEvmSettleFromIntent, type IntentLike } from "@eco-incorp/sauce/verify";
|
|
92
|
+
import type { Address } from "viem";
|
|
93
|
+
|
|
94
|
+
export function inspectSingleSettle(
|
|
95
|
+
intent: IntentLike,
|
|
96
|
+
trustedPot: Address,
|
|
97
|
+
trustedEngine: Address,
|
|
98
|
+
) {
|
|
99
|
+
const result = extractEvmSettleFromIntent(intent);
|
|
100
|
+
if (!result) throw new Error("No recognized settlement");
|
|
101
|
+
if (intent.route.calls.length !== 1 || result.callIndex !== 0) {
|
|
102
|
+
throw new Error("Expected exactly one settlement call");
|
|
103
|
+
}
|
|
104
|
+
if (result.ingredientCount !== 1) throw new Error("Unexpected extra program");
|
|
105
|
+
if (result.target?.toLowerCase() !== trustedPot.toLowerCase()) {
|
|
106
|
+
throw new Error("Unexpected Pot");
|
|
107
|
+
}
|
|
108
|
+
if (result.engine?.toLowerCase() !== trustedEngine.toLowerCase()) {
|
|
109
|
+
throw new Error("Unexpected engine");
|
|
110
|
+
}
|
|
111
|
+
return result; // Compare tokens, minOut, and recipient to application expectations.
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
For a swap-plus-settle intent, use the expected call count and positions for that
|
|
116
|
+
application and validate every other call. `extractEvmSettleFromIntent()` returns
|
|
117
|
+
the first recognized settlement; it does not approve the whole batch or check
|
|
118
|
+
the intent's destination chain.
|
|
119
|
+
|
|
120
|
+
`decodeSettleCall(data)` examines one cook, and
|
|
121
|
+
`extractEvmSettleFromCalls(calls)` operates without the intent wrapper. The
|
|
122
|
+
decoder also recognizes the historical `cook(bytes[])` wrapper: only its first
|
|
123
|
+
ingredient is inspected. A legacy router executes every ingredient, so check
|
|
124
|
+
`ingredientCount` and interpret an absent `engine` according to that contract.
|
|
125
|
+
Current `Pot.cook(address,bytes)` carries exactly one program and reports the
|
|
126
|
+
engine it names.
|
|
127
|
+
|
|
128
|
+
### Compiler upgrades and historical pins
|
|
129
|
+
|
|
130
|
+
`validateSettleProgram` accepts an explicit list of program hashes or
|
|
131
|
+
`{ hash, bytes }` `ProgramPin` records. Use the full record for a historical
|
|
132
|
+
program with a different length. Passing an empty list accepts no program; it
|
|
133
|
+
does not fall back to the default pin.
|
|
134
|
+
|
|
135
|
+
Compiler upgrades can change program bytes. When upgrading the SDK or compiler,
|
|
136
|
+
check which program versions your application produces and accepts. Import the
|
|
137
|
+
SDK's settlement pins rather than copying their values. Keep historical pins only
|
|
138
|
+
for program versions your application explicitly accepts.
|
|
139
|
+
|
|
140
|
+
The source is available through `settleSource()` from
|
|
141
|
+
`@eco-incorp/sauce/recipes`, and as the
|
|
142
|
+
`@eco-incorp/sauce/recipes/settle.sauce.ts` asset. `SAUCE_BASE_DIRS` locates its ABI
|
|
143
|
+
dependencies for a reproducing resolver. The verifier itself does not load that
|
|
144
|
+
source or recompile it.
|
|
145
|
+
|
|
146
|
+
## SVM: verify program and accounts
|
|
147
|
+
|
|
148
|
+
SVM settle parameters are compiled into the program, and account identities live
|
|
149
|
+
outside it. State the expected floor and token-program split, then verify both
|
|
150
|
+
parts.
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
import { compile } from "@eco-incorp/sauce/compiler";
|
|
154
|
+
import { svmSettleSource } from "@eco-incorp/sauce/svm";
|
|
155
|
+
import { verifySvmSettleProgram } from "@eco-incorp/sauce/svm/verify";
|
|
156
|
+
|
|
157
|
+
const expected = { minOut: 1_000_000n, splCount: 1n };
|
|
158
|
+
const source = new TextEncoder().encode(svmSettleSource(1));
|
|
159
|
+
const artifact = compile({
|
|
160
|
+
target: "svm",
|
|
161
|
+
resolve: (path) => (path === "main.js" ? source : undefined),
|
|
162
|
+
defines: [
|
|
163
|
+
["SETTLE_MIN_OUT", expected.minOut.toString()],
|
|
164
|
+
["SETTLE_SPL_COUNT", expected.splCount.toString()],
|
|
165
|
+
],
|
|
166
|
+
});
|
|
167
|
+
if (!artifact.manifest) throw new Error("Expected SVM accounts");
|
|
168
|
+
|
|
169
|
+
const result = verifySvmSettleProgram(artifact.bytecode, artifact.manifest, expected);
|
|
170
|
+
if (!result.genuine) throw new Error(result.mismatch);
|
|
171
|
+
console.log(result.escrowCount, result.refs);
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
This example demonstrates reproduction. To verify received data, pass the
|
|
175
|
+
received bytecode and manifest instead. The helper infers the escrow count from
|
|
176
|
+
the `3N + 3` account shape, checks canonical slot names, and recompiles the shipped
|
|
177
|
+
source with the expected values. Supported settle generators accept 1–16 escrows.
|
|
178
|
+
The result does not establish that the account addresses attached to an actual
|
|
179
|
+
instruction are the ones the application expects.
|
|
180
|
+
|
|
181
|
+
### Execution verification
|
|
182
|
+
|
|
183
|
+
`decodeSvmSettleExecution({ instructionData, accounts })` resolves accounts
|
|
184
|
+
positionally against the canonical settlement refs. The default `wireFormat: "gated-v1"` accepts raw **engine CPI instructions** produced by Kitchen 1.0.0 for
|
|
185
|
+
engine 1.1.0:
|
|
186
|
+
|
|
187
|
+
| Instruction | Data | Full CPI account list |
|
|
188
|
+
| ---------------------- | ------------------------------------------------------------------ | -------------------------------------- |
|
|
189
|
+
| `execute` | discriminator (8 bytes), owner (32), salt (32), bump (1), bytecode | settlement accounts, Pot |
|
|
190
|
+
| `execute_from_account` | discriminator (8 bytes), owner (32), salt (32), bump (1) | code account, settlement accounts, Pot |
|
|
191
|
+
|
|
192
|
+
The decoder removes the code account and trailing Pot before resolving the
|
|
193
|
+
`3N + 3` settlement slots. It returns parsed `gate` metadata and the staged
|
|
194
|
+
`codeAccount` when present. It rejects truncated headers, extra staged data,
|
|
195
|
+
invalid account addresses, and incompatible account counts. Labels are diagnostic;
|
|
196
|
+
account positions determine identities. Structural decoding alone cannot identify
|
|
197
|
+
settlement: unrelated programs can use the same account count.
|
|
198
|
+
|
|
199
|
+
Historical 8-byte headers require explicit `wireFormat: "legacy-ungated"`.
|
|
200
|
+
That inspection mode accepts the user account tail or its code-prefixed form;
|
|
201
|
+
it does not make legacy instructions executable on the released engine.
|
|
202
|
+
Kitchen `cook` and `cook_from_account` have different data and account layouts
|
|
203
|
+
and must not be passed directly to this decoder.
|
|
204
|
+
|
|
205
|
+
`verifySvmSettleExecution()` adds `minOut`, `splCount`, and optional `bytecode`
|
|
206
|
+
and `pin` inputs. Check both its `genuine` and `verifiedBy` fields:
|
|
207
|
+
|
|
208
|
+
| `verifiedBy` | What was compared |
|
|
209
|
+
| --------------------- | ----------------------------------------------------------------------------------------------------------------------- |
|
|
210
|
+
| `inline-bytecode` | The program inside an `execute` instruction matches the canonical program; supplied bytecode, if any, must match it too |
|
|
211
|
+
| `bytecode` | Supplied staged bytecode matches the canonical program and the supplied pin hashes those bytes |
|
|
212
|
+
| `caller-asserted-pin` | A caller-supplied pin equals the hash of the canonical program; no staged bytes were supplied |
|
|
213
|
+
| `none` | No basis to authenticate the staged program |
|
|
214
|
+
|
|
215
|
+
For staged execution, the pin comes from the **caller**, not from the released
|
|
216
|
+
engine's `execute_from_account` calldata. That instruction has no content-pin
|
|
217
|
+
field. A `bytecode` or `caller-asserted-pin` result therefore depends on the
|
|
218
|
+
caller's evidence connecting that pin to the code account that will execute,
|
|
219
|
+
such as the relevant Kitchen `cook_from_account` instruction and staged account
|
|
220
|
+
contents. The helper does not fetch that evidence. Supplying canonical bytes
|
|
221
|
+
without a pin cannot authenticate a staged execution.
|
|
222
|
+
|
|
223
|
+
Also check the engine program ID and the account identities, roles, mints,
|
|
224
|
+
owners, and destinations required by the application. Parsed gate metadata is
|
|
225
|
+
not proof of a valid Pot derivation or signature. The verifier does not validate
|
|
226
|
+
the Kitchen invocation, account roles, on-chain state, or execution success;
|
|
227
|
+
`genuine` describes the recognized program under the stated pin assumptions.
|
|
228
|
+
|
|
229
|
+
### Eco Portal envelopes
|
|
230
|
+
|
|
231
|
+
`decodePortalCalldataWithAccounts()` unwraps the SVM Portal's instruction data
|
|
232
|
+
and ordered account metas. It requires the declared account count to match the
|
|
233
|
+
full account list, canonical Borsh flags, and no trailing bytes. Envelope decoding
|
|
234
|
+
alone does not validate the target, program identity, or settlement.
|
|
235
|
+
`extractSvmSettleFromIntent()` and
|
|
236
|
+
`extractSvmSettleFromCalls()` combine envelope extraction with execution
|
|
237
|
+
verification and report the call target. They expect the raw engine format
|
|
238
|
+
above, default to `gated-v1`, and do **not** decode Kitchen cook envelopes. Supply
|
|
239
|
+
expected `minOut`, `splCount`, optional `wireFormat`, and optional `bytecode`
|
|
240
|
+
through their options. When verifying staged code, attach
|
|
241
|
+
the independently obtained `pin` to the relevant input call; pins are per call,
|
|
242
|
+
not shared across the batch.
|
|
243
|
+
|
|
244
|
+
A working Kitchen-targeted route needs separate Kitchen decoding before its
|
|
245
|
+
program and account plan can be checked. For an already executed transaction,
|
|
246
|
+
inspect the recorded inner engine instruction instead. The SDK's legacy SVM
|
|
247
|
+
route builder cannot produce that Kitchen integration; see the
|
|
248
|
+
[Solana guide](solana.md#svm-destinations-in-eco-intents).
|
|
249
|
+
|
|
250
|
+
As on EVM, finding a genuine settlement does not validate adjacent calls or an
|
|
251
|
+
arbitrary callee that accepts the same instruction discriminator. Match the
|
|
252
|
+
reported target and account plan to the deployment and intent your application
|
|
253
|
+
expects.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eco-incorp/sauce",
|
|
3
|
-
"version": "0.99.
|
|
3
|
+
"version": "0.99.3",
|
|
4
4
|
"description": "Sauce protocol tooling: SDK, action primitives, and a local dev environment.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
"url": "git+https://github.com/eco-incorp/sauce.git"
|
|
9
9
|
},
|
|
10
10
|
"homepage": "https://sauce.eco.com",
|
|
11
|
+
"license": "SEE LICENSE IN LICENSE.md",
|
|
11
12
|
"bugs": "https://github.com/eco-incorp/sauce/issues",
|
|
12
13
|
"publishConfig": {
|
|
13
14
|
"access": "public",
|
|
@@ -79,6 +80,7 @@
|
|
|
79
80
|
"sauce-dev-tools": "./dev-tools/scripts/init.js"
|
|
80
81
|
},
|
|
81
82
|
"files": [
|
|
83
|
+
"LICENSE.md",
|
|
82
84
|
"sdk/dist",
|
|
83
85
|
"actions/dist",
|
|
84
86
|
"sdk/src/skills",
|
|
@@ -88,7 +90,9 @@
|
|
|
88
90
|
"dev-tools/sauce",
|
|
89
91
|
"dev-tools/artifacts",
|
|
90
92
|
"dev-tools/hardhat.config.cjs",
|
|
91
|
-
"dev-tools/README.md"
|
|
93
|
+
"dev-tools/README.md",
|
|
94
|
+
"docs/**/*.md",
|
|
95
|
+
"docs/examples/*.ts"
|
|
92
96
|
],
|
|
93
97
|
"dependencies": {
|
|
94
98
|
"@solana-program/address-lookup-table": "^0.12.1",
|
|
@@ -98,7 +102,7 @@
|
|
|
98
102
|
"@solana/kit": "^6.10.0",
|
|
99
103
|
"acorn": "^8.15.0",
|
|
100
104
|
"dotenv": "^17.3.1",
|
|
101
|
-
"sauce-compiler": "npm:@eco-incorp/sauce-compiler
|
|
105
|
+
"sauce-compiler": "npm:@eco-incorp/sauce-compiler@2.3.0",
|
|
102
106
|
"typescript": "^5.7.0",
|
|
103
107
|
"viem": "^2.45.3"
|
|
104
108
|
},
|
|
@@ -112,9 +116,10 @@
|
|
|
112
116
|
"typescript-eslint": "8.70.0"
|
|
113
117
|
},
|
|
114
118
|
"engines": {
|
|
115
|
-
"node": ">=
|
|
119
|
+
"node": ">=24"
|
|
116
120
|
},
|
|
117
121
|
"scripts": {
|
|
122
|
+
"docs:check": "node docs/scripts/check-docs.mjs",
|
|
118
123
|
"build": "pnpm -r --filter './sdk' --filter './actions' build",
|
|
119
124
|
"typecheck": "pnpm -r typecheck",
|
|
120
125
|
"test": "pnpm -r test",
|
|
@@ -1,16 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": "1.0.0",
|
|
3
3
|
"commit": "f2f6dfbe38809304d83ca755eb7975c19d35ceab",
|
|
4
|
+
"releases": {
|
|
5
|
+
"v12-evm": {
|
|
6
|
+
"version": "1.0.1",
|
|
7
|
+
"commit": "9281c2eeb0e14557e6565a3a689ae31380740fa7"
|
|
8
|
+
},
|
|
9
|
+
"kitchen-evm": {
|
|
10
|
+
"version": "1.0.0",
|
|
11
|
+
"commit": "f2f6dfbe38809304d83ca755eb7975c19d35ceab"
|
|
12
|
+
},
|
|
13
|
+
"v12-svm": {
|
|
14
|
+
"version": "1.1.0",
|
|
15
|
+
"commit": "5c809b3d001583c0fad81f23271eadb5265cd747"
|
|
16
|
+
},
|
|
17
|
+
"kitchen-svm": {
|
|
18
|
+
"version": "1.0.0",
|
|
19
|
+
"commit": "f2f6dfbe38809304d83ca755eb7975c19d35ceab"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
4
22
|
"evm": {
|
|
5
23
|
"chainIndependent": true,
|
|
6
24
|
"factory": "0xba5Ed099633D3B313e4D5F7bdc1305d3c28ba5Ed",
|
|
7
25
|
"deployer": "0x6Ab56944462222A2405ffb87d01A29e37890abC3",
|
|
8
26
|
"contracts": {
|
|
9
27
|
"engine": {
|
|
10
|
-
"address": "
|
|
28
|
+
"address": "0x9745fdfaB1be84a0003f0472A842A0b91E5A323c",
|
|
11
29
|
"saltName": "Engine",
|
|
12
|
-
"rawSalt": "
|
|
13
|
-
"guardedSalt": "
|
|
30
|
+
"rawSalt": "0x6ab56944462222a2405ffb87d01a29e37890abc300456e67696e650000010001",
|
|
31
|
+
"guardedSalt": "0xbfaa08f51a17021008df6c83a6de420a69d30bb65908e3b1d31b5bcf7b0c20f4",
|
|
14
32
|
"derivation": "CREATE(CREATE2(factory, guardedSalt, keccak256(CreateX proxy initcode)), 1)"
|
|
15
33
|
},
|
|
16
34
|
"router": {
|
|
@@ -49,8 +67,8 @@
|
|
|
49
67
|
"clusterIndependent": true,
|
|
50
68
|
"programs": {
|
|
51
69
|
"engine": {
|
|
52
|
-
"programId": "
|
|
53
|
-
"label": "engine@1.
|
|
70
|
+
"programId": "7MetdnWSaEsowvUmVyvwrbAeUW9xXFpVWXUXw4MxZ5CG",
|
|
71
|
+
"label": "engine@1.1.0",
|
|
54
72
|
"derivation": "ed25519 keypair from sha256(SOLANA_PROGRAM_KEY_SEED, label)",
|
|
55
73
|
"upgradeAuthority": "none — deployed --final, so this program can never be upgraded or closed"
|
|
56
74
|
},
|