@gibs/bridge-sdk 1.17.0 → 1.19.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 (56) hide show
  1. package/README.md +85 -1
  2. package/dist/cjs/config.d.ts +18 -3
  3. package/dist/cjs/config.js +49 -17
  4. package/dist/cjs/consolidated-quote.js +3 -0
  5. package/dist/cjs/execution.d.ts +17 -4
  6. package/dist/cjs/execution.js +40 -13
  7. package/dist/cjs/index.d.ts +1 -0
  8. package/dist/cjs/index.js +1 -0
  9. package/dist/cjs/near-intents-route.d.ts +13 -0
  10. package/dist/cjs/near-intents-route.js +19 -3
  11. package/dist/cjs/prices.d.ts +10 -0
  12. package/dist/cjs/prices.js +54 -2
  13. package/dist/cjs/routing/candidate-route.d.ts +46 -1
  14. package/dist/cjs/routing/candidate-route.js +47 -2
  15. package/dist/cjs/routing/carrier-provider-key.d.ts +31 -0
  16. package/dist/cjs/routing/carrier-provider-key.js +42 -0
  17. package/dist/cjs/routing/carriers/pulsex.d.ts +50 -25
  18. package/dist/cjs/routing/carriers/pulsex.js +135 -85
  19. package/dist/cjs/routing/index.d.ts +7 -3
  20. package/dist/cjs/routing/index.js +11 -2
  21. package/dist/cjs/routing/route-data.d.ts +47 -5
  22. package/dist/cjs/routing/search/plan-route-data.d.ts +17 -1
  23. package/dist/cjs/routing/search/plan-route-data.js +39 -13
  24. package/dist/cjs/routing/swap-transactions.d.ts +7 -3
  25. package/dist/cjs/routing/swap-transactions.js +6 -4
  26. package/dist/cjs/swap-venues.d.ts +43 -0
  27. package/dist/cjs/swap-venues.js +29 -0
  28. package/dist/cjs/types.d.ts +8 -0
  29. package/dist/config.d.ts +18 -3
  30. package/dist/config.js +48 -16
  31. package/dist/consolidated-quote.js +3 -0
  32. package/dist/execution.d.ts +17 -4
  33. package/dist/execution.js +41 -14
  34. package/dist/index.d.ts +1 -0
  35. package/dist/index.js +1 -0
  36. package/dist/near-intents-route.d.ts +13 -0
  37. package/dist/near-intents-route.js +17 -2
  38. package/dist/prices.d.ts +10 -0
  39. package/dist/prices.js +52 -1
  40. package/dist/routing/candidate-route.d.ts +46 -1
  41. package/dist/routing/candidate-route.js +45 -1
  42. package/dist/routing/carrier-provider-key.d.ts +31 -0
  43. package/dist/routing/carrier-provider-key.js +37 -0
  44. package/dist/routing/carriers/pulsex.d.ts +50 -25
  45. package/dist/routing/carriers/pulsex.js +133 -84
  46. package/dist/routing/index.d.ts +7 -3
  47. package/dist/routing/index.js +4 -2
  48. package/dist/routing/route-data.d.ts +47 -5
  49. package/dist/routing/search/plan-route-data.d.ts +17 -1
  50. package/dist/routing/search/plan-route-data.js +40 -14
  51. package/dist/routing/swap-transactions.d.ts +7 -3
  52. package/dist/routing/swap-transactions.js +7 -5
  53. package/dist/swap-venues.d.ts +43 -0
  54. package/dist/swap-venues.js +24 -0
  55. package/dist/types.d.ts +8 -0
  56. package/package.json +3 -3
@@ -1,3 +1,4 @@
1
+ import { type CandidateExecutionInputs } from '../execution.js';
1
2
  import type { RouteCandidate } from './candidate.js';
2
3
  import type { RouteData } from './route-data.js';
3
4
  /**
@@ -37,7 +38,51 @@ export declare const buildRouteDataForCandidate: (candidate: RouteCandidate) =>
37
38
  * site, so a surface that warns about a long journey and a surface that ranks
38
39
  * routes cannot come to different counts.
39
40
  *
41
+ * THIS COUNT LEAVES OUT APPROVALS. A token that is not the chain's native coin
42
+ * needs an `approve` transaction before its first section when the allowance
43
+ * is too small, and that approval is a signature too. Raw route data does not
44
+ * say who the spender is or what the account has approved already, so this
45
+ * function cannot count it. Use {@link routeSignatureCountForAccount} for the
46
+ * number the wallet will really ask for.
47
+ *
40
48
  * @param route - the raw route data
41
- * @returns the number of signatures, one per section
49
+ * @returns the number of signatures, one per section, with no approvals
42
50
  */
