@riftresearch/sdk 0.2.2 → 0.2.4
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 +6 -20
- package/dist/index.d.ts +9 -0
- package/dist/index.js +58 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,19 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
SDK for swapping between Bitcoin and EVM chains.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Quickstart
|
|
6
|
+
|
|
7
|
+
Install the SDK:
|
|
6
8
|
|
|
7
9
|
```bash
|
|
8
10
|
npm install @riftresearch/sdk
|
|
9
|
-
# or
|
|
10
|
-
pnpm add @riftresearch/sdk
|
|
11
|
-
# or
|
|
12
|
-
yarn add @riftresearch/sdk
|
|
13
|
-
# or
|
|
14
|
-
bun add @riftresearch/sdk
|
|
15
11
|
```
|
|
16
12
|
|
|
17
|
-
|
|
13
|
+
Then use it:
|
|
18
14
|
|
|
19
15
|
```ts
|
|
20
16
|
import { RiftSdk, BTC, type Currency } from '@riftresearch/sdk'
|
|
@@ -46,8 +42,8 @@ const sdk = new RiftSdk({
|
|
|
46
42
|
publicClient,
|
|
47
43
|
walletClient,
|
|
48
44
|
sendBitcoin: async ({ recipient, amountSats }) => {
|
|
49
|
-
//
|
|
50
|
-
|
|
45
|
+
// Implement your Bitcoin wallet connection, e.g.:
|
|
46
|
+
// window.bitcoin.transfer({ recipient, amountSats })
|
|
51
47
|
},
|
|
52
48
|
})
|
|
53
49
|
|
|
@@ -71,13 +67,3 @@ console.log(`Swap ID: ${swap.swapId}`) // API order ID
|
|
|
71
67
|
const status = await sdk.getOrderStatus(swap.swapId)
|
|
72
68
|
console.log(`Status: ${status.status}`)
|
|
73
69
|
```
|
|
74
|
-
|
|
75
|
-
## Build & Publish
|
|
76
|
-
|
|
77
|
-
The SDK uses **bunup**.
|
|
78
|
-
|
|
79
|
-
- Build: `bun run --filter '@riftresearch/sdk' build`
|
|
80
|
-
- Publish (from repo root): `bun run publish:sdk`
|
|
81
|
-
- Release (version bump + build + publish): `bun run release:sdk`
|
|
82
|
-
|
|
83
|
-
The `dist/` directory is what gets published to npm.
|
package/dist/index.d.ts
CHANGED
|
@@ -412,12 +412,18 @@ interface RiftSdkOptions {
|
|
|
412
412
|
sendBitcoin: SendBitcoinFn;
|
|
413
413
|
/** Rift API URL. Defaults to production API */
|
|
414
414
|
apiUrl?: string;
|
|
415
|
+
/** Optional preflight checks before executing swaps */
|
|
416
|
+
preflight?: {
|
|
417
|
+
/** Check sender balance before executing EVM steps (default: true) */
|
|
418
|
+
checkBalances?: boolean;
|
|
419
|
+
};
|
|
415
420
|
}
|
|
416
421
|
declare class RiftSdk {
|
|
417
422
|
private riftClient;
|
|
418
423
|
private publicClient;
|
|
419
424
|
private walletClient;
|
|
420
425
|
private sendBitcoinFn;
|
|
426
|
+
private preflightCheckBalances;
|
|
421
427
|
constructor(options: RiftSdkOptions);
|
|
422
428
|
/**
|
|
423
429
|
* Get a quote for a swap and return a function to execute it.
|
|
@@ -451,8 +457,11 @@ declare class RiftSdk {
|
|
|
451
457
|
private executeBtcTransferStep;
|
|
452
458
|
private buildQuoteResult;
|
|
453
459
|
private buildOrderResult;
|
|
460
|
+
private assertSufficientBalance;
|
|
454
461
|
private getAddress;
|
|
455
462
|
private getRefundAddress;
|
|
463
|
+
private assertEvmChainMatch;
|
|
464
|
+
private assertEvmChainMatchForSteps;
|
|
456
465
|
/**
|
|
457
466
|
* Get the current status of an order by its ID.
|
|
458
467
|
*/
|
package/dist/index.js
CHANGED
|
@@ -157,6 +157,7 @@ class RiftSdk {
|
|
|
157
157
|
publicClient;
|
|
158
158
|
walletClient;
|
|
159
159
|
sendBitcoinFn;
|
|
160
|
+
preflightCheckBalances;
|
|
160
161
|
constructor(options) {
|
|
161
162
|
this.riftClient = new SwapRouterClient({
|
|
162
163
|
baseUrl: options.apiUrl ?? "https://router-api-v2-production.up.railway.app"
|
|
@@ -164,6 +165,7 @@ class RiftSdk {
|
|
|
164
165
|
this.publicClient = options.publicClient;
|
|
165
166
|
this.walletClient = options.walletClient;
|
|
166
167
|
this.sendBitcoinFn = options.sendBitcoin;
|
|
168
|
+
this.preflightCheckBalances = options.preflight?.checkBalances !== false;
|
|
167
169
|
}
|
|
168
170
|
async getQuote(params) {
|
|
169
171
|
const route = detectRoute(params.from, params.to);
|
|
@@ -181,12 +183,16 @@ class RiftSdk {
|
|
|
181
183
|
quote,
|
|
182
184
|
executeSwap: async () => {
|
|
183
185
|
const refundAddress = params.refundAddress ?? this.getRefundAddress(params);
|
|
186
|
+
if (this.preflightCheckBalances) {
|
|
187
|
+
await this.assertSufficientBalance(params.from, quote.from.amount);
|
|
188
|
+
}
|
|
184
189
|
const orderResponse = await this.riftClient.createOrder({
|
|
185
190
|
id: riftQuote.id,
|
|
186
191
|
destinationAddress: params.destinationAddress,
|
|
187
192
|
refundAddress,
|
|
188
193
|
approvalMode: params.approvalMode
|
|
189
194
|
});
|
|
195
|
+
this.assertEvmChainMatchForSteps(orderResponse.executionSteps);
|
|
190
196
|
for (const step of orderResponse.executionSteps) {
|
|
191
197
|
const result = await this.executeStep(step);
|
|
192
198
|
if (isMonochain && step.action === "evm_call" && step.kind === "oneinch_swap" && result.txHash) {
|
|
@@ -277,6 +283,29 @@ class RiftSdk {
|
|
|
277
283
|
rift: swap
|
|
278
284
|
};
|
|
279
285
|
}
|
|
286
|
+
async assertSufficientBalance(currency, amount) {
|
|
287
|
+
if (currency.chain.kind !== "EVM")
|
|
288
|
+
return;
|
|
289
|
+
this.assertEvmChainMatch(currency.chain.chainId);
|
|
290
|
+
const required = BigInt(amount);
|
|
291
|
+
const owner = this.getAddress();
|
|
292
|
+
if (currency.token.kind === "NATIVE") {
|
|
293
|
+
const balance2 = await this.publicClient.getBalance({ address: owner });
|
|
294
|
+
if (balance2 < required) {
|
|
295
|
+
throw new Error(`Insufficient balance for native token. Need ${required.toString()}, have ${balance2.toString()}`);
|
|
296
|
+
}
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
const balance = await this.publicClient.readContract({
|
|
300
|
+
address: currency.token.address,
|
|
301
|
+
abi: erc20Abi,
|
|
302
|
+
functionName: "balanceOf",
|
|
303
|
+
args: [owner]
|
|
304
|
+
});
|
|
305
|
+
if (balance < required) {
|
|
306
|
+
throw new Error(`Insufficient balance for token ${currency.token.address}. Need ${required.toString()}, have ${balance.toString()}`);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
280
309
|
getAddress() {
|
|
281
310
|
const account = this.walletClient.account;
|
|
282
311
|
if (!account) {
|
|
@@ -290,6 +319,35 @@ class RiftSdk {
|
|
|
290
319
|
}
|
|
291
320
|
return this.getAddress();
|
|
292
321
|
}
|
|
322
|
+
assertEvmChainMatch(expectedChainId) {
|
|
323
|
+
const walletChainId = this.walletClient.chain?.id;
|
|
324
|
+
if (!walletChainId) {
|
|
325
|
+
throw new Error("Wallet client is missing an EVM chain configuration");
|
|
326
|
+
}
|
|
327
|
+
if (walletChainId !== expectedChainId) {
|
|
328
|
+
throw new Error(`Wallet client chain mismatch. Expected ${expectedChainId}, got ${walletChainId}`);
|
|
329
|
+
}
|
|
330
|
+
const publicChainId = this.publicClient.chain?.id;
|
|
331
|
+
if (!publicChainId) {
|
|
332
|
+
throw new Error("Public client is missing an EVM chain configuration");
|
|
333
|
+
}
|
|
334
|
+
if (publicChainId !== expectedChainId) {
|
|
335
|
+
throw new Error(`Public client chain mismatch. Expected ${expectedChainId}, got ${publicChainId}`);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
assertEvmChainMatchForSteps(steps) {
|
|
339
|
+
const evmSteps = steps.filter((step) => step.action === "evm_call");
|
|
340
|
+
const firstStep = evmSteps[0];
|
|
341
|
+
if (!firstStep)
|
|
342
|
+
return;
|
|
343
|
+
const expectedChainId = firstStep.chainId;
|
|
344
|
+
for (const step of evmSteps) {
|
|
345
|
+
if (step.chainId !== expectedChainId) {
|
|
346
|
+
throw new Error(`Mixed EVM chain IDs in execution steps. Expected ${expectedChainId}, got ${step.chainId}`);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
this.assertEvmChainMatch(expectedChainId);
|
|
350
|
+
}
|
|
293
351
|
async getOrderStatus(orderId) {
|
|
294
352
|
return this.riftClient.getOrder(orderId);
|
|
295
353
|
}
|