@riftresearch/sdk 0.11.0 → 0.12.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/dist/index.d.ts +35 -4
- package/dist/index.js +193 -7
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -143,11 +143,12 @@ interface ErrorResponse {
|
|
|
143
143
|
/**
|
|
144
144
|
* Execution actions - the mechanism by which a step is executed.
|
|
145
145
|
*/
|
|
146
|
-
type ExecutionAction = "evm_call" | "btc_transfer";
|
|
146
|
+
type ExecutionAction = "evm_call" | "eip712_sign" | "btc_transfer";
|
|
147
147
|
/**
|
|
148
148
|
* Step kinds grouped by action type.
|
|
149
149
|
*/
|
|
150
|
-
type EvmCallKind = "approval" | "transfer_erc20" | "dex_swap";
|
|
150
|
+
type EvmCallKind = "approval" | "transfer_erc20" | "dex_swap" | "cowswap_eth_order";
|
|
151
|
+
type Eip712SignKind = "cowswap_erc20_order";
|
|
151
152
|
type BtcTransferKind = "transfer_btc";
|
|
152
153
|
/**
|
|
153
154
|
* EVM Call step - execute calldata on an EVM chain.
|
|
@@ -178,6 +179,33 @@ interface EvmCallStep {
|
|
|
178
179
|
venue?: string;
|
|
179
180
|
}
|
|
180
181
|
/**
|
|
182
|
+
* CowSwap order payload signed by the user via EIP-712.
|
|
183
|
+
*/
|
|
184
|
+
interface CowSwapOrderToSign {
|
|
185
|
+
sellToken: string;
|
|
186
|
+
buyToken: string;
|
|
187
|
+
receiver: string;
|
|
188
|
+
sellAmount: U256;
|
|
189
|
+
buyAmount: U256;
|
|
190
|
+
validTo: number;
|
|
191
|
+
appData: string;
|
|
192
|
+
feeAmount: U256;
|
|
193
|
+
kind: "sell" | "buy";
|
|
194
|
+
partiallyFillable: boolean;
|
|
195
|
+
sellTokenBalance: "erc20" | "internal" | "external";
|
|
196
|
+
buyTokenBalance: "erc20" | "internal";
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* EIP-712 sign step - sign and submit an off-chain order.
|
|
200
|
+
*/
|
|
201
|
+
interface Eip712SignStep {
|
|
202
|
+
id: string;
|
|
203
|
+
action: "eip712_sign";
|
|
204
|
+
kind: Eip712SignKind;
|
|
205
|
+
chainId: number;
|
|
206
|
+
orderToSign: CowSwapOrderToSign;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
181
209
|
* BTC Transfer step - send Bitcoin to an address.
|
|
182
210
|
* Used for: depositing BTC to Rift vault.
|
|
183
211
|
*/
|
|
@@ -197,7 +225,7 @@ interface BtcTransferStep {
|
|
|
197
225
|
* Discriminated union of all execution step types.
|
|
198
226
|
* Discriminate on `action` for execution logic, or `kind` for specific handling.
|
|
199
227
|
*/
|
|
200
|
-
type ExecutionStep = EvmCallStep | BtcTransferStep;
|
|
228
|
+
type ExecutionStep = EvmCallStep | Eip712SignStep | BtcTransferStep;
|
|
201
229
|
/**
|
|
202
230
|
* Swap response with execution steps that the client must execute.
|
|
203
231
|
*/
|
|
@@ -375,7 +403,7 @@ type SendBitcoinFn = (params: {
|
|
|
375
403
|
/** Amount to send in satoshis */
|
|
376
404
|
amountSats: string;
|
|
377
405
|
}) => Promise<void>;
|
|
378
|
-
type ExecuteSwapStepType = "approval" | "transaction";
|
|
406
|
+
type ExecuteSwapStepType = "approval" | "transaction" | "signature";
|
|
379
407
|
type ExecuteSwapOnExecuteStepCallback = (type: ExecuteSwapStepType) => void | Promise<void>;
|
|
380
408
|
type ExecuteSwapContext<chain extends Chain2 | undefined = Chain2 | undefined> = {
|
|
381
409
|
/** Viem PublicClient for reading chain data */
|
|
@@ -448,6 +476,7 @@ declare class RiftSdk {
|
|
|
448
476
|
* Handles: approval, transfer_evm, dex_swap
|
|
449
477
|
*/
|
|
450
478
|
private executeEvmCallStep;
|
|
479
|
+
private executeEip712SignStep;
|
|
451
480
|
/**
|
|
452
481
|
* Execute a BTC transfer step - send BTC to the vault address.
|
|
453
482
|
*/
|
|
@@ -456,6 +485,8 @@ declare class RiftSdk {
|
|
|
456
485
|
private buildSwapResult;
|
|
457
486
|
private buildDexSwapRevertMessage;
|
|
458
487
|
private resolveDexVenueLabel;
|
|
488
|
+
private shouldReportStepResult;
|
|
489
|
+
private getCowSwapApiBase;
|
|
459
490
|
private assertSufficientBalance;
|
|
460
491
|
private getAddress;
|
|
461
492
|
private getRefundAddress;
|
package/dist/index.js
CHANGED
|
@@ -156,14 +156,97 @@ function getSupportedModes(from, to) {
|
|
|
156
156
|
import { erc20Abi } from "viem";
|
|
157
157
|
|
|
158
158
|
// src/client.ts
|
|
159
|
-
|
|
159
|
+
async function request(baseUrl, path, init) {
|
|
160
|
+
try {
|
|
161
|
+
const response = await fetch(`${baseUrl}${path}`, init);
|
|
162
|
+
const status = response.status;
|
|
163
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
164
|
+
let value = null;
|
|
165
|
+
if (status !== 204) {
|
|
166
|
+
if (contentType.includes("application/json")) {
|
|
167
|
+
try {
|
|
168
|
+
value = await response.json();
|
|
169
|
+
} catch {
|
|
170
|
+
value = null;
|
|
171
|
+
}
|
|
172
|
+
} else {
|
|
173
|
+
const text = await response.text();
|
|
174
|
+
value = text.length > 0 ? text : null;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
if (response.ok) {
|
|
178
|
+
return {
|
|
179
|
+
data: value,
|
|
180
|
+
error: null,
|
|
181
|
+
status
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
const message = value && typeof value === "object" && "error" in value && typeof value.error === "string" ? value.error : typeof value === "string" && value.length > 0 ? value : `Request failed with status ${status}`;
|
|
185
|
+
return {
|
|
186
|
+
data: null,
|
|
187
|
+
error: {
|
|
188
|
+
status,
|
|
189
|
+
value,
|
|
190
|
+
message
|
|
191
|
+
},
|
|
192
|
+
status
|
|
193
|
+
};
|
|
194
|
+
} catch (error) {
|
|
195
|
+
return {
|
|
196
|
+
data: null,
|
|
197
|
+
error: {
|
|
198
|
+
status: 0,
|
|
199
|
+
message: error instanceof Error ? error.message : String(error)
|
|
200
|
+
},
|
|
201
|
+
status: 0
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
function get(baseUrl, path) {
|
|
206
|
+
return request(baseUrl, path, {
|
|
207
|
+
method: "GET",
|
|
208
|
+
headers: {
|
|
209
|
+
accept: "application/json"
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
function postJson(baseUrl, path, body) {
|
|
214
|
+
return request(baseUrl, path, {
|
|
215
|
+
method: "POST",
|
|
216
|
+
headers: {
|
|
217
|
+
accept: "application/json",
|
|
218
|
+
"content-type": "application/json"
|
|
219
|
+
},
|
|
220
|
+
body: JSON.stringify(body)
|
|
221
|
+
});
|
|
222
|
+
}
|
|
160
223
|
function createClient(baseUrl) {
|
|
161
|
-
|
|
224
|
+
const normalizedBaseUrl = baseUrl.replace(/\/$/, "");
|
|
225
|
+
const swap = (params) => {
|
|
226
|
+
const swapId = encodeURIComponent(params.swapId);
|
|
227
|
+
return {
|
|
228
|
+
get: () => get(normalizedBaseUrl, `/swap/${swapId}`),
|
|
229
|
+
tx: {
|
|
230
|
+
post: (body) => postJson(normalizedBaseUrl, `/swap/${swapId}/tx`, body)
|
|
231
|
+
},
|
|
232
|
+
"refresh-step": {
|
|
233
|
+
post: (body) => postJson(normalizedBaseUrl, `/swap/${swapId}/refresh-step`, body)
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
};
|
|
237
|
+
swap.post = (body) => postJson(normalizedBaseUrl, "/swap", body);
|
|
238
|
+
return {
|
|
239
|
+
quote: {
|
|
240
|
+
post: (body) => postJson(normalizedBaseUrl, "/quote", body)
|
|
241
|
+
},
|
|
242
|
+
swap
|
|
243
|
+
};
|
|
162
244
|
}
|
|
163
245
|
|
|
164
246
|
// src/sdk.ts
|
|
165
247
|
var GAS_LIMIT_MULTIPLIER_NUMERATOR = 3n;
|
|
166
248
|
var GAS_LIMIT_MULTIPLIER_DENOMINATOR = 2n;
|
|
249
|
+
var GPV2_SETTLEMENT = "0x9008d19f58aabd9ed0d60971565aa8510560ab41";
|
|
167
250
|
|
|
168
251
|
class RiftSdk {
|
|
169
252
|
riftClient;
|
|
@@ -270,12 +353,13 @@ class RiftSdk {
|
|
|
270
353
|
const result = await this.executeStep(step, context, swapResponse.swapId, route);
|
|
271
354
|
this.logDebug("step completed", {
|
|
272
355
|
stepId: step.id,
|
|
273
|
-
txHash: result.txHash
|
|
356
|
+
txHash: result.txHash,
|
|
357
|
+
cowswapOrderId: result.cowswapOrderId
|
|
274
358
|
});
|
|
275
|
-
if (
|
|
359
|
+
if (this.shouldReportStepResult(step, result)) {
|
|
276
360
|
this.logDebug("reporting step result", {
|
|
277
361
|
stepId: step.id,
|
|
278
|
-
|
|
362
|
+
kind: "kind" in step ? step.kind : undefined,
|
|
279
363
|
monochain: isMonochain
|
|
280
364
|
});
|
|
281
365
|
this.unwrapEdenResult(await this.riftClient.swap({ swapId: swapResponse.swapId }).tx.post({
|
|
@@ -303,6 +387,8 @@ class RiftSdk {
|
|
|
303
387
|
switch (step.action) {
|
|
304
388
|
case "evm_call":
|
|
305
389
|
return this.executeEvmCallStep(step, context, swapId, route);
|
|
390
|
+
case "eip712_sign":
|
|
391
|
+
return this.executeEip712SignStep(step, context);
|
|
306
392
|
case "btc_transfer":
|
|
307
393
|
return this.executeBtcTransferStep(step, context);
|
|
308
394
|
}
|
|
@@ -389,7 +475,91 @@ class RiftSdk {
|
|
|
389
475
|
}
|
|
390
476
|
throw new Error(`EVM step transaction reverted (${effectiveStep.kind}) with hash ${txHash}`);
|
|
391
477
|
}
|
|
392
|
-
return { txHash };
|
|
478
|
+
return step.kind === "cowswap_eth_order" ? { txHash, cowswapOrderId: txHash } : { txHash };
|
|
479
|
+
}
|
|
480
|
+
async executeEip712SignStep(step, context) {
|
|
481
|
+
const walletClient = this.requireWalletClient(context);
|
|
482
|
+
const account = walletClient.account;
|
|
483
|
+
if (!account) {
|
|
484
|
+
throw new Error("No account configured on wallet client");
|
|
485
|
+
}
|
|
486
|
+
await context.onExecuteStep?.("signature");
|
|
487
|
+
const signature = await walletClient.signTypedData({
|
|
488
|
+
account,
|
|
489
|
+
domain: {
|
|
490
|
+
name: "Gnosis Protocol",
|
|
491
|
+
version: "v2",
|
|
492
|
+
chainId: step.chainId,
|
|
493
|
+
verifyingContract: GPV2_SETTLEMENT
|
|
494
|
+
},
|
|
495
|
+
types: {
|
|
496
|
+
Order: [
|
|
497
|
+
{ name: "sellToken", type: "address" },
|
|
498
|
+
{ name: "buyToken", type: "address" },
|
|
499
|
+
{ name: "receiver", type: "address" },
|
|
500
|
+
{ name: "sellAmount", type: "uint256" },
|
|
501
|
+
{ name: "buyAmount", type: "uint256" },
|
|
502
|
+
{ name: "validTo", type: "uint32" },
|
|
503
|
+
{ name: "appData", type: "bytes32" },
|
|
504
|
+
{ name: "feeAmount", type: "uint256" },
|
|
505
|
+
{ name: "kind", type: "string" },
|
|
506
|
+
{ name: "partiallyFillable", type: "bool" },
|
|
507
|
+
{ name: "sellTokenBalance", type: "string" },
|
|
508
|
+
{ name: "buyTokenBalance", type: "string" }
|
|
509
|
+
]
|
|
510
|
+
},
|
|
511
|
+
primaryType: "Order",
|
|
512
|
+
message: {
|
|
513
|
+
sellToken: step.orderToSign.sellToken,
|
|
514
|
+
buyToken: step.orderToSign.buyToken,
|
|
515
|
+
receiver: step.orderToSign.receiver,
|
|
516
|
+
sellAmount: BigInt(step.orderToSign.sellAmount),
|
|
517
|
+
buyAmount: BigInt(step.orderToSign.buyAmount),
|
|
518
|
+
validTo: step.orderToSign.validTo,
|
|
519
|
+
appData: step.orderToSign.appData,
|
|
520
|
+
feeAmount: BigInt(step.orderToSign.feeAmount),
|
|
521
|
+
kind: step.orderToSign.kind,
|
|
522
|
+
partiallyFillable: step.orderToSign.partiallyFillable,
|
|
523
|
+
sellTokenBalance: step.orderToSign.sellTokenBalance,
|
|
524
|
+
buyTokenBalance: step.orderToSign.buyTokenBalance
|
|
525
|
+
}
|
|
526
|
+
});
|
|
527
|
+
const apiBase = this.getCowSwapApiBase(step.chainId);
|
|
528
|
+
if (!apiBase) {
|
|
529
|
+
throw new Error(`CowSwap is not supported on chain ${step.chainId}`);
|
|
530
|
+
}
|
|
531
|
+
const response = await fetch(`${apiBase}/api/v1/orders`, {
|
|
532
|
+
method: "POST",
|
|
533
|
+
headers: { "Content-Type": "application/json" },
|
|
534
|
+
body: JSON.stringify({
|
|
535
|
+
sellToken: step.orderToSign.sellToken,
|
|
536
|
+
buyToken: step.orderToSign.buyToken,
|
|
537
|
+
receiver: step.orderToSign.receiver,
|
|
538
|
+
sellAmount: step.orderToSign.sellAmount,
|
|
539
|
+
buyAmount: step.orderToSign.buyAmount,
|
|
540
|
+
validTo: step.orderToSign.validTo,
|
|
541
|
+
appData: step.orderToSign.appData,
|
|
542
|
+
feeAmount: step.orderToSign.feeAmount,
|
|
543
|
+
kind: step.orderToSign.kind,
|
|
544
|
+
partiallyFillable: step.orderToSign.partiallyFillable,
|
|
545
|
+
sellTokenBalance: step.orderToSign.sellTokenBalance,
|
|
546
|
+
buyTokenBalance: step.orderToSign.buyTokenBalance,
|
|
547
|
+
signingScheme: "eip712",
|
|
548
|
+
signature,
|
|
549
|
+
from: account.address
|
|
550
|
+
})
|
|
551
|
+
});
|
|
552
|
+
if (!response.ok) {
|
|
553
|
+
const errorText = await response.text();
|
|
554
|
+
throw new Error(`CowSwap order submission failed: ${errorText}`);
|
|
555
|
+
}
|
|
556
|
+
const body = await response.json();
|
|
557
|
+
const uid = body && typeof body === "object" && "uid" in body ? body.uid : undefined;
|
|
558
|
+
const orderId = typeof body === "string" ? body : typeof uid === "string" ? uid : null;
|
|
559
|
+
if (!orderId) {
|
|
560
|
+
throw new Error("CowSwap order submission succeeded but returned no order id");
|
|
561
|
+
}
|
|
562
|
+
return { cowswapOrderId: orderId };
|
|
393
563
|
}
|
|
394
564
|
async executeBtcTransferStep(step, context) {
|
|
395
565
|
const sendBitcoin = this.requireSendBitcoin(context);
|
|
@@ -443,6 +613,22 @@ class RiftSdk {
|
|
|
443
613
|
const trimmed = venue.trim();
|
|
444
614
|
return trimmed.length > 0 ? trimmed : "the selected venue";
|
|
445
615
|
}
|
|
616
|
+
shouldReportStepResult(step, result) {
|
|
617
|
+
if (step.action === "eip712_sign") {
|
|
618
|
+
return Boolean(result.cowswapOrderId);
|
|
619
|
+
}
|
|
620
|
+
if (step.action === "evm_call") {
|
|
621
|
+
return (step.kind === "dex_swap" || step.kind === "cowswap_eth_order") && (Boolean(result.txHash) || Boolean(result.cowswapOrderId));
|
|
622
|
+
}
|
|
623
|
+
return false;
|
|
624
|
+
}
|
|
625
|
+
getCowSwapApiBase(chainId) {
|
|
626
|
+
if (chainId === 1)
|
|
627
|
+
return "https://api.cow.fi/mainnet";
|
|
628
|
+
if (chainId === 8453)
|
|
629
|
+
return "https://api.cow.fi/base";
|
|
630
|
+
return null;
|
|
631
|
+
}
|
|
446
632
|
async assertSufficientBalance(currency, amount, context) {
|
|
447
633
|
if (currency.chain.kind !== "EVM")
|
|
448
634
|
return;
|
|
@@ -500,7 +686,7 @@ class RiftSdk {
|
|
|
500
686
|
}
|
|
501
687
|
}
|
|
502
688
|
assertEvmChainMatchForSteps(steps, context) {
|
|
503
|
-
const evmSteps = steps.filter((step) => step.action === "evm_call");
|
|
689
|
+
const evmSteps = steps.filter((step) => step.action === "evm_call" || step.action === "eip712_sign");
|
|
504
690
|
const firstStep = evmSteps[0];
|
|
505
691
|
if (!firstStep)
|
|
506
692
|
return;
|