43
51
  export declare const routeSignatureCount: (route: RouteData) => number;
52
+ /** What {@link routeSignatureCountForAccount} reports. */
53
+ export type RouteSignatureCount = {
54
+ /** Signatures for the sections themselves: one per planned section. */
55
+ readonly signatures: number;
56
+ /** Approval transactions the account must sign first, given what it has approved already. */
57
+ readonly approvals: number;
58
+ /** `signatures + approvals`: every wallet prompt the planned sections cause. */
59
+ readonly total: number;
60
+ };
61
+ /**
62
+ * How many wallet signatures a route asks one account for, approvals included.
63
+ *
64
+ * {@link routeSignatureCount} counts sections only, so a USDC route reads "1"
65
+ * and then asks for two prompts: approve, then send. This function plans the
66
+ * sections with {@link planCandidateExecution} and counts what that plan
67
+ * contains, so it uses the same allowance rule and the same spender the
68
+ * execution planner uses. A native input needs no approval. An allowance that
69
+ * already covers the amount needs none. A smaller, non-zero allowance counts
70
+ * the reset and the new approval, the two transactions the planner emits. The
71
+ * spender is whatever the planner picks: the omnibridge mediator, a swap
72
+ * venue's router (including routers passed in `swapVenues`), or the
73
+ * aggregator's approval address.
74
+ *
75
+ * Pass every section of the route to count the whole route. Pass fewer to
76
+ * count only the window you plan now; each section is counted against the
77
+ * allowance on chain today, so a later section that spends a token an earlier
78
+ * section delivers is counted as if the approval is still needed.
79
+ *
80
+ * An aggregator section needs its `aggregator` inputs, a quote and the request
81
+ * it answered, exactly as {@link planCandidateExecution} does. Without them
82
+ * this function throws, because the approval spender comes from that quote.
83
+ *
84
+ * @param inputs - the same inputs {@link planCandidateExecution} takes
85
+ * @returns the signatures, approvals, and their total
86
+ * @throws when a section cannot be planned; the message names the section and the reason
87
+ */
88
+ export declare const routeSignatureCountForAccount: (inputs: CandidateExecutionInputs) => Promise<RouteSignatureCount>;
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.routeSignatureCount = exports.buildRouteDataForCandidate = void 0;
3
+ exports.routeSignatureCountForAccount = exports.routeSignatureCount = exports.buildRouteDataForCandidate = void 0;
4
4
  const near_intents_route_js_1 = require("../near-intents-route.js");
5
+ const execution_js_1 = require("../execution.js");
5
6
  const producers_js_1 = require("./producers.js");
6
7
  /**
7
8
  * One door in front of the two base route builders.
@@ -43,8 +44,52 @@ exports.buildRouteDataForCandidate = buildRouteDataForCandidate;
43
44
  * site, so a surface that warns about a long journey and a surface that ranks
44
45
  * routes cannot come to different counts.
45
46
  *
47
+ * THIS COUNT LEAVES OUT APPROVALS. A token that is not the chain's native coin
48
+ * needs an `approve` transaction before its first section when the allowance
49
+ * is too small, and that approval is a signature too. Raw route data does not
50
+ * say who the spender is or what the account has approved already, so this
51
+ * function cannot count it. Use {@link routeSignatureCountForAccount} for the
52
+ * number the wallet will really ask for.
53
+ *
46
54
  * @param route - the raw route data
47
- * @returns the number of signatures, one per section
55
+ * @returns the number of signatures, one per section, with no approvals
48
56
  */
49
57
  const routeSignatureCount = (route) => route.sections.length;
50
58
  exports.routeSignatureCount = routeSignatureCount;
