@gibs/bridge-sdk 1.13.1 → 1.17.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.
- package/README.md +244 -18
- package/abis/package.json +6 -0
- package/bridge-limits/package.json +6 -0
- package/chain-info/package.json +6 -0
- package/chain-names/package.json +6 -0
- package/chains/package.json +6 -0
- package/claims/package.json +6 -0
- package/config/package.json +6 -0
- package/consolidated-quote/package.json +6 -0
- package/destination-calldata/package.json +6 -0
- package/dist/chain-info.d.ts +1 -1
- package/dist/chain-info.js +11 -12
- package/dist/chains.d.ts +25 -0
- package/dist/chains.js +55 -20
- package/dist/cjs/abis.d.ts +1 -0
- package/dist/cjs/abis.js +19 -0
- package/dist/cjs/bridge-limits.d.ts +103 -0
- package/dist/cjs/bridge-limits.js +89 -0
- package/dist/cjs/chain-info.d.ts +169 -0
- package/dist/cjs/chain-info.js +452 -0
- package/dist/cjs/chain-names.d.ts +160 -0
- package/dist/cjs/chain-names.js +207 -0
- package/dist/cjs/chains.d.ts +90 -0
- package/dist/cjs/chains.js +357 -0
- package/dist/cjs/claims.d.ts +198 -0
- package/dist/cjs/claims.js +182 -0
- package/dist/cjs/config.d.ts +240 -0
- package/dist/cjs/config.js +537 -0
- package/dist/cjs/consolidated-quote.d.ts +648 -0
- package/dist/cjs/consolidated-quote.js +1048 -0
- package/dist/cjs/destination-calldata.d.ts +118 -0
- package/dist/cjs/destination-calldata.js +156 -0
- package/dist/cjs/ecosystems.d.ts +217 -0
- package/dist/cjs/ecosystems.js +298 -0
- package/dist/cjs/execution.d.ts +346 -0
- package/dist/cjs/execution.js +468 -0
- package/dist/cjs/fee-type.d.ts +10 -0
- package/dist/cjs/fee-type.js +10 -0
- package/dist/cjs/hyperliquid-execution.d.ts +152 -0
- package/dist/cjs/hyperliquid-execution.js +175 -0
- package/dist/cjs/image-links.d.ts +117 -0
- package/dist/cjs/image-links.js +153 -0
- package/dist/cjs/index.d.ts +23 -0
- package/dist/cjs/index.js +39 -0
- package/dist/cjs/lifi-execution-guard.d.ts +210 -0
- package/dist/cjs/lifi-execution-guard.js +409 -0
- package/dist/cjs/near-intents-conformance.d.ts +85 -0
- package/dist/cjs/near-intents-conformance.js +337 -0
- package/dist/cjs/near-intents-route.d.ts +47 -0
- package/dist/cjs/near-intents-route.js +303 -0
- package/dist/cjs/near-intents.d.ts +524 -0
- package/dist/cjs/near-intents.js +1071 -0
- package/dist/cjs/origin-deposit.d.ts +326 -0
- package/dist/cjs/origin-deposit.js +82 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/pre-quote.d.ts +198 -0
- package/dist/cjs/pre-quote.js +180 -0
- package/dist/cjs/prices.d.ts +107 -0
- package/dist/cjs/prices.js +172 -0
- package/dist/cjs/providers.d.ts +238 -0
- package/dist/cjs/providers.js +171 -0
- package/dist/cjs/quote-fees.d.ts +102 -0
- package/dist/cjs/quote-fees.js +201 -0
- package/dist/cjs/referral.d.ts +85 -0
- package/dist/cjs/referral.js +85 -0
- package/dist/cjs/relay-currencies.d.ts +47 -0
- package/dist/cjs/relay-currencies.js +95 -0
- package/dist/cjs/relay-depository.d.ts +2 -0
- package/dist/cjs/relay-depository.js +85 -0
- package/dist/cjs/relay-quote.d.ts +301 -0
- package/dist/cjs/relay-quote.js +996 -0
- package/dist/cjs/route-steps.d.ts +138 -0
- package/dist/cjs/route-steps.js +310 -0
- package/dist/cjs/routing/amounts.d.ts +80 -0
- package/dist/cjs/routing/amounts.js +126 -0
- package/dist/cjs/routing/candidate-route.d.ts +43 -0
- package/dist/cjs/routing/candidate-route.js +50 -0
- package/dist/cjs/routing/candidate.d.ts +237 -0
- package/dist/cjs/routing/candidate.js +100 -0
- package/dist/cjs/routing/carriers/ask-answer.d.ts +77 -0
- package/dist/cjs/routing/carriers/ask-answer.js +2 -0
- package/dist/cjs/routing/carriers/omnibridge.d.ts +137 -0
- package/dist/cjs/routing/carriers/omnibridge.js +459 -0
- package/dist/cjs/routing/carriers/pulsex-paths.d.ts +80 -0
- package/dist/cjs/routing/carriers/pulsex-paths.js +97 -0
- package/dist/cjs/routing/carriers/pulsex-split.d.ts +175 -0
- package/dist/cjs/routing/carriers/pulsex-split.js +193 -0
- package/dist/cjs/routing/carriers/pulsex.d.ts +159 -0
- package/dist/cjs/routing/carriers/pulsex.js +565 -0
- package/dist/cjs/routing/carriers/wrap.d.ts +25 -0
- package/dist/cjs/routing/carriers/wrap.js +119 -0
- package/dist/cjs/routing/composed-route-quality.d.ts +125 -0
- package/dist/cjs/routing/composed-route-quality.js +144 -0
- package/dist/cjs/routing/entry-chain-anchor.d.ts +88 -0
- package/dist/cjs/routing/entry-chain-anchor.js +59 -0
- package/dist/cjs/routing/format.d.ts +31 -0
- package/dist/cjs/routing/format.js +64 -0
- package/dist/cjs/routing/index.d.ts +38 -0
- package/dist/cjs/routing/index.js +134 -0
- package/dist/cjs/routing/producers.d.ts +770 -0
- package/dist/cjs/routing/producers.js +1617 -0
- package/dist/cjs/routing/providers.d.ts +31 -0
- package/dist/cjs/routing/providers.js +48 -0
- package/dist/cjs/routing/route-data.d.ts +355 -0
- package/dist/cjs/routing/route-data.js +2 -0
- package/dist/cjs/routing/search/compose.d.ts +168 -0
- package/dist/cjs/routing/search/compose.js +104 -0
- package/dist/cjs/routing/search/graph.d.ts +668 -0
- package/dist/cjs/routing/search/graph.js +461 -0
- package/dist/cjs/routing/search/plan-route-data.d.ts +269 -0
- package/dist/cjs/routing/search/plan-route-data.js +848 -0
- package/dist/cjs/routing/search/score.d.ts +356 -0
- package/dist/cjs/routing/search/score.js +445 -0
- package/dist/cjs/routing/swap-transactions.d.ts +91 -0
- package/dist/cjs/routing/swap-transactions.js +131 -0
- package/dist/cjs/routing/usd-value.d.ts +17 -0
- package/dist/cjs/routing/usd-value.js +29 -0
- package/dist/cjs/settings.d.ts +785 -0
- package/dist/cjs/settings.js +1074 -0
- package/dist/cjs/ton-connect.d.ts +98 -0
- package/dist/cjs/ton-connect.js +206 -0
- package/dist/cjs/ton-execution.d.ts +7 -0
- package/dist/cjs/ton-execution.js +23 -0
- package/dist/cjs/ton.d.ts +37 -0
- package/dist/cjs/ton.js +83 -0
- package/dist/cjs/tron-execution.d.ts +146 -0
- package/dist/cjs/tron-execution.js +248 -0
- package/dist/cjs/types.d.ts +51 -0
- package/dist/cjs/types.js +2 -0
- package/dist/claims.d.ts +198 -0
- package/dist/claims.js +140 -0
- package/dist/config.d.ts +24 -0
- package/dist/config.js +39 -5
- package/dist/consolidated-quote.d.ts +109 -15
- package/dist/consolidated-quote.js +310 -52
- package/dist/execution.d.ts +346 -0
- package/dist/execution.js +428 -0
- package/dist/hyperliquid-execution.js +2 -3
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/lifi-execution-guard.d.ts +13 -2
- package/dist/lifi-execution-guard.js +4 -0
- package/dist/near-intents.js +2 -3
- package/dist/pre-quote.d.ts +6 -6
- package/dist/pre-quote.js +10 -14
- package/dist/providers.d.ts +17 -0
- package/dist/providers.js +6 -0
- package/dist/referral.d.ts +12 -4
- package/dist/referral.js +12 -4
- package/dist/relay-depository.d.ts +2 -0
- package/dist/relay-depository.js +82 -0
- package/dist/relay-quote.js +2 -3
- package/dist/routing/candidate.d.ts +3 -3
- package/dist/routing/candidate.js +3 -3
- package/dist/routing/carriers/ask-answer.d.ts +17 -0
- package/dist/routing/carriers/omnibridge.js +23 -21
- package/dist/routing/carriers/pulsex-paths.d.ts +80 -0
- package/dist/routing/carriers/pulsex-paths.js +92 -0
- package/dist/routing/carriers/pulsex-split.d.ts +175 -0
- package/dist/routing/carriers/pulsex-split.js +185 -0
- package/dist/routing/carriers/pulsex.d.ts +31 -21
- package/dist/routing/carriers/pulsex.js +141 -71
- package/dist/routing/composed-route-quality.d.ts +28 -6
- package/dist/routing/composed-route-quality.js +36 -5
- package/dist/routing/entry-chain-anchor.d.ts +1 -1
- package/dist/routing/entry-chain-anchor.js +1 -1
- package/dist/routing/index.d.ts +6 -2
- package/dist/routing/index.js +6 -2
- package/dist/routing/producers.js +1 -1
- package/dist/routing/providers.d.ts +5 -0
- package/dist/routing/providers.js +5 -0
- package/dist/routing/search/graph.d.ts +15 -0
- package/dist/routing/search/plan-route-data.d.ts +25 -0
- package/dist/routing/search/plan-route-data.js +43 -7
- package/dist/routing/search/score.d.ts +3 -0
- package/dist/routing/search/score.js +11 -3
- package/dist/routing/swap-transactions.d.ts +91 -0
- package/dist/routing/swap-transactions.js +125 -0
- package/dist/settings.d.ts +94 -1
- package/dist/settings.js +95 -3
- package/dist/ton-connect.d.ts +98 -0
- package/dist/ton-connect.js +200 -0
- package/dist/ton-execution.d.ts +4 -114
- package/dist/ton-execution.js +4 -244
- package/dist/ton.d.ts +37 -0
- package/dist/ton.js +65 -0
- package/docs/examples/example-a-ether-to-pulse.ts +300 -0
- package/docs/examples/example-b-token-pulsechain-to-ethereum.ts +270 -0
- package/docs/examples/shared.ts +261 -0
- package/docs/examples/tsconfig.json +18 -0
- package/docs/integration-guide.md +617 -0
- package/ecosystems/package.json +6 -0
- package/execution/package.json +6 -0
- package/fee-type/package.json +6 -0
- package/hyperliquid-execution/package.json +6 -0
- package/image-links/package.json +6 -0
- package/lifi-execution-guard/package.json +6 -0
- package/llms.txt +75 -10
- package/near-intents/package.json +6 -0
- package/near-intents-route/package.json +6 -0
- package/origin-deposit/package.json +6 -0
- package/package.json +817 -10
- package/pre-quote/package.json +6 -0
- package/prices/package.json +6 -0
- package/providers/package.json +6 -0
- package/quote-fees/package.json +6 -0
- package/referral/package.json +6 -0
- package/relay-currencies/package.json +6 -0
- package/relay-quote/package.json +6 -0
- package/route-steps/package.json +6 -0
- package/routing/package.json +6 -0
- package/settings/package.json +6 -0
- package/ton/package.json +6 -0
- package/ton-connect/package.json +6 -0
- package/ton-execution/package.json +6 -0
- package/tron-execution/package.json +6 -0
- package/types/package.json +6 -0
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.readPulseXSectionQuote = exports.planCandidateExecution = exports.planExecution = exports.assumeNoAllowance = void 0;
|
|
37
|
+
const viem_1 = require("viem");
|
|
38
|
+
const abis = __importStar(require("./abis.js"));
|
|
39
|
+
const config_js_1 = require("./config.js");
|
|
40
|
+
const consolidated_quote_js_1 = require("./consolidated-quote.js");
|
|
41
|
+
const pulsex_js_1 = require("./routing/carriers/pulsex.js");
|
|
42
|
+
const swap_transactions_js_1 = require("./routing/swap-transactions.js");
|
|
43
|
+
const settings_js_1 = require("./settings.js");
|
|
44
|
+
/**
|
|
45
|
+
* An {@link AllowanceReader} that reports no allowance anywhere, so the plan
|
|
46
|
+
* includes every approval. For a caller that reads allowances itself at send
|
|
47
|
+
* time.
|
|
48
|
+
*/
|
|
49
|
+
const assumeNoAllowance = async () => 0n;
|
|
50
|
+
exports.assumeNoAllowance = assumeNoAllowance;
|
|
51
|
+
const refusal = (value) => ({ kind: 'refused', refusal: value });
|
|
52
|
+
/** The fee director a delivery choice encodes, or null when the reader buys no delivery. */
|
|
53
|
+
const encodeDelivery = ({ leg, pathway, }) => {
|
|
54
|
+
const { delivery } = leg;
|
|
55
|
+
if (!delivery.shouldDeliver)
|
|
56
|
+
return { kind: 'encoded', feeDirector: null };
|
|
57
|
+
if (!pathway.requiresDelivery)
|
|
58
|
+
return refusal({ reason: 'delivery-not-offered' });
|
|
59
|
+
// A zero fee pays no relayer, so the transfer would wait for a delivery that never comes.
|
|
60
|
+
if (delivery.fee.maximumFee <= 0n)
|
|
61
|
+
return refusal({ reason: 'delivery-fee-missing' });
|
|
62
|
+
const feeDirector = (0, settings_js_1.feeDirectorStructEncoded)({
|
|
63
|
+
recipient: leg.recipient,
|
|
64
|
+
bridgePathway: pathway,
|
|
65
|
+
feeType: delivery.fee.feeType,
|
|
66
|
+
priceCorrective: delivery.fee.priceCorrective,
|
|
67
|
+
gasTipFee: delivery.fee.gasTipFee,
|
|
68
|
+
percentFee: delivery.fee.percentFee,
|
|
69
|
+
feeTypeSettings: (0, settings_js_1.feeTypeSettings)({ feeType: delivery.fee.feeType, unwrap: leg.unwrap }),
|
|
70
|
+
limit: delivery.fee.maximumFee,
|
|
71
|
+
assetOut: delivery.fee.assetOut,
|
|
72
|
+
});
|
|
73
|
+
if (feeDirector === null)
|
|
74
|
+
return refusal({ reason: 'delivery-fee-unencodable' });
|
|
75
|
+
return { kind: 'encoded', feeDirector };
|
|
76
|
+
};
|
|
77
|
+
const deliveryTermsOf = (delivery) => {
|
|
78
|
+
if (!delivery.shouldDeliver)
|
|
79
|
+
return { status: 'not-requested' };
|
|
80
|
+
return {
|
|
81
|
+
status: 'requested',
|
|
82
|
+
feeType: delivery.fee.feeType,
|
|
83
|
+
maximumFee: delivery.fee.maximumFee,
|
|
84
|
+
feeToken: delivery.fee.assetOut,
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
const omnibridgeCalls = (leg, account) => {
|
|
88
|
+
if (leg.amountIn <= 0n)
|
|
89
|
+
return refusal({ reason: 'amount-not-positive' });
|
|
90
|
+
const pathway = (0, settings_js_1.bridgePathway)({ bridgeKey: leg.bridgeKey, isProd: leg.isProd, assetIn: leg.assetIn });
|
|
91
|
+
if (pathway === null)
|
|
92
|
+
return refusal({ reason: 'no-pathway' });
|
|
93
|
+
const encoded = encodeDelivery({ leg, pathway });
|
|
94
|
+
if (encoded.kind !== 'encoded')
|
|
95
|
+
return encoded;
|
|
96
|
+
const { feeDirector } = encoded;
|
|
97
|
+
const dataParam = (0, settings_js_1.destinationDataParam)({
|
|
98
|
+
recipient: leg.recipient,
|
|
99
|
+
bridgePathway: pathway,
|
|
100
|
+
assetIn: leg.assetIn,
|
|
101
|
+
destinationRouter: pathway.destinationRouter,
|
|
102
|
+
feeDirectorStructEncoded: feeDirector,
|
|
103
|
+
assetLink: leg.assetLink,
|
|
104
|
+
shouldDeliver: leg.delivery.shouldDeliver,
|
|
105
|
+
unwrap: leg.unwrap,
|
|
106
|
+
});
|
|
107
|
+
const call = (0, settings_js_1.transactionInputs)({
|
|
108
|
+
bridgeKey: leg.bridgeKey,
|
|
109
|
+
signedCrossing: { originChainId: Number(leg.bridgeKey[1]), destinationChainId: Number(leg.bridgeKey[2]) },
|
|
110
|
+
bridgePathway: pathway,
|
|
111
|
+
assetIn: leg.assetIn,
|
|
112
|
+
recipient: leg.recipient,
|
|
113
|
+
account,
|
|
114
|
+
assetLink: leg.assetLink,
|
|
115
|
+
destinationDataParam: dataParam,
|
|
116
|
+
amountToBridge: leg.amountIn,
|
|
117
|
+
feeDirectorStructEncoded: feeDirector,
|
|
118
|
+
shouldDeliver: leg.delivery.shouldDeliver,
|
|
119
|
+
});
|
|
120
|
+
if (call === null)
|
|
121
|
+
return refusal({ reason: 'bridge-call-refused' });
|
|
122
|
+
return {
|
|
123
|
+
kind: 'calls',
|
|
124
|
+
approval: (0, settings_js_1.omnibridgeApproval)({
|
|
125
|
+
bridgePathway: pathway,
|
|
126
|
+
assetIn: leg.assetIn,
|
|
127
|
+
assetLink: leg.assetLink,
|
|
128
|
+
amountToBridge: leg.amountIn,
|
|
129
|
+
}),
|
|
130
|
+
action: { chainId: Number(leg.bridgeKey[1]), kind: 'bridge', ...call, gasLimit: null },
|
|
131
|
+
delivery: deliveryTermsOf(leg.delivery),
|
|
132
|
+
};
|
|
133
|
+
};
|
|
134
|
+
const pulseXSwapCalls = (leg) => {
|
|
135
|
+
const { edge } = leg.hop;
|
|
136
|
+
const chainId = edge.from.chainId;
|
|
137
|
+
const routerAddress = (0, pulsex_js_1.pulseXRouterForEdge)(edge);
|
|
138
|
+
// The builder refuses a hop that records no priced path, a router other
|
|
139
|
+
// than the edge's own, and a leg on screen that disagrees.
|
|
140
|
+
const call = (0, swap_transactions_js_1.buildPulseXSwapTransaction)({
|
|
141
|
+
hop: leg.hop,
|
|
142
|
+
amountIn: leg.amountIn,
|
|
143
|
+
minAmountOut: leg.minAmountOut,
|
|
144
|
+
recipient: leg.recipient,
|
|
145
|
+
deadline: leg.deadline,
|
|
146
|
+
signedLeg: { kind: 'swap', chainId },
|
|
147
|
+
chainId,
|
|
148
|
+
routerAddress,
|
|
149
|
+
});
|
|
150
|
+
if (call === null || routerAddress === null)
|
|
151
|
+
return refusal({ reason: 'swap-refused' });
|
|
152
|
+
const spendsNative = edge.from.address.toLowerCase() === viem_1.zeroAddress;
|
|
153
|
+
return {
|
|
154
|
+
kind: 'calls',
|
|
155
|
+
approval: spendsNative
|
|
156
|
+
? null
|
|
157
|
+
: { chainId, token: edge.from.address, spender: routerAddress, minimum: leg.amountIn },
|
|
158
|
+
action: { chainId, kind: 'swap', ...call, gasLimit: null },
|
|
159
|
+
delivery: null,
|
|
160
|
+
};
|
|
161
|
+
};
|
|
162
|
+
const wrapCalls = (leg) => {
|
|
163
|
+
const call = (0, swap_transactions_js_1.buildWrapTransaction)({ edge: leg.edge, amountIn: leg.amountIn });
|
|
164
|
+
if (call === null)
|
|
165
|
+
return refusal({ reason: 'wrap-refused' });
|
|
166
|
+
const wraps = leg.edge.from.address.toLowerCase() === viem_1.zeroAddress;
|
|
167
|
+
return {
|
|
168
|
+
kind: 'calls',
|
|
169
|
+
approval: null,
|
|
170
|
+
action: { chainId: leg.edge.from.chainId, kind: wraps ? 'wrap' : 'unwrap', ...call, gasLimit: null },
|
|
171
|
+
delivery: null,
|
|
172
|
+
};
|
|
173
|
+
};
|
|
174
|
+
const aggregatorCalls = (leg) => {
|
|
175
|
+
const origin = (0, consolidated_quote_js_1.aggregatorOriginCalls)({ quote: leg.quote, request: leg.request });
|
|
176
|
+
if (origin.kind === 'refused')
|
|
177
|
+
return refusal({ reason: 'aggregator-origin-refused', origin: origin.refusal });
|
|
178
|
+
const { approval, deposit } = origin;
|
|
179
|
+
const staysOnChain = leg.request.toChainId === leg.request.fromChainId;
|
|
180
|
+
return {
|
|
181
|
+
kind: 'calls',
|
|
182
|
+
approval,
|
|
183
|
+
action: {
|
|
184
|
+
chainId: leg.request.fromChainId,
|
|
185
|
+
kind: staysOnChain ? 'swap' : 'bridge',
|
|
186
|
+
to: deposit.to,
|
|
187
|
+
data: deposit.data,
|
|
188
|
+
value: deposit.value,
|
|
189
|
+
gasLimit: deposit.gasLimit,
|
|
190
|
+
},
|
|
191
|
+
delivery: null,
|
|
192
|
+
};
|
|
193
|
+
};
|
|
194
|
+
const legCalls = (leg, account) => {
|
|
195
|
+
if (leg.kind === 'omnibridge')
|
|
196
|
+
return omnibridgeCalls(leg, account);
|
|
197
|
+
if (leg.kind === 'pulsex-swap')
|
|
198
|
+
return pulseXSwapCalls(leg);
|
|
199
|
+
if (leg.kind === 'wrap')
|
|
200
|
+
return wrapCalls(leg);
|
|
201
|
+
return aggregatorCalls(leg);
|
|
202
|
+
};
|
|
203
|
+
/** The approve transactions an approval needs now: none when the allowance on chain covers it. */
|
|
204
|
+
const approvalTransactions = async ({ approval, account, readAllowance, }) => {
|
|
205
|
+
const allowance = await readAllowance(approval.chainId, approval.token, account, approval.spender);
|
|
206
|
+
return (0, settings_js_1.approvalAmounts)({ allowance, minimum: approval.minimum }).map((amount) => ({
|
|
207
|
+
chainId: approval.chainId,
|
|
208
|
+
kind: 'approve',
|
|
209
|
+
...(0, settings_js_1.approveCall)({ token: approval.token, spender: approval.spender, amount }),
|
|
210
|
+
gasLimit: null,
|
|
211
|
+
}));
|
|
212
|
+
};
|
|
213
|
+
/**
|
|
214
|
+
* Plans the transactions for a list of legs, in order.
|
|
215
|
+
*
|
|
216
|
+
* Each leg contributes the exact approval it needs when the allowance on
|
|
217
|
+
* chain does not cover it (a reset to zero first when a smaller allowance
|
|
218
|
+
* remains), then its own call. Nothing is sent.
|
|
219
|
+
*
|
|
220
|
+
* @param options.account - the account that signs every transaction
|
|
221
|
+
* @param options.legs - the legs, in the order the wallet signs them
|
|
222
|
+
* @param options.readAllowance - reads an allowance on chain; see {@link AllowanceReader}
|
|
223
|
+
* @returns the ordered transactions, or the first leg that cannot be planned
|
|
224
|
+
*/
|
|
225
|
+
const planExecution = async ({ account, legs, readAllowance, }) => {
|
|
226
|
+
const calls = legs.map((leg) => legCalls(leg, account));
|
|
227
|
+
const refusedIndex = calls.findIndex((entry) => entry.kind === 'refused');
|
|
228
|
+
const refused = calls[refusedIndex];
|
|
229
|
+
if (refused !== undefined && refused.kind === 'refused') {
|
|
230
|
+
return { kind: 'refused', legIndex: refusedIndex, refusal: refused.refusal };
|
|
231
|
+
}
|
|
232
|
+
const planned = calls.flatMap((entry) => (entry.kind === 'calls' ? [entry] : []));
|
|
233
|
+
const perLeg = await Promise.all(planned.map(async (entry) => {
|
|
234
|
+
const approvals = entry.approval === null
|
|
235
|
+
? []
|
|
236
|
+
: await approvalTransactions({ approval: entry.approval, account, readAllowance });
|
|
237
|
+
return [...approvals, entry.action];
|
|
238
|
+
}));
|
|
239
|
+
const ordered = perLeg.flat();
|
|
240
|
+
const transactions = ordered.map((action, index) => ({ ...action, waitForReceipt: index < ordered.length - 1 }));
|
|
241
|
+
const deliveries = planned.flatMap((entry, legIndex) => entry.delivery === null ? [] : [{ ...entry.delivery, legIndex }]);
|
|
242
|
+
return { kind: 'planned', transactions, deliveries };
|
|
243
|
+
};
|
|
244
|
+
exports.planExecution = planExecution;
|
|
245
|
+
const OMNIBRIDGE_CARRIERS = new Set(Object.values(config_js_1.Providers));
|
|
246
|
+
const isOmnibridgeCarrier = (carrier) => OMNIBRIDGE_CARRIERS.has(carrier);
|
|
247
|
+
const missing = (needs) => ({
|
|
248
|
+
kind: 'refused',
|
|
249
|
+
refusal: { reason: 'section-inputs-missing', needs },
|
|
250
|
+
});
|
|
251
|
+
const shape = (detail) => ({ kind: 'refused', refusal: { reason: 'section-shape', detail } });
|
|
252
|
+
const omnibridgeSectionLeg = ({ carrier, from, to, inputs, assetIn, }) => {
|
|
253
|
+
if (inputs.omnibridge === undefined)
|
|
254
|
+
return missing('omnibridge');
|
|
255
|
+
return {
|
|
256
|
+
kind: 'leg',
|
|
257
|
+
leg: {
|
|
258
|
+
kind: 'omnibridge',
|
|
259
|
+
bridgeKey: [carrier, (0, config_js_1.toChain)(from.chainId), (0, config_js_1.toChain)(to.chainId)],
|
|
260
|
+
isProd: inputs.omnibridge.isProd,
|
|
261
|
+
assetIn,
|
|
262
|
+
assetLink: inputs.omnibridge.assetLink,
|
|
263
|
+
amountIn: inputs.amountIn,
|
|
264
|
+
recipient: inputs.recipient,
|
|
265
|
+
delivery: inputs.omnibridge.delivery,
|
|
266
|
+
unwrap: inputs.omnibridge.unwrap,
|
|
267
|
+
},
|
|
268
|
+
};
|
|
269
|
+
};
|
|
270
|
+
const liveQuoteRequired = { kind: 'refused', refusal: { reason: 'live-quote-required' } };
|
|
271
|
+
const aggregatorSectionLeg = (carrier, inputs) => {
|
|
272
|
+
if (inputs.aggregator === undefined)
|
|
273
|
+
return liveQuoteRequired;
|
|
274
|
+
const { quote, request } = inputs.aggregator;
|
|
275
|
+
if (quote.provider !== carrier) {
|
|
276
|
+
return {
|
|
277
|
+
kind: 'refused',
|
|
278
|
+
refusal: { reason: 'quote-provider-mismatch', quoteProvider: quote.provider, sectionCarrier: carrier },
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
return { kind: 'leg', leg: { kind: 'aggregator', quote, request } };
|
|
282
|
+
};
|
|
283
|
+
const pulseXSectionLeg = (hop, inputs) => {
|
|
284
|
+
if (inputs.swap === undefined)
|
|
285
|
+
return missing('swap');
|
|
286
|
+
const { quotedAmountOut } = inputs.swap;
|
|
287
|
+
if (quotedAmountOut !== undefined && quotedAmountOut <= 0n) {
|
|
288
|
+
return { kind: 'refused', refusal: { reason: 'swap-quote-not-positive' } };
|
|
289
|
+
}
|
|
290
|
+
// Without a fresh quote the floor comes from the hop's own figure, so it must be a real quote.
|
|
291
|
+
if (quotedAmountOut === undefined && hop.outcome.kind !== 'quote') {
|
|
292
|
+
return { kind: 'refused', refusal: { reason: 'swap-estimate-only' } };
|
|
293
|
+
}
|
|
294
|
+
return {
|
|
295
|
+
kind: 'leg',
|
|
296
|
+
leg: {
|
|
297
|
+
kind: 'pulsex-swap',
|
|
298
|
+
hop,
|
|
299
|
+
amountIn: inputs.amountIn,
|
|
300
|
+
minAmountOut: (0, swap_transactions_js_1.swapMinimumOut)({
|
|
301
|
+
quotedAmount: quotedAmountOut ?? hop.outcome.deliveredAmount,
|
|
302
|
+
slippageBasisPoints: inputs.swap.slippageBasisPoints,
|
|
303
|
+
}),
|
|
304
|
+
recipient: inputs.recipient,
|
|
305
|
+
deadline: inputs.swap.deadline,
|
|
306
|
+
},
|
|
307
|
+
};
|
|
308
|
+
};
|
|
309
|
+
/** Turns one section of an engine plan into its leg, dispatching on the first hop's carrier. */
|
|
310
|
+
const planSectionLeg = ({ hops, inputs, resolveToken, }) => {
|
|
311
|
+
const firstHop = hops[0];
|
|
312
|
+
if (firstHop === undefined)
|
|
313
|
+
return shape('the section has no hops');
|
|
314
|
+
const { carrier, origin, from, to } = firstHop.edge;
|
|
315
|
+
if (origin === 'by-hand')
|
|
316
|
+
return { kind: 'refused', refusal: { reason: 'paid-by-hand' } };
|
|
317
|
+
// An aggregator section may run several hops inside one signature (a fused
|
|
318
|
+
// omnibridge entry); every other carrier signs exactly one hop.
|
|
319
|
+
const singleHop = hops.length === 1;
|
|
320
|
+
if (isOmnibridgeCarrier(carrier)) {
|
|
321
|
+
if (!singleHop)
|
|
322
|
+
return shape('an omnibridge section is exactly one hop');
|
|
323
|
+
return omnibridgeSectionLeg({ carrier, from, to, inputs, assetIn: resolveToken(from) });
|
|
324
|
+
}
|
|
325
|
+
if (carrier === 'PulseX') {
|
|
326
|
+
if (!singleHop)
|
|
327
|
+
return shape('a swap section is exactly one hop');
|
|
328
|
+
return pulseXSectionLeg(firstHop, inputs);
|
|
329
|
+
}
|
|
330
|
+
if (carrier === 'wrap') {
|
|
331
|
+
if (!singleHop)
|
|
332
|
+
return shape('a wrap section is exactly one hop');
|
|
333
|
+
return { kind: 'leg', leg: { kind: 'wrap', edge: firstHop.edge, amountIn: inputs.amountIn } };
|
|
334
|
+
}
|
|
335
|
+
return aggregatorSectionLeg(carrier, inputs);
|
|
336
|
+
};
|
|
337
|
+
/** The sections of a plan, each as its hops. */
|
|
338
|
+
const planSections = (plan) => plan.signatures.map((group) => group.flatMap((hopIndex) => plan.hops[hopIndex] ?? []));
|
|
339
|
+
/**
|
|
340
|
+
* A candidate built without an engine plan is one signature: either a
|
|
341
|
+
* same-chain omnibridge crossing (`buildDirectCrossingCandidate`, whose quote
|
|
342
|
+
* names the bridge) or an aggregator quote.
|
|
343
|
+
*
|
|
344
|
+
* THE CANDIDATE'S OWN QUOTE IS NEVER SIGNED. It priced the route on screen
|
|
345
|
+
* and may be stale or a dry probe; only the live quote in
|
|
346
|
+
* `inputs.aggregator` is. Without one the section is refused with
|
|
347
|
+
* `live-quote-required`.
|
|
348
|
+
*/
|
|
349
|
+
const planlessSectionLeg = (candidate, inputs) => {
|
|
350
|
+
const provider = candidate.quote.provider;
|
|
351
|
+
if (isOmnibridgeCarrier(provider)) {
|
|
352
|
+
return omnibridgeSectionLeg({
|
|
353
|
+
carrier: provider,
|
|
354
|
+
from: candidate.originToken,
|
|
355
|
+
to: candidate.destinationToken,
|
|
356
|
+
inputs,
|
|
357
|
+
assetIn: candidate.originToken,
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
return aggregatorSectionLeg(provider, inputs);
|
|
361
|
+
};
|
|
362
|
+
/**
|
|
363
|
+
* What is wrong with the requested window of sections, or null when it fits.
|
|
364
|
+
* A window starts at `firstSectionIndex` and spans `plannedCount` sections.
|
|
365
|
+
*/
|
|
366
|
+
const sectionWindowProblem = ({ firstSectionIndex, plannedCount, sectionCount, }) => {
|
|
367
|
+
if (!Number.isSafeInteger(firstSectionIndex) || firstSectionIndex < 0) {
|
|
368
|
+
return `firstSectionIndex must be a non-negative safe integer, received ${firstSectionIndex}`;
|
|
369
|
+
}
|
|
370
|
+
if (plannedCount < 1)
|
|
371
|
+
return `pass at least 1 section input, received ${plannedCount}`;
|
|
372
|
+
if (firstSectionIndex + plannedCount > sectionCount) {
|
|
373
|
+
return `sections ${firstSectionIndex} to ${firstSectionIndex + plannedCount - 1} do not fit a route of ${sectionCount} section${sectionCount === 1 ? '' : 's'}`;
|
|
374
|
+
}
|
|
375
|
+
return null;
|
|
376
|
+
};
|
|
377
|
+
/**
|
|
378
|
+
* Plans the transactions for a chosen route candidate: the candidate
|
|
379
|
+
* `buildRouteCandidateFromPlan` returns for an engine plan (the interface's
|
|
380
|
+
* `buildCandidateFromEnginePlan`), or a candidate built without a plan.
|
|
381
|
+
*
|
|
382
|
+
* ONE SECTION IS ONE SIGNATURE. A plan's `signatures` groups its hops into
|
|
383
|
+
* sections; the section's first hop names its carrier. An omnibridge section
|
|
384
|
+
* becomes a crossing, a PulseX section a swap signed on its recorded path, a
|
|
385
|
+
* wrap section a wrap or unwrap, and any other wallet-signed carrier an
|
|
386
|
+
* aggregator deposit from the live quote the caller supplies. A section paid
|
|
387
|
+
* by hand has nothing to sign and is refused.
|
|
388
|
+
*
|
|
389
|
+
* A LATER SECTION CAN BE PLANNED ALONE. Pass `firstSectionIndex` to skip the
|
|
390
|
+
* sections that already landed. The wallet then plans the swap after the
|
|
391
|
+
* crossing arrived, from the amount that arrived, with a fresh
|
|
392
|
+
* `swap.quotedAmountOut` and a fresh `swap.deadline`. The slippage floor and the
|
|
393
|
+
* deadline are not fixed minutes before the swap is signed. Every safety check
|
|
394
|
+
* still applies to the later section: verified spenders, live quotes for
|
|
395
|
+
* aggregator sections, exact approvals.
|
|
396
|
+
*
|
|
397
|
+
* Every `sectionIndex` in a refusal and every `legIndex` in `deliveries` is
|
|
398
|
+
* the absolute section index.
|
|
399
|
+
*
|
|
400
|
+
* @param inputs - see {@link CandidateExecutionInputs}
|
|
401
|
+
* @returns the ordered transactions with the deliveries they buy, or the first section that cannot be planned
|
|
402
|
+
*/
|
|
403
|
+
const planCandidateExecution = async (inputs) => {
|
|
404
|
+
const { candidate, account, readAllowance, resolveToken, sections } = inputs;
|
|
405
|
+
const firstSectionIndex = inputs.firstSectionIndex ?? 0;
|
|
406
|
+
const plan = candidate.plan;
|
|
407
|
+
const allSections = plan === undefined ? null : planSections(plan);
|
|
408
|
+
const sectionCount = allSections === null ? 1 : allSections.length;
|
|
409
|
+
const problem = sectionWindowProblem({ firstSectionIndex, plannedCount: sections.length, sectionCount });
|
|
410
|
+
if (problem !== null) {
|
|
411
|
+
const validIndex = Number.isSafeInteger(firstSectionIndex) && firstSectionIndex >= 0;
|
|
412
|
+
return {
|
|
413
|
+
kind: 'refused',
|
|
414
|
+
sectionIndex: validIndex ? firstSectionIndex : 0,
|
|
415
|
+
refusal: { reason: 'section-shape', detail: problem },
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
const sectionLegs = sections.map((sectionInputs, index) => allSections === null
|
|
419
|
+
? planlessSectionLeg(candidate, sectionInputs)
|
|
420
|
+
: planSectionLeg({ hops: allSections[firstSectionIndex + index] ?? [], inputs: sectionInputs, resolveToken }));
|
|
421
|
+
const refusedIndex = sectionLegs.findIndex((entry) => entry.kind === 'refused');
|
|
422
|
+
const refused = sectionLegs[refusedIndex];
|
|
423
|
+
if (refused !== undefined && refused.kind === 'refused') {
|
|
424
|
+
return { kind: 'refused', sectionIndex: firstSectionIndex + refusedIndex, refusal: refused.refusal };
|
|
425
|
+
}
|
|
426
|
+
const legs = sectionLegs.flatMap((entry) => (entry.kind === 'leg' ? [entry.leg] : []));
|
|
427
|
+
const planned = await (0, exports.planExecution)({ account, legs, readAllowance });
|
|
428
|
+
if (planned.kind === 'refused') {
|
|
429
|
+
return { kind: 'refused', sectionIndex: firstSectionIndex + planned.legIndex, refusal: planned.refusal };
|
|
430
|
+
}
|
|
431
|
+
return {
|
|
432
|
+
kind: 'planned',
|
|
433
|
+
transactions: planned.transactions,
|
|
434
|
+
deliveries: planned.deliveries.map((delivery) => ({ ...delivery, legIndex: firstSectionIndex + delivery.legIndex })),
|
|
435
|
+
remainingSectionCount: sectionCount - firstSectionIndex - sections.length,
|
|
436
|
+
};
|
|
437
|
+
};
|
|
438
|
+
exports.planCandidateExecution = planCandidateExecution;
|
|
439
|
+
/**
|
|
440
|
+
* Reads a fresh quote for a PulseX section: what the router's `getAmountsOut`
|
|
441
|
+
* says the swap delivers for `amountIn`, along the exact path the swap signs
|
|
442
|
+
* ({@link pulseXSwapPathForHop}) on the edge's own router. A wallet passes the
|
|
443
|
+
* result as `swap.quotedAmountOut` just before it signs.
|
|
444
|
+
*
|
|
445
|
+
* @param options.hop - the swap hop; its recorded path and edge name what to read
|
|
446
|
+
* @param options.amountIn - the amount the swap spends, in base units
|
|
447
|
+
* @param options.client - a client that can call `readContract`
|
|
448
|
+
* @returns the amount the last token of the path delivers, or null when the hop records no path, names no known router, the amount is not positive, or the read fails or returns nothing
|
|
449
|
+
*/
|
|
450
|
+
const readPulseXSectionQuote = async ({ hop, amountIn, client, }) => {
|
|
451
|
+
const path = (0, pulsex_js_1.pulseXSwapPathForHop)(hop);
|
|
452
|
+
const router = (0, pulsex_js_1.pulseXRouterForEdge)(hop.edge);
|
|
453
|
+
if (path === null || router === null || amountIn <= 0n)
|
|
454
|
+
return null;
|
|
455
|
+
try {
|
|
456
|
+
const amounts = await client.readContract({
|
|
457
|
+
address: router,
|
|
458
|
+
abi: abis.univ2Router,
|
|
459
|
+
functionName: 'getAmountsOut',
|
|
460
|
+
args: [amountIn, path],
|
|
461
|
+
});
|
|
462
|
+
return amounts.at(-1) ?? null;
|
|
463
|
+
}
|
|
464
|
+
catch {
|
|
465
|
+
return null;
|
|
466
|
+
}
|
|
467
|
+
};
|
|
468
|
+
exports.readPulseXSectionQuote = readPulseXSectionQuote;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** The type of fee to use for the bridge */
|
|
2
|
+
export declare enum FeeType {
|
|
3
|
+
PERCENT = "%",
|
|
4
|
+
GAS_TIP = "gas+%",
|
|
5
|
+
FIXED = "fixed"
|
|
6
|
+
}
|
|
7
|
+
/** The keys of the fee type */
|
|
8
|
+
export type FeeTypeKeys = keyof typeof FeeType;
|
|
9
|
+
/** A map of fee type values to keys */
|
|
10
|
+
export declare const feeTypeValToKeyMap: Map<FeeType, "PERCENT" | "GAS_TIP" | "FIXED">;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.feeTypeValToKeyMap = exports.FeeType = void 0;
|
|
4
|
+
(function (FeeType) {
|
|
5
|
+
FeeType["PERCENT"] = "%";
|
|
6
|
+
FeeType["GAS_TIP"] = "gas+%";
|
|
7
|
+
FeeType["FIXED"] = "fixed";
|
|
8
|
+
})(exports.FeeType || (exports.FeeType = {}));
|
|
9
|
+
/** A map of fee type values to keys */
|
|
10
|
+
exports.feeTypeValToKeyMap = new Map(Object.keys(exports.FeeType).map((key) => [exports.FeeType[key], key]));
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { type Hex } from 'viem';
|
|
2
|
+
import type { HyperliquidAuthorization, HyperliquidDeposit, TypedDataField } from './origin-deposit.js';
|
|
3
|
+
/**
|
|
4
|
+
* Executing a Hyperliquid deposit, as pure data.
|
|
5
|
+
*
|
|
6
|
+
* Hyperliquid is the one origin whose deposit is never broadcast to a chain.
|
|
7
|
+
* The user signs a typed-data ACTION and that signed action is posted to
|
|
8
|
+
* Hyperliquid's own exchange API; Relay then observes the transfer and fills the
|
|
9
|
+
* route. Two details make this impossible to derive from the quote alone, and
|
|
10
|
+
* both are encoded here rather than rediscovered at a call site:
|
|
11
|
+
*
|
|
12
|
+
* 1. Relay's quote supplies `eip712Types`, `eip712PrimaryType` and the action,
|
|
13
|
+
* but NOT the signing domain. The domain is fixed by Hyperliquid and is
|
|
14
|
+
* reconstructed by {@link buildHyperliquidTypedData}.
|
|
15
|
+
* 2. Hyperliquid wants the signature split into `r`/`s`/`v` components, not the
|
|
16
|
+
* concatenated hex string a wallet returns.
|
|
17
|
+
*
|
|
18
|
+
* Kept free of transport so it is fully testable: nothing here signs, fetches,
|
|
19
|
+
* or reads a clock. The caller supplies the signature and performs the request.
|
|
20
|
+
*
|
|
21
|
+
* The shape mirrors Relay's own client, which is the only reference
|
|
22
|
+
* implementation of this exchange — their public documentation covers the
|
|
23
|
+
* generic `signature` step but not this action-bearing `transaction` step.
|
|
24
|
+
*/
|
|
25
|
+
/** Where a signed Hyperliquid action is submitted. Hyperliquid's API, not Relay's. */
|
|
26
|
+
export declare const hyperliquidExchangeUrl = "https://api.hyperliquid.xyz/exchange";
|
|
27
|
+
/** The signing domain Hyperliquid requires. Fixed; never supplied by the quote. */
|
|
28
|
+
export declare const hyperliquidDomainName = "HyperliquidSignTransaction";
|
|
29
|
+
/** The signing domain's version. Fixed alongside {@link hyperliquidDomainName}. */
|
|
30
|
+
export declare const hyperliquidDomainVersion = "1";
|
|
31
|
+
/**
|
|
32
|
+
* The domain's `verifyingContract`. Hyperliquid actions are verified off-chain,
|
|
33
|
+
* so no contract is involved and the field is the all-zero address.
|
|
34
|
+
*/
|
|
35
|
+
export declare const hyperliquidVerifyingContract: "0x0000000000000000000000000000000000000000";
|
|
36
|
+
/** A complete typed-data payload, ready to hand to a wallet's typed-data signing call. */
|
|
37
|
+
export type HyperliquidTypedData = {
|
|
38
|
+
domain: {
|
|
39
|
+
name: string;
|
|
40
|
+
version: string;
|
|
41
|
+
chainId: number;
|
|
42
|
+
verifyingContract: Hex;
|
|
43
|
+
};
|
|
44
|
+
types: Record<string, TypedDataField[]>;
|
|
45
|
+
primaryType: string;
|
|
46
|
+
/**
|
|
47
|
+
* The signed message. This exact object is ALSO the `action` submitted to the
|
|
48
|
+
* exchange, so the bytes signed and the bytes submitted cannot drift apart.
|
|
49
|
+
*/
|
|
50
|
+
message: Record<string, unknown>;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Builds the typed-data payload for a Hyperliquid deposit.
|
|
54
|
+
*
|
|
55
|
+
* The message is the action's parameters plus the action `type` and a
|
|
56
|
+
* `signatureChainId`; the latter is the signing chain in hex and MUST agree
|
|
57
|
+
* with `domain.chainId`, because Hyperliquid recovers the signer using both.
|
|
58
|
+
* They are derived from the single `signatureChainId` argument so they cannot
|
|
59
|
+
* disagree.
|
|
60
|
+
*
|
|
61
|
+
* @param deposit - the parsed Hyperliquid origin deposit
|
|
62
|
+
* @param options.signatureChainId - the chain id the connected wallet signs
|
|
63
|
+
* under. Not the Relay origin chain id: it identifies the signing domain, and
|
|
64
|
+
* Relay's own client uses the wallet's active chain here.
|
|
65
|
+
* @returns the payload to sign, whose `message` doubles as the submitted action
|
|
66
|
+
*/
|
|
67
|
+
export declare const buildHyperliquidTypedData: (deposit: HyperliquidDeposit, { signatureChainId }: {
|
|
68
|
+
signatureChainId: number;
|
|
69
|
+
}) => HyperliquidTypedData;
|
|
70
|
+
/** The JSON body Hyperliquid's exchange endpoint expects for a signed action. */
|
|
71
|
+
export type HyperliquidExchangeRequest = {
|
|
72
|
+
/** The signature split into components; the concatenated hex form is rejected. */
|
|
73
|
+
signature: {
|
|
74
|
+
r: Hex;
|
|
75
|
+
s: Hex;
|
|
76
|
+
v: number;
|
|
77
|
+
};
|
|
78
|
+
/** Replay-protection nonce, which must match the nonce inside the signed action. */
|
|
79
|
+
nonce: number;
|
|
80
|
+
/** The signed message, submitted verbatim. */
|
|
81
|
+
action: Record<string, unknown>;
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Builds the exchange request for an action the user has signed.
|
|
85
|
+
*
|
|
86
|
+
* The nonce is read back out of the signed message rather than passed in: it is
|
|
87
|
+
* covered by the signature, so any independently supplied value could disagree
|
|
88
|
+
* with what was signed and be rejected.
|
|
89
|
+
*
|
|
90
|
+
* @param options.typedData - the payload that was signed
|
|
91
|
+
* @param options.signature - the wallet's signature over it
|
|
92
|
+
* @returns the request body, or null when the signed action carries no usable nonce
|
|
93
|
+
*/
|
|
94
|
+
export declare const buildHyperliquidExchangeRequest: ({ typedData, signature, }: {
|
|
95
|
+
typedData: HyperliquidTypedData;
|
|
96
|
+
signature: Hex;
|
|
97
|
+
}) => HyperliquidExchangeRequest | null;
|
|
98
|
+
/**
|
|
99
|
+
* Whether an exchange response reports success. Hyperliquid answers with HTTP
|
|
100
|
+
* 200 even for a rejected action, so the body's own status is the only reliable
|
|
101
|
+
* signal — treating the status code as the outcome would report a failed
|
|
102
|
+
* transfer as a completed one.
|
|
103
|
+
*
|
|
104
|
+
* @param payload - the parsed response body
|
|
105
|
+
* @returns true only when the body explicitly reports success
|
|
106
|
+
*/
|
|
107
|
+
export declare const isHyperliquidExchangeSuccess: (payload: unknown) => boolean;
|
|
108
|
+
/**
|
|
109
|
+
* The typed-data payload for the authorization that must be completed BEFORE
|
|
110
|
+
* the action is submitted.
|
|
111
|
+
*
|
|
112
|
+
* Relay builds the authorization against a chain it picks when quoting, but the
|
|
113
|
+
* signature is produced by whichever chain the wallet is actually on. Both the
|
|
114
|
+
* domain here and `signatureChainId` in {@link buildHyperliquidAuthorizationRequest}
|
|
115
|
+
* are therefore overridden with the active wallet chain; leaving Relay's value in
|
|
116
|
+
* place makes the recovered signer disagree with the submitted one and the
|
|
117
|
+
* authorization is rejected.
|
|
118
|
+
*
|
|
119
|
+
* @param authorization - the authorization carried by the deposit
|
|
120
|
+
* @param options.signatureChainId - the chain id the connected wallet signs under
|
|
121
|
+
* @returns the payload to sign
|
|
122
|
+
*/
|
|
123
|
+
export declare const buildHyperliquidAuthorizationTypedData: (authorization: HyperliquidAuthorization, { signatureChainId }: {
|
|
124
|
+
signatureChainId: number;
|
|
125
|
+
}) => HyperliquidTypedData;
|
|
126
|
+
/** A prepared authorization submission: where to send it, and what to send. */
|
|
127
|
+
export type HyperliquidAuthorizationRequest = {
|
|
128
|
+
/**
|
|
129
|
+
* The absolute URL, INCLUDING the signature as a query parameter. Relay reads
|
|
130
|
+
* the signature from the query string, not the body — a request carrying it in
|
|
131
|
+
* the body is accepted and then fails to authorize.
|
|
132
|
+
*/
|
|
133
|
+
url: string;
|
|
134
|
+
method: string;
|
|
135
|
+
body: Record<string, unknown>;
|
|
136
|
+
};
|
|
137
|
+
/**
|
|
138
|
+
* Builds the authorization submission for a signed authorization.
|
|
139
|
+
*
|
|
140
|
+
* @param options.authorization - the authorization that was signed
|
|
141
|
+
* @param options.signature - the wallet's signature over its typed data
|
|
142
|
+
* @param options.signatureChainId - the chain id the wallet signed under, which
|
|
143
|
+
* replaces the value Relay quoted so the body agrees with the signature
|
|
144
|
+
* @param options.baseUrl - Relay's API root; the step's endpoint is relative
|
|
145
|
+
* @returns the request to perform, or null when the endpoint is not a usable path
|
|
146
|
+
*/
|
|
147
|
+
export declare const buildHyperliquidAuthorizationRequest: ({ authorization, signature, signatureChainId, baseUrl, }: {
|
|
148
|
+
authorization: HyperliquidAuthorization;
|
|
149
|
+
signature: Hex;
|
|
150
|
+
signatureChainId: number;
|
|
151
|
+
baseUrl?: string;
|
|
152
|
+
}) => HyperliquidAuthorizationRequest | null;
|