@xoxno/sdk-js 1.0.218 → 1.0.220

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.
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Pre-signing allowlist for the Soroban authorization tree of a PREPARED
3
+ * transaction.
4
+ *
5
+ * Simulation records every `require_auth` that code on the call stack makes
6
+ * for the caller — including one made by a rogue pool or token inside a swap
7
+ * hop, e.g. `any_token.transfer(caller, attacker, x)`. The wallet signature
8
+ * covers the whole tree, so whatever `prepareTransaction` returns is what the
9
+ * user authorizes. Each policy below is the set of sub-invocations the
10
+ * contracts legitimately request from the caller, with the source that proves
11
+ * it (paths are in the `rs-lending-xlm` repository):
12
+ *
13
+ * | Entrypoint | Caller sub-invocations | Source |
14
+ * |---|---|---|
15
+ * | controller `supply` | `asset.transfer(caller, pool, <= amount)` per asset | `contracts/controller/src/positions/supply.rs:118` |
16
+ * | controller `repay` | `asset.transfer(caller, pool, <= amount)` per asset | `contracts/controller/src/positions/debt.rs:144` |
17
+ * | controller `liquidate` | `asset.transfer(liquidator, pool, <= payment)` per asset | `contracts/controller/src/positions/liquidation/apply.rs:50` |
18
+ * | controller `multiply` | `asset.transfer(caller, controller, <= initial_payment)` when present | `contracts/controller/src/strategies/multiply.rs:169` |
19
+ * | controller `migrate_from_blend` | `blend_pool.submit(caller, controller, controller, [withdraw / withdraw_collateral / repay])`, at most twice | `contracts/controller/src/external/blend.rs:46-97` |
20
+ * | controller `borrow`, `withdraw`, `swap_debt`, `swap_collateral`, `repay_debt_with_collateral`, `flash_loan`, `flash_position`, any other | none | the controller funds these from its own custody (`strategies/legs.rs:50`, `strategies/flash_position.rs:285`) |
21
+ * | governance, any | none | proposer auth only |
22
+ * | router `execute_strategy` | `token_in.transfer(sender, router, <= total_in)` | `contracts/swap-aggregator/src/execute/mod.rs:81` |
23
+ */
24
+ import { xdr } from '@stellar/stellar-sdk';
25
+ import { type StellarNetwork } from './contracts.js';
26
+ export type StellarAuthPolicyErrorCode = 'MALFORMED_TRANSACTION' | 'INVOCATION_CHANGED' | 'UNSUPPORTED_CONTRACT' | 'CALLER_MISMATCH' | 'DUPLICATE_ENTRY' | 'UNEXPECTED_ROOT' | 'UNEXPECTED_CALL' | 'NESTED_INVOCATION' | 'UNEXPECTED_TOKEN' | 'UNEXPECTED_SENDER' | 'UNEXPECTED_RECIPIENT' | 'AMOUNT_EXCEEDED';
27
+ /** The invocation that broke the policy, in readable form. */
28
+ export interface StellarAuthOffender {
29
+ contract: string;
30
+ fn: string;
31
+ args: string[];
32
+ }
33
+ /** Thrown when the authorization tree holds anything the policy does not allow. */
34
+ export declare class StellarAuthPolicyError extends Error {
35
+ readonly code: StellarAuthPolicyErrorCode;
36
+ readonly offender?: StellarAuthOffender;
37
+ constructor(code: StellarAuthPolicyErrorCode, message: string, offender?: StellarAuthOffender);
38
+ }
39
+ /** Total the caller may send to `to` in `token` across all sub-invocations. */
40
+ export interface StellarAuthTransferAllowance {
41
+ token: string;
42
+ to: string;
43
+ maxAmount: bigint;
44
+ }
45
+ /** A non-transfer sub-invocation the caller legitimately authorizes. */
46
+ export interface StellarAuthCallAllowance {
47
+ contract: string;
48
+ fn: string;
49
+ maxCount: number;
50
+ /** Returns why `args` are not acceptable, or `undefined` when they are. */
51
+ reject: (args: xdr.ScVal[]) => string | undefined;
52
+ }
53
+ export interface StellarAuthPolicy {
54
+ caller: string;
55
+ root: {
56
+ contract: string;
57
+ fn: string;
58
+ };
59
+ transfers: StellarAuthTransferAllowance[];
60
+ calls?: StellarAuthCallAllowance[];
61
+ }
62
+ /**
63
+ * Enforce `policy` on the authorization entries of a prepared transaction.
64
+ * Entries that belong to other addresses are ignored. For the caller: at most
65
+ * one entry, the expected root, and only allowlisted leaf sub-invocations.
66
+ * @param sourceAccount - Account that source-account credentials stand for
67
+ * (the operation source, else the transaction source). When omitted, such
68
+ * entries are treated as the caller's.
69
+ * @throws StellarAuthPolicyError
70
+ */
71
+ export declare function assertStellarAuthEntries(entries: readonly xdr.SorobanAuthorizationEntry[], policy: StellarAuthPolicy, sourceAccount?: string): void;
72
+ /** Contract addresses a policy is derived against. */
73
+ export interface StellarAuthDeployment {
74
+ lendingController: string;
75
+ lendingPool: string;
76
+ aggregatorRouter: string;
77
+ governance: string;
78
+ }
79
+ /**
80
+ * Derive the policy for one contract invocation from its own arguments. The
81
+ * arguments are what the application built from the user's intent, so the
82
+ * allowed transfers are bounded by exactly what the user asked to pay.
83
+ * @throws StellarAuthPolicyError for a contract outside `deployment`.
84
+ */
85
+ export declare function stellarAuthPolicyForInvocation(caller: string, invocation: xdr.InvokeContractArgs, deployment: StellarAuthDeployment): StellarAuthPolicy;
86
+ export interface StellarPreparedTxAuthOptions {
87
+ network: StellarNetwork;
88
+ /** The wallet address that will sign. */
89
+ caller: string;
90
+ /**
91
+ * The unsigned builder output that was sent to `prepareTransaction`. When
92
+ * given, the prepared invocation must be byte-identical to it.
93
+ */
94
+ builtXdr?: string;
95
+ /** Replaces the derived policy (other contracts, custom flash receivers). */
96
+ policy?: StellarAuthPolicy;
97
+ /** Overrides manifest addresses for a non-standard deployment. */
98
+ deployment?: Partial<StellarAuthDeployment>;
99
+ }
100
+ /**
101
+ * Check a prepared transaction (base64 XDR, as `prepareTransaction` returns
102
+ * it) before it is passed to a wallet. Takes XDR strings so no live SDK object
103
+ * crosses the consumer's bundle boundary. Never sign when this throws.
104
+ * @throws StellarAuthPolicyError | StellarRouteVerificationError
105
+ */
106
+ export declare function assertStellarPreparedTxAuth(preparedXdr: string, opts: StellarPreparedTxAuthOptions): void;
@@ -20,6 +20,8 @@ export interface StellarDeployment {
20
20
  readonly aquariusApiUrl: string;
21
21
  readonly aquariusRouter: string;
22
22
  readonly lendingController: string;
23
+ /** The controller's single liquidity pool: the recipient of supply, repay and liquidation transfers. */
24
+ readonly lendingPool: string;
23
25
  readonly aggregatorRouter: string;
24
26
  readonly governance: string;
25
27
  readonly priceAggregator: string;
@@ -41,6 +43,7 @@ export declare const STELLAR_NETWORKS: {
41
43
  readonly aquariusApiUrl: "https://amm-api.aqua.network";
42
44
  readonly aquariusRouter: "CBQDHNBFBZYE4MKPWBSJOPIYLW4SFSXAXUTSXJN76GNKYVYPCKWC6QUK";
43
45
  readonly lendingController: "CAUCMIN5KSXEVZ7NMXR3LZATGD5EFIEUI5XWTFLYRO2R5OTXI22WE5JX";
46
+ readonly lendingPool: "CBXRNDQMAJFG4VUKMKFEMFS75UUXE2SPSNV4LEEFCSNBCN66PYRWBKXO";
44
47
  readonly aggregatorRouter: "CCVENFSVCBYDHVOACFZXMNNYVOZ3LKXPZYU5LUI4N7KTXOKRVYD7F3TR";
45
48
  readonly governance: "CC44PEQW7HSEPKAZ5ZRPH2JS5M5KVJXCUBLJ2ZX4E3WCDKMNFILHC2AD";
46
49
  readonly priceAggregator: "CBGUF2G2Q7HCVCWYISDXBHPVBGMYNXA7PG2VET66YBZX6IKOOV27NSMV";
@@ -56,6 +59,7 @@ export declare const STELLAR_NETWORKS: {
56
59
  readonly aquariusApiUrl: "https://amm-api-testnet.aqua.network";
57
60
  readonly aquariusRouter: "CBCFTQSPDBAIZ6R6PJQKSQWKNKWH2QIV3I4J72SHWBIK3ADRRAM5A6GD";
58
61
  readonly lendingController: "CCXRWJ6SIU2WPFEGLFGJVITPL57QAYIMIO6OAM2NBGNDQSSCK2FFV3F3";
62
+ readonly lendingPool: "CBSGF6QOQAMPFBEVSYPEQHSZRIHJ6RCGUPCRDMUX36DEKRWFAO2PZB5A";
59
63
  readonly aggregatorRouter: "CDNTWMWW2WGYTKIZTJYNGNVQQZI4KTC5BQRZ3275KESRX5T4O3AYECL5";
60
64
  readonly governance: "CDS33JDOYH3F3FL4QUQ6DV4WKHML2AKHF4LADTZ57FRUAEBTE7NMY5FQ";
61
65
  readonly priceAggregator: "CAALOOTIDXCX7D7FMQIBSSAJLPKOM3GMXS4UUSTDIG42JCRRJHOPUHOP";
@@ -74,6 +78,7 @@ export declare const stellarNetworks: {
74
78
  readonly aquariusApiUrl: "https://amm-api.aqua.network";
75
79
  readonly aquariusRouter: "CBQDHNBFBZYE4MKPWBSJOPIYLW4SFSXAXUTSXJN76GNKYVYPCKWC6QUK";
76
80
  readonly lendingController: "CAUCMIN5KSXEVZ7NMXR3LZATGD5EFIEUI5XWTFLYRO2R5OTXI22WE5JX";
81
+ readonly lendingPool: "CBXRNDQMAJFG4VUKMKFEMFS75UUXE2SPSNV4LEEFCSNBCN66PYRWBKXO";
77
82
  readonly aggregatorRouter: "CCVENFSVCBYDHVOACFZXMNNYVOZ3LKXPZYU5LUI4N7KTXOKRVYD7F3TR";
78
83
  readonly governance: "CC44PEQW7HSEPKAZ5ZRPH2JS5M5KVJXCUBLJ2ZX4E3WCDKMNFILHC2AD";
79
84
  readonly priceAggregator: "CBGUF2G2Q7HCVCWYISDXBHPVBGMYNXA7PG2VET66YBZX6IKOOV27NSMV";
@@ -89,6 +94,7 @@ export declare const stellarNetworks: {
89
94
  readonly aquariusApiUrl: "https://amm-api-testnet.aqua.network";
90
95
  readonly aquariusRouter: "CBCFTQSPDBAIZ6R6PJQKSQWKNKWH2QIV3I4J72SHWBIK3ADRRAM5A6GD";
91
96
  readonly lendingController: "CCXRWJ6SIU2WPFEGLFGJVITPL57QAYIMIO6OAM2NBGNDQSSCK2FFV3F3";
97
+ readonly lendingPool: "CBSGF6QOQAMPFBEVSYPEQHSZRIHJ6RCGUPCRDMUX36DEKRWFAO2PZB5A";
92
98
  readonly aggregatorRouter: "CDNTWMWW2WGYTKIZTJYNGNVQQZI4KTC5BQRZ3275KESRX5T4O3AYECL5";
93
99
  readonly governance: "CDS33JDOYH3F3FL4QUQ6DV4WKHML2AKHF4LADTZ57FRUAEBTE7NMY5FQ";
94
100
  readonly priceAggregator: "CAALOOTIDXCX7D7FMQIBSSAJLPKOM3GMXS4UUSTDIG42JCRRJHOPUHOP";
@@ -14,6 +14,8 @@ export * from './governance.js';
14
14
  export * from './events/index.js';
15
15
  export * from './quote.js';
16
16
  export * from './swap.js';
17
+ export * from './route-verify.js';
18
+ export * from './auth-policy.js';
17
19
  export * from './prepare.js';
18
20
  export * from './position-mode.js';
19
21
  export * from './repay-swap.js';
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Decoder and pre-signing verifier for the aggregator router's packed route
3
+ * (`routeXdr` / `swap_xdr`).
4
+ *
5
+ * The quote server is unauthenticated and returns the route as an opaque blob
6
+ * next to separate JSON display fields. The router enforces only the minimum
7
+ * that is ENCODED in the blob, so a caller must decode it and compare it with
8
+ * its own request before a wallet signs. The decoder mirrors
9
+ * `contracts/swap-aggregator/src/program.rs` (`Program::decode` + `validate`)
10
+ * and `execute::run` check for check; the encoder is `./scval-encode.ts`.
11
+ */
12
+ import { type StellarNetwork } from './contracts.js';
13
+ import { type StellarStrategySwapInput, type StellarSwapVenue } from './scval-encode.js';
14
+ /**
15
+ * Cap on the serialized payload, checked before XDR parsing so a hostile
16
+ * response cannot force a proportional allocation. The largest legal payload
17
+ * (256 addresses, 126 amounts, 346 program bytes) is below 16 KiB.
18
+ */
19
+ export declare const STELLAR_ROUTE_MAX_BYTES: number;
20
+ export type StellarRouteErrorCode = 'MALFORMED' | 'OVERSIZED' | 'UNSUPPORTED_VERSION' | 'UNKNOWN_OPCODE' | 'INVALID_STRUCTURE' | 'TOKEN_IN_MISMATCH' | 'TOKEN_OUT_MISMATCH' | 'MIN_OUT_TOO_LOW' | 'AMOUNT_IN_EXCEEDED' | 'EXPECTATION_MISSING';
21
+ /** Thrown when a route cannot be decoded or disagrees with the caller's request. */
22
+ export declare class StellarRouteVerificationError extends Error {
23
+ readonly code: StellarRouteErrorCode;
24
+ constructor(code: StellarRouteErrorCode, message: string);
25
+ }
26
+ export type DecodedStellarRouteMode = {
27
+ kind: 'all';
28
+ } | {
29
+ kind: 'prev';
30
+ } | {
31
+ kind: 'fixed';
32
+ amount: bigint;
33
+ } | {
34
+ kind: 'ppm';
35
+ ppm: number;
36
+ };
37
+ export type DecodedStellarRouteOp = {
38
+ kind: 'swap';
39
+ venue: StellarSwapVenue;
40
+ mode: DecodedStellarRouteMode;
41
+ pool: string;
42
+ tokenIn: string;
43
+ tokenOut: string;
44
+ } | {
45
+ kind: 'burn' | 'mint';
46
+ pool: string;
47
+ shareToken: string;
48
+ /** Burn: first index of the per-constituent floor run. Mint: index of the minimum shares. */
49
+ amountIndex: number;
50
+ };
51
+ export interface DecodedStellarRoute {
52
+ version: number;
53
+ tokenIn: string;
54
+ tokenOut: string;
55
+ /** The minimum output the router enforces on chain (`amounts[min_out]`). */
56
+ totalMinOut: bigint;
57
+ referralId: number;
58
+ assets: string[];
59
+ amounts: bigint[];
60
+ ops: DecodedStellarRouteOp[];
61
+ /** Split weights in parts per million. */
62
+ weights: number[];
63
+ }
64
+ /**
65
+ * Any form the builders accept: base64 `routeXdr`, `0x` hex, raw bytes,
66
+ * `{ routeXdr }` / `{ swapXdr }` / `{ bytes }`, or a decoded payload object
67
+ * (encoded locally first, so the check covers exactly what would be signed).
68
+ */
69
+ export type StellarRouteBytesInput = StellarStrategySwapInput;
70
+ /**
71
+ * Decode and structurally validate route bytes. Applies every check of the
72
+ * on-chain decoder, so a route that `Program::decode` rejects does not decode
73
+ * here. Venue behaviour (pools, liquidity, budget) is not checked.
74
+ * @throws StellarRouteVerificationError
75
+ */
76
+ export declare function decodeStellarRouteBytes(route: StellarRouteBytesInput): DecodedStellarRoute;
77
+ /**
78
+ * Contract id of a quote-server token id: `C…` as is, `XLM` / `native` and
79
+ * `CODE:GISSUER` through the Stellar Asset Contract id of `network`.
80
+ * @throws StellarRouteVerificationError when the id needs a network and none is given.
81
+ */
82
+ export declare function stellarTokenContractId(tokenId: string, network?: StellarNetwork): string;
83
+ /** What the CALLER asked for. Take these from request state, not from the response. */
84
+ export interface StellarRouteExpectation {
85
+ /** Input token contract id (`C…`). */
86
+ tokenIn: string;
87
+ /** Output token contract id (`C…`). */
88
+ tokenOut: string;
89
+ /** Lowest acceptable encoded `total_min_out`, base units. This is the value shown to the user. */
90
+ minOut: string | bigint;
91
+ /** Input amount, base units. When given, no fixed-size leg may spend more of `tokenIn`. */
92
+ amountIn?: string | bigint;
93
+ }
94
+ /**
95
+ * Decode `route` and require it to match `expected`. Call before signing any
96
+ * transaction that carries route bytes; never sign when this throws.
97
+ * @returns The decoded route, for display or further checks.
98
+ * @throws StellarRouteVerificationError
99
+ */
100
+ export declare function verifyStellarRouteBytes(route: StellarRouteBytesInput, expected: StellarRouteExpectation): DecodedStellarRoute;
@@ -21,6 +21,16 @@ export declare const STELLAR_SWAP_VENUE_OPCODE: Record<StellarSwapVenue, number>
21
21
  export declare const STELLAR_PROGRAM_VERSION = 1;
22
22
  /** Split weights are parts per million. */
23
23
  export declare const PPM_DENOMINATOR = 1000000;
24
+ export declare const OP_BURN = 5;
25
+ export declare const OP_MINT = 6;
26
+ export declare const MODE_ALL = 0;
27
+ export declare const MODE_PREV = 1;
28
+ export declare const MODE_FIXED_BASE = 2;
29
+ export declare const MODE_PPM_BASE = 128;
30
+ export declare const MAX_OPS = 48;
31
+ export declare const MAX_WEIGHTS = 32;
32
+ export declare const MAX_ASSETS = 256;
33
+ export declare const MAX_AMOUNTS: number;
24
34
  export interface StellarStrategySwapHopInput {
25
35
  /** Quote-side estimate; not carried on the wire. */
26
36
  amountOut?: string;
@@ -11,8 +11,27 @@
11
11
  * opaque route bytes to the controller, which forwards them to the aggregator.
12
12
  */
13
13
  import type { StellarAggregatorQuoteResponseDto } from '@xoxno/types';
14
+ import { type StellarNetwork } from './contracts.js';
14
15
  import type { BuiltStellarTx, StellarBuilderOptions } from './lending.js';
15
16
  import { type StellarStrategyPayloadInput, type StellarStrategySwapHopInput, type StellarStrategySwapInput, type StellarStrategySwapPathInput } from './scval-encode.js';
17
+ /**
18
+ * The caller's own request, used to check a quote before it is signed. Every
19
+ * field that is absent falls back to the quote's JSON, which proves only that
20
+ * the response agrees with itself — pass request state whenever it is known.
21
+ */
22
+ export interface StellarQuoteExpectation {
23
+ tokenIn?: string;
24
+ tokenOut?: string;
25
+ /** Lowest acceptable minimum output, base units. */
26
+ minOut?: string | bigint;
27
+ amountIn?: string | bigint;
28
+ }
29
+ export interface StellarQuoteMapOptions {
30
+ referralId?: number | string;
31
+ /** Needed only when a token id is `XLM` or `CODE:GISSUER` instead of `C…`. */
32
+ network?: StellarNetwork;
33
+ expected?: StellarQuoteExpectation;
34
+ }
16
35
  export type StellarStrategyPayload = StellarStrategyPayloadInput;
17
36
  export type StellarStrategySwap = StellarStrategySwapInput;
18
37
  export type StellarStrategySwapHop = StellarStrategySwapHopInput;
@@ -55,15 +74,16 @@ export declare function buildStellarBatchSwapTx(opts: StellarBatchSwapBuilderOpt
55
74
  * Translate a quote-server response into the decoded `StrategyPayload` shape.
56
75
  * Prefer `mapQuoteResponseToStrategySwap` when the quote includes `routeXdr`.
57
76
  */
58
- export declare function mapQuoteResponseToStrategyPayload(quote: StellarAggregatorQuoteResponseDto, opts?: {
59
- referralId?: number | string;
60
- }): StellarStrategyPayloadInput;
77
+ export declare function mapQuoteResponseToStrategyPayload(quote: StellarAggregatorQuoteResponseDto, opts?: Pick<StellarQuoteMapOptions, 'referralId'>): StellarStrategyPayloadInput;
61
78
  /**
62
79
  * Return the executable quote route when the API provided it; otherwise build
63
80
  * the decoded fallback payload from hop/path fields.
81
+ *
82
+ * Either form is decoded and checked before it is returned: it must spend and
83
+ * deliver the expected pair and enforce a minimum that is not below the
84
+ * quote's `amountOutMin` (what a UI displays) nor below `expected.minOut`.
85
+ * @throws StellarRouteVerificationError — never sign a quote that throws here.
64
86
  */
65
- export declare function mapQuoteResponseToStrategySwap(quote: StellarAggregatorQuoteResponseDto, opts?: {
66
- referralId?: number | string;
67
- }): StellarStrategySwapInput;
87
+ export declare function mapQuoteResponseToStrategySwap(quote: StellarAggregatorQuoteResponseDto, opts?: StellarQuoteMapOptions): StellarStrategySwapInput;
68
88
  /** @deprecated Use `mapQuoteResponseToStrategyPayload`. */
69
89
  export declare const mapQuoteResponseToAggregatorSwap: typeof mapQuoteResponseToStrategyPayload;