59
+ /**
60
+ * How many wallet signatures a route asks one account for, approvals included.
61
+ *
62
+ * {@link routeSignatureCount} counts sections only, so a USDC route reads "1"
63
+ * and then asks for two prompts: approve, then send. This function plans the
64
+ * sections with {@link planCandidateExecution} and counts what that plan
65
+ * contains, so it uses the same allowance rule and the same spender the
66
+ * execution planner uses. A native input needs no approval. An allowance that
67
+ * already covers the amount needs none. A smaller, non-zero allowance counts
68
+ * the reset and the new approval, the two transactions the planner emits. The
69
+ * spender is whatever the planner picks: the omnibridge mediator, a swap
70
+ * venue's router (including routers passed in `swapVenues`), or the
71
+ * aggregator's approval address.
72
+ *
73
+ * Pass every section of the route to count the whole route. Pass fewer to
74
+ * count only the window you plan now; each section is counted against the
75
+ * allowance on chain today, so a later section that spends a token an earlier
76
+ * section delivers is counted as if the approval is still needed.
77
+ *
78
+ * An aggregator section needs its `aggregator` inputs, a quote and the request
79
+ * it answered, exactly as {@link planCandidateExecution} does. Without them
80
+ * this function throws, because the approval spender comes from that quote.
81
+ *
82
+ * @param inputs - the same inputs {@link planCandidateExecution} takes
83
+ * @returns the signatures, approvals, and their total
84
+ * @throws when a section cannot be planned; the message names the section and the reason
85
+ */
86
+ const routeSignatureCountForAccount = async (inputs) => {
87
+ const plan = await (0, execution_js_1.planCandidateExecution)(inputs);
88
+ if (plan.kind === 'refused') {
89
+ throw new Error(`Cannot count signatures: section ${plan.sectionIndex} cannot be planned (${JSON.stringify(plan.refusal)}).`);
90
+ }
91
+ const approvals = plan.transactions.filter((transaction) => transaction.kind === 'approve').length;
92
+ const signatures = plan.transactions.length - approvals;
93
+ return { signatures, approvals, total: plan.transactions.length };
94
+ };
95
+ exports.routeSignatureCountForAccount = routeSignatureCountForAccount;
@@ -0,0 +1,31 @@
1
+ import { type ProviderKey } from '../providers.js';
2
+ /**
3
+ * The carrier id of the native-coin wrap and unwrap step
4
+ * (`routing/carriers/wrap.ts`).
5
+ */
6
+ export declare const WRAP_CARRIER_ID = "wrap";
7
+ /**
8
+ * The steps a route can take that no third-party provider performs. A step of
9
+ * this kind is drawn from its own mark, never from a provider's.
10
+ */
11
+ export type CarrierStepKind = 'wrap';
12
+ /**
13
+ * The one place an engine carrier id becomes a {@link ProviderKey}.
14
+ *
15
+ * AN ENGINE CARRIER ID IS NOT A PROVIDER KEY. The engine is a plug-in host: a
16
+ * carrier id is any string, and one of them, `'wrap'`, names a step that no
17
+ * provider performs. Handing a raw id to the logo, glyph, or name tables drew a
18
+ * blank mark and logged an error. Route data resolves the key here, once, and
19
+ * every display site reads the resolved key.
20
+ *
21
+ * @param carrierId - the `carrier` of a planned hop's edge
22
+ * @returns the provider key, or null when no registered provider carries that id
23
+ */
24
+ export declare const carrierProviderKey: (carrierId: string) => ProviderKey | null;
25
+ /**
26
+ * The kind of provider-less step a carrier id performs.
27
+ *
28
+ * @param carrierId - the `carrier` of a planned hop's edge
29
+ * @returns the step kind, or null when the carrier is a provider or unknown
30
+ */
31
+ export declare const carrierStepKind: (carrierId: string) => CarrierStepKind | null;
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.carrierStepKind = exports.carrierProviderKey = exports.WRAP_CARRIER_ID = void 0;
4
+ const config_js_1 = require("../config.js");
5
+ const providers_js_1 = require("../providers.js");
6
+ /**
7
+ * The carrier id of the native-coin wrap and unwrap step
8
+ * (`routing/carriers/wrap.ts`).
9
+ */
10
+ exports.WRAP_CARRIER_ID = 'wrap';
11
+ /**
12
+ * Every engine carrier id that IS a provider, mapped to its {@link ProviderKey}.
13
+ * The omnibridge crossings carry the provider value itself; the aggregators
14
+ * carry their registry id; the PulseChain exchange carries its own literal.
15
+ */
16
+ const providerKeyByCarrierId = new Map([
17
+ ...Object.values(config_js_1.Providers).map((provider) => [provider, provider]),
18
+ ...providers_js_1.providerRegistry.map((descriptor) => [descriptor.id, descriptor.id]),
19
+ ['PulseX', 'PulseX'],
20
+ ]);
21
+ /**
22
+ * The one place an engine carrier id becomes a {@link ProviderKey}.
23
+ *
24
+ * AN ENGINE CARRIER ID IS NOT A PROVIDER KEY. The engine is a plug-in host: a
25
+ * carrier id is any string, and one of them, `'wrap'`, names a step that no
26
+ * provider performs. Handing a raw id to the logo, glyph, or name tables drew a
27
+ * blank mark and logged an error. Route data resolves the key here, once, and
28
+ * every display site reads the resolved key.
29
+ *
30
+ * @param carrierId - the `carrier` of a planned hop's edge
31
+ * @returns the provider key, or null when no registered provider carries that id
32
+ */
33
+ const carrierProviderKey = (carrierId) => providerKeyByCarrierId.get(carrierId) ?? null;
34
+ exports.carrierProviderKey = carrierProviderKey;
35
+ /**
36
+ * The kind of provider-less step a carrier id performs.
37
+ *
38
+ * @param carrierId - the `carrier` of a planned hop's edge
39
+ * @returns the step kind, or null when the carrier is a provider or unknown
40
+ */
41
+ const carrierStepKind = (carrierId) => carrierId === exports.WRAP_CARRIER_ID ? 'wrap' : null;
42
+ exports.carrierStepKind = carrierStepKind;
@@ -1,34 +1,50 @@
1
1
  import { type Hex } from 'viem';
2
2
  import type { PublicClient } from 'viem';
3
+ import { type SwapVenue, type SwapVenues } from '../../swap-venues.js';
3
4
  import { type AssetNode, type HopEdge, type PlannedHop } from '../search/graph.js';
4
5
  import type { CarrierAskAnswer, CarrierExactResult } from './ask-answer.js';
5
6
  /**
6
- * One PulseX deployment a swap can execute on: the router the reader signs
7
- * and the factory whose pools that router trades against. A Uniswap-V2-style
7
+ * One swap deployment a swap can execute on: the router the reader signs and
8
+ * the factory whose pools that router trades against. A Uniswap-V2-style
8
9
  * router resolves every pool through its OWN factory, so one router call can
9
10
  * only ever touch that one deployment's pools — a path can never mix them.
11
+ *
12
+ * Same type as {@link SwapVenue}; the old name stays for existing callers.
10
13
  */
11
- export type PulseXVenue = {
12
- readonly router: Hex;
13
- readonly factory: Hex;
14
- };
14
+ export type PulseXVenue = SwapVenue;
15
15
  /**
16
- * Every PulseX deployment on PulseChain, V1 first: `uniV2Routers` paired with
17
- * `uniV2Factories` by index. Each factory is the router's own
18
- * `router.factory()` read on chain — see `uniV2Factories`'s own doc in
19
- * `config.ts`. A router with no recorded factory is left out, because its
20
- * pools cannot be read.
16
+ * Every PulseX deployment on PulseChain, V1 first: the PulseChain entry of
17
+ * {@link defaultSwapVenues}. Frozen. It lists the DEFAULTS only — a carrier
18
+ * built with its own `venues` offers those instead.
21
19
  */
22
20
  export declare const pulseXVenues: readonly PulseXVenue[];
23
21
  /**
24
- * The router a PulseX edge must be signed on — the one its figure was quoted
25
- * against. Reads the edge's own {@link HopEdge.venue}; an edge with none is a
26
- * V1 edge (see {@link defaultPulseXVenue}).
22
+ * The {@link SwapVenue} a swap edge runs on: the one its figure was quoted
23
+ * against. Reads the edge's own {@link HopEdge.venue}; an edge with none runs
24
+ * on the FIRST venue of its chain (V1 for PulseX) — every swap edge built
25
+ * before venues existed was quoted and signed there, and the same-chain swap
26
+ * sender's own hand-built edge still is.
27
+ *
28
+ * NEVER FALLS BACK TO ANOTHER CHAIN OR ANOTHER ROUTER. An edge that names a
29
+ * router `venues` does not list gets null, so the caller can refuse it.
30
+ *
31
+ * @param venues - the venues the caller allows
32
+ * @param edge - the edge to sign; `from` names the chain, and defaults to PulseChain when absent
33
+ * @returns the venue, or null when the edge is not a swap edge or names a router that is not in `venues`
34
+ */
35
+ export declare const venueForEdge: (venues: SwapVenues, edge: Pick<HopEdge, "carrier" | "venue"> & {
36
+ readonly from?: Pick<AssetNode, "chainId">;
37
+ }) => SwapVenue | null;
38
+ /**
39
+ * The router a PulseX edge must be signed on, judged against the DEFAULT
40
+ * venues only. Prefer {@link venueForEdge} with the venues your host passes.
27
41
  *
28
42
  * @param edge - the edge to sign
29
- * @returns the router, or null when the edge is not a PulseX edge or names a venue that is not a known PulseX router
43
+ * @returns the router, or null when the edge is not a swap edge or names a router that is not a default
30
44
  */
31
- export declare const pulseXRouterForEdge: (edge: Pick<HopEdge, "carrier" | "venue">) => Hex | null;
45
+ export declare const pulseXRouterForEdge: (edge: Pick<HopEdge, "carrier" | "venue"> & {
46
+ readonly from?: Pick<AssetNode, "chainId">;
47
+ }) => Hex | null;
32
48
  /**
33
49
  * The fixed Wrapped-PLS path from `from` to `to` — `[from, WPLS, to]`, or
34
50
  * `[from, to]` when one side is WPLS — or null when both ends resolve to the
@@ -78,9 +94,10 @@ export type PulseXPathStep = {
78
94
  *
79
95
  * @param amountIn - the amount entering the first pool
80
96
  * @param steps - the pools in order of travel
97
+ * @param feeBasisPoints - the venue's swap fee in basis points; PulseX's 29 when omitted
81
98
  * @returns the amount leaving the last pool; 0 when any pool cannot pay out
82
99
  */
83
- export declare const amountOutAlongPath: (amountIn: bigint, steps: readonly PulseXPathStep[]) => bigint;
100
+ export declare const amountOutAlongPath: (amountIn: bigint, steps: readonly PulseXPathStep[], feeBasisPoints?: number) => bigint;
84
101
  /**
85
102
  * How far a trade's executed rate falls below the marginal (near-spot) rate,
86
103
  * in percent. The marginal rate is a tiny reference trade through the same
@@ -110,12 +127,12 @@ export type CreatePulseXCarrierOptions = {
110
127
  * in the edge's `to` token's base units. Returns null when the path has no
111
128
  * liquidity.
112
129
  *
113
- * MUST READ THE EDGE'S OWN ROUTER ({@link pulseXRouterForEdge}). A V2 edge
130
+ * MUST READ THE EDGE'S OWN ROUTER ({@link venueForEdge}). A V2 edge
114
131
  * answered from V1 would carry V1's figure into a V2 signature.
115
132
  */
116
133
  readonly readAmountOut: (edge: HopEdge, inputAmount: bigint) => Promise<bigint | null>;
117
134
  /**
118
- * Returns a PulseChain client, for {@link Carrier.prepare}'s own batched
135
+ * Returns a client for a chain, for {@link Carrier.prepare}'s own batched
119
136
  * reserve reads — never called by `ask`, which keeps using
120
137
  * {@link readAmountOut} unchanged.
121
138
  *
@@ -123,17 +140,25 @@ export type CreatePulseXCarrierOptions = {
123
140
  * field for why: a host that has not wired this yet gets the carrier's
124
141
  * original behavior, `prepare` a no-op and `exact` always `null`.
125
142
  *
126
- * @param chainId - always {@link pulsechainChainId} — PulseX runs nowhere else
143
+ * @param chainId - a chain that has swap venues
127
144
  * @returns a client, or null when this host has none
128
145
  */
129
146
  readonly clientForChain?: (chainId: number) => PublicClient | null;
130
147
  /**
131
- * The PulseX routers this host can SIGN on. The carrier offers an edge on
132
- * each, and only on these: an edge is always signed on the router it was
133
- * quoted against ({@link pulseXRouterForEdge}), so a router the host cannot
134
- * sign on must never be quoted either.
148
+ * The swap venues to offer. Merged over {@link defaultSwapVenues} by
149
+ * {@link resolveSwapVenues}: a chain named here REPLACES that chain's
150
+ * default list, a chain left out keeps its defaults, and an empty list
151
+ * switches swaps off on that chain. A venue on ANY chain builds swap edges
152
+ * there.
153
+ */
154
+ readonly venues?: SwapVenues;
155
+ /**
156
+ * Narrows the offered venues to these routers. An edge is always signed on
157
+ * the router it was quoted against ({@link venueForEdge}), so a router the
158
+ * host cannot sign on must never be quoted either. A router that is in no
159
+ * offered venue is a configuration error and throws at construction.
135
160
  *
136
- * Defaults to every known venue ({@link pulseXVenues}: V1 and V2).
161
+ * Defaults to every offered venue.
137
162
  */
138
163
  readonly routers?: readonly Hex[];
139
164
  };