@harukit/sdk 1.0.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.
@@ -0,0 +1,405 @@
1
+ import { getAddress, } from 'viem';
2
+ import { CHAIN_NAME_TO_ID, CHAIN_ID_TO_NAME } from '@harukit/shared';
3
+ const HARU_BATCH_SPONSOR_DOMAIN_BASE = {
4
+ name: 'Haru7702BatchSponsor',
5
+ version: '1',
6
+ };
7
+ function resolveChainId(chain, defaultChain) {
8
+ const name = (chain || defaultChain || 'arbitrum').toLowerCase();
9
+ const id = CHAIN_NAME_TO_ID[name];
10
+ if (!id) {
11
+ throw new Error(`Unsupported chain: "${name}". ` +
12
+ `Supported: ${Object.keys(CHAIN_NAME_TO_ID).join(', ')}. ` +
13
+ `Set defaultChain in Haru7702 constructor to avoid specifying chain on every call.`);
14
+ }
15
+ return id;
16
+ }
17
+ function toHex(value) {
18
+ if (!value.startsWith('0x')) {
19
+ throw new Error(`Expected hex string (0x...), got: "${value.slice(0, 30)}..."`);
20
+ }
21
+ return value;
22
+ }
23
+ /**
24
+ * Haru7702 — EIP-7702 batch transaction client with gas sponsorship.
25
+ *
26
+ * @example Single-chain swap (one-shot)
27
+ * ```ts
28
+ * const haru = new Haru7702({ apiKey: '...' }); // defaultChain = 'arbitrum'
29
+ * await haru.executeSwap({ quote, wallet, signAuthorization });
30
+ * ```
31
+ *
32
+ * @example Multi-chain swap (automatic parallel execution)
33
+ * ```ts
34
+ * const haru = new Haru7702({ apiKey: '...' });
35
+ * const batches = haru.buildCalls(quote); // Map { 'arbitrum' → ChainCallBundle, 'base' → ChainCallBundle }
36
+ * await haru.executeSwap({ quote, wallet, signAuthorization }); // handles multi-chain automatically
37
+ * ```
38
+ *
39
+ * @example Transfer
40
+ * ```ts
41
+ * await haru.executeTransfer({ transfer, wallet, signAuthorization });
42
+ * ```
43
+ */
44
+ export class Haru7702 {
45
+ defaultChain;
46
+ apiBaseUrl;
47
+ apiKey;
48
+ constructor(options = {}) {
49
+ this.defaultChain = options.defaultChain || 'arbitrum';
50
+ this.apiBaseUrl = options.baseUrl || 'https://api.haruapi.com';
51
+ this.apiKey = options.apiKey || '';
52
+ }
53
+ getHeaders() {
54
+ const headers = {
55
+ 'Content-Type': 'application/json',
56
+ };
57
+ if (this.apiKey) {
58
+ headers['X-API-Key'] = this.apiKey;
59
+ }
60
+ return headers;
61
+ }
62
+ serializeWithBigInt(obj) {
63
+ return JSON.stringify(obj, (key, value) => {
64
+ if (typeof value === 'bigint') {
65
+ return value.toString();
66
+ }
67
+ return value;
68
+ });
69
+ }
70
+ async createSignRawHash(wallet) {
71
+ if (!wallet) {
72
+ throw new Error('Wallet is required');
73
+ }
74
+ const provider = await wallet.getEthereumProvider();
75
+ return async (hash) => {
76
+ const signature = await provider.request({
77
+ method: 'secp256k1_sign',
78
+ params: [hash],
79
+ });
80
+ return signature;
81
+ };
82
+ }
83
+ async signAuthorization(signAuthorization, walletAddress, chain) {
84
+ const chainId = resolveChainId(chain, this.defaultChain);
85
+ const authorization = await signAuthorization({
86
+ contractAddress: await this.getContractAddress(chainId),
87
+ chainId,
88
+ }, { address: walletAddress });
89
+ return this.serializeWithBigInt(authorization);
90
+ }
91
+ async signBatchCall(calls, nonce, deadline, sponsor, signRawHash, walletAddress, chain) {
92
+ if (calls.length === 0) {
93
+ throw new Error('Cannot sign empty batch');
94
+ }
95
+ const chainId = resolveChainId(chain, this.defaultChain);
96
+ const { keccak256, toBytes, encodeAbiParameters, encodePacked } = await import('viem');
97
+ const EXECUTE_TYPEHASH_STRING = "Execute(bytes32 callsHash,uint256 nonce,uint256 deadline,address sponsor,address executor)";
98
+ const EXECUTE_TYPEHASH = keccak256(toBytes(EXECUTE_TYPEHASH_STRING));
99
+ const CALL_TYPEHASH_STRING = "Call(address to,uint256 value,bytes data,uint256 gasLimit)";
100
+ const CALL_TYPEHASH = keccak256(toBytes(CALL_TYPEHASH_STRING));
101
+ const callHashes = calls.map(call => {
102
+ const normalizedTo = getAddress(call.to);
103
+ const normalizedValue = BigInt(call.value || '0');
104
+ const normalizedData = toHex(call.data);
105
+ const normalizedGasLimit = 0n;
106
+ return keccak256(encodeAbiParameters([
107
+ { type: 'bytes32' },
108
+ { type: 'address' },
109
+ { type: 'uint256' },
110
+ { type: 'bytes32' },
111
+ { type: 'uint256' },
112
+ ], [
113
+ CALL_TYPEHASH,
114
+ normalizedTo,
115
+ normalizedValue,
116
+ keccak256(normalizedData),
117
+ normalizedGasLimit,
118
+ ]));
119
+ });
120
+ const concatenatedHashes = toHex('0x' + callHashes.map(h => h.slice(2)).join(''));
121
+ const callsHash = keccak256(concatenatedHashes);
122
+ const normalizedSponsor = getAddress(sponsor);
123
+ const normalizedExecutor = getAddress(walletAddress);
124
+ const structHash = keccak256(encodeAbiParameters([
125
+ { type: 'bytes32' },
126
+ { type: 'bytes32' },
127
+ { type: 'uint256' },
128
+ { type: 'uint256' },
129
+ { type: 'address' },
130
+ { type: 'address' },
131
+ ], [
132
+ EXECUTE_TYPEHASH,
133
+ callsHash,
134
+ nonce,
135
+ deadline,
136
+ normalizedSponsor,
137
+ normalizedExecutor,
138
+ ]));
139
+ const domainTypeHash = keccak256(toBytes('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'));
140
+ const nameHash = keccak256(toBytes(HARU_BATCH_SPONSOR_DOMAIN_BASE.name));
141
+ const versionHash = keccak256(toBytes(HARU_BATCH_SPONSOR_DOMAIN_BASE.version));
142
+ const verifyingContractAddress = getAddress(walletAddress);
143
+ const domainSeparator = keccak256(encodeAbiParameters([
144
+ { type: 'bytes32' },
145
+ { type: 'bytes32' },
146
+ { type: 'bytes32' },
147
+ { type: 'uint256' },
148
+ { type: 'address' },
149
+ ], [
150
+ domainTypeHash,
151
+ nameHash,
152
+ versionHash,
153
+ BigInt(chainId),
154
+ verifyingContractAddress,
155
+ ]));
156
+ const fullHash = keccak256(encodePacked(['bytes1', 'bytes1', 'bytes32', 'bytes32'], ['0x19', '0x01', domainSeparator, structHash]));
157
+ return signRawHash(fullHash);
158
+ }
159
+ /**
160
+ * Build execution calls from a swap quote or transfer.
161
+ * Always returns calls grouped by chain as Map<chain, ChainCallBundle>.
162
+ * Works for both single-chain and multi-chain operations.
163
+ */
164
+ buildCalls(quote) {
165
+ const batches = new Map();
166
+ if ('txData' in quote && quote.txData && 'steps' in quote.txData) {
167
+ for (const step of quote.txData.steps) {
168
+ const chainId = step.data.chainId;
169
+ const chain = CHAIN_ID_TO_NAME[chainId] || String(chainId);
170
+ const existing = batches.get(chain);
171
+ const call = {
172
+ to: step.data.to,
173
+ value: BigInt(step.data.value || '0'),
174
+ data: step.data.data,
175
+ };
176
+ if (existing) {
177
+ existing.calls.push(call);
178
+ }
179
+ else {
180
+ batches.set(chain, { calls: [call], chain, chainId });
181
+ }
182
+ }
183
+ }
184
+ else if ('steps' in quote && quote.steps) {
185
+ for (const step of quote.steps) {
186
+ if (step.kind !== 'transaction')
187
+ continue;
188
+ const chainId = step.chainId;
189
+ const chain = CHAIN_ID_TO_NAME[chainId] || String(chainId);
190
+ const existing = batches.get(chain);
191
+ for (const item of step.items) {
192
+ const newCall = {
193
+ to: item.data.to,
194
+ value: BigInt(item.data.value || '0'),
195
+ data: item.data.data,
196
+ };
197
+ if (existing) {
198
+ existing.calls.push(newCall);
199
+ }
200
+ else {
201
+ batches.set(chain, { calls: [newCall], chain, chainId });
202
+ }
203
+ }
204
+ }
205
+ }
206
+ else if ('txData' in quote && quote.txData && 'chainId' in quote.txData) {
207
+ const txData = quote.txData;
208
+ const chainId = txData.chainId;
209
+ const chain = CHAIN_ID_TO_NAME[chainId] || String(chainId);
210
+ batches.set(chain, {
211
+ calls: [{
212
+ to: txData.to,
213
+ value: BigInt(txData.value || '0'),
214
+ data: toHex(txData.data),
215
+ }],
216
+ chain,
217
+ chainId,
218
+ });
219
+ }
220
+ else {
221
+ throw new Error('Quote/transfer has no transaction data');
222
+ }
223
+ return batches;
224
+ }
225
+ /**
226
+ * Execute a swap in one call. Handles multi-chain automatically.
227
+ * Returns immediately with transaction hashes (does not wait for confirmation).
228
+ */
229
+ async executeSwap(params) {
230
+ const { quote, wallet, signAuthorization, deadline = BigInt(Math.floor(Date.now() / 1000) + 3600) } = params;
231
+ const batches = this.buildCalls(quote);
232
+ const results = new Map();
233
+ await Promise.all(Array.from(batches.entries()).map(async ([chain, bundle]) => {
234
+ const [authorization, signRawHash] = await Promise.all([
235
+ this.signAuthorization(signAuthorization, wallet.address, chain),
236
+ this.createSignRawHash(wallet),
237
+ ]);
238
+ const [nonce, sponsorAddress] = await Promise.all([
239
+ this.getNonce(wallet.address, chain),
240
+ this.getSponsorAddress(),
241
+ ]);
242
+ const batchSignature = await this.signBatchCall(bundle.calls, nonce, deadline, sponsorAddress, signRawHash, wallet.address, chain);
243
+ const result = await this.sponsorTx({ calls: bundle.calls, signature: batchSignature, nonce, deadline }, authorization, wallet.address, chain);
244
+ results.set(chain, result);
245
+ }));
246
+ return results;
247
+ }
248
+ /**
249
+ * Execute a transfer in one call.
250
+ * Returns immediately with transaction hash (does not wait for confirmation).
251
+ */
252
+ async executeTransfer(params) {
253
+ const { transfer, wallet, signAuthorization, deadline = BigInt(Math.floor(Date.now() / 1000) + 3600) } = params;
254
+ const batches = this.buildCalls(transfer);
255
+ const results = new Map();
256
+ await Promise.all(Array.from(batches.entries()).map(async ([chain, bundle]) => {
257
+ const [authorization, signRawHash] = await Promise.all([
258
+ this.signAuthorization(signAuthorization, wallet.address, chain),
259
+ this.createSignRawHash(wallet),
260
+ ]);
261
+ const [nonce, sponsorAddress] = await Promise.all([
262
+ this.getNonce(wallet.address, chain),
263
+ this.getSponsorAddress(),
264
+ ]);
265
+ const batchSignature = await this.signBatchCall(bundle.calls, nonce, deadline, sponsorAddress, signRawHash, wallet.address, chain);
266
+ const result = await this.sponsorTx({ calls: bundle.calls, signature: batchSignature, nonce, deadline }, authorization, wallet.address, chain);
267
+ results.set(chain, result);
268
+ }));
269
+ return results;
270
+ }
271
+ /**
272
+ * Execute a pre-built bundle (from buildCalls) in one call.
273
+ * Useful when you've combined multiple quotes into a single bundle.
274
+ * Returns immediately with transaction hash (does not wait for confirmation).
275
+ */
276
+ async executeBatch(params) {
277
+ const { bundle, wallet, signAuthorization, deadline = BigInt(Math.floor(Date.now() / 1000) + 3600) } = params;
278
+ const results = new Map();
279
+ const [authorization, signRawHash] = await Promise.all([
280
+ this.signAuthorization(signAuthorization, wallet.address, bundle.chain),
281
+ this.createSignRawHash(wallet),
282
+ ]);
283
+ const [nonce, sponsorAddress] = await Promise.all([
284
+ this.getNonce(wallet.address, bundle.chain),
285
+ this.getSponsorAddress(),
286
+ ]);
287
+ const batchSignature = await this.signBatchCall(bundle.calls, nonce, deadline, sponsorAddress, signRawHash, wallet.address, bundle.chain);
288
+ const result = await this.sponsorTx({ calls: bundle.calls, signature: batchSignature, nonce, deadline }, authorization, wallet.address, bundle.chain);
289
+ results.set(bundle.chain, result);
290
+ return results;
291
+ }
292
+ /**
293
+ * Get the contract address for a specific chain.
294
+ * Fetches from the dedicated contract-address endpoint.
295
+ */
296
+ async getContractAddress(chainId) {
297
+ const response = await fetch(`${this.apiBaseUrl}/v1/relay/contract-address?chainId=${chainId}`, { headers: this.getHeaders() });
298
+ if (!response.ok) {
299
+ const body = await response.text().catch(() => '');
300
+ throw new Error(`Failed to get contract address for chain ${chainId}: ${response.status} ${body}`);
301
+ }
302
+ const data = await response.json();
303
+ return getAddress(data.address);
304
+ }
305
+ async getSponsorAddress() {
306
+ const response = await fetch(`${this.apiBaseUrl}/v1/relay/sponsor`, {
307
+ headers: this.getHeaders(),
308
+ });
309
+ if (!response.ok) {
310
+ const body = await response.text().catch(() => '');
311
+ throw new Error(`Failed to get sponsor address: ${response.status} ${body}`);
312
+ }
313
+ const data = await response.json();
314
+ return getAddress(data.sponsorAddress);
315
+ }
316
+ async getNonce(userAddress, chain) {
317
+ const chainId = resolveChainId(chain, this.defaultChain);
318
+ const metadata = await this.getNonceMetadata(userAddress, chainId);
319
+ return BigInt(metadata.nonce);
320
+ }
321
+ async getNonceMetadata(userAddress, chainId) {
322
+ const id = chainId ?? resolveChainId(undefined, this.defaultChain);
323
+ const response = await fetch(`${this.apiBaseUrl}/v1/relay/nonce/${userAddress}?chainId=${id}`, {
324
+ headers: this.getHeaders(),
325
+ });
326
+ if (!response.ok) {
327
+ const body = await response.text().catch(() => '');
328
+ throw new Error(`Failed to get nonce metadata: ${response.status} ${body}`);
329
+ }
330
+ return response.json();
331
+ }
332
+ async simulateTx(authorization, signedBatch, userEOA, chain) {
333
+ const chainId = resolveChainId(chain, this.defaultChain);
334
+ const response = await fetch(`${this.apiBaseUrl}/v1/relay/simulate`, {
335
+ method: 'POST',
336
+ headers: this.getHeaders(),
337
+ body: JSON.stringify({
338
+ userEOA,
339
+ authorization,
340
+ calls: signedBatch.calls.map((c) => ({
341
+ to: c.to,
342
+ value: c.value.toString(),
343
+ data: c.data,
344
+ })),
345
+ batchSignature: signedBatch.signature,
346
+ nonce: signedBatch.nonce.toString(),
347
+ deadline: signedBatch.deadline.toString(),
348
+ chainId,
349
+ }),
350
+ });
351
+ if (!response.ok) {
352
+ const body = await response.text().catch(() => '');
353
+ throw new Error(`Simulation failed: ${response.status} ${body}`);
354
+ }
355
+ return response.json();
356
+ }
357
+ async sponsorTx(signedBatch, authorization, userEOA, chain) {
358
+ const chainId = resolveChainId(chain, this.defaultChain);
359
+ const response = await fetch(`${this.apiBaseUrl}/v1/relay/execute`, {
360
+ method: 'POST',
361
+ headers: this.getHeaders(),
362
+ body: JSON.stringify({
363
+ userEOA,
364
+ authorization,
365
+ calls: signedBatch.calls.map((c) => ({
366
+ to: c.to,
367
+ value: c.value.toString(),
368
+ data: c.data,
369
+ })),
370
+ batchSignature: signedBatch.signature,
371
+ nonce: signedBatch.nonce.toString(),
372
+ deadline: signedBatch.deadline.toString(),
373
+ chainId,
374
+ }),
375
+ });
376
+ if (!response.ok) {
377
+ const body = await response.text().catch(() => '');
378
+ throw new Error(`Failed to sponsor transaction: ${response.status} ${body}`);
379
+ }
380
+ return response.json();
381
+ }
382
+ async waitForTx(txHash, chain) {
383
+ const maxAttempts = 30;
384
+ const delayMs = 2000;
385
+ for (let i = 0; i < maxAttempts; i++) {
386
+ const status = await this.getTxStatus(txHash, chain);
387
+ if (status.status === 'confirmed' || status.status === 'failed') {
388
+ return status;
389
+ }
390
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
391
+ }
392
+ return { status: 'pending' };
393
+ }
394
+ async getTxStatus(txHash, chain) {
395
+ const chainId = resolveChainId(chain, this.defaultChain);
396
+ const response = await fetch(`${this.apiBaseUrl}/v1/relay/transactions/${txHash}/status?chainId=${chainId}`, {
397
+ headers: this.getHeaders(),
398
+ });
399
+ if (!response.ok) {
400
+ const body = await response.text().catch(() => '');
401
+ throw new Error(`Failed to get transaction status: ${response.status} ${body}`);
402
+ }
403
+ return response.json();
404
+ }
405
+ }
@@ -0,0 +1,56 @@
1
+ import type { Config, BaseHaruOptions } from '@harukit/types';
2
+ import { TokensClient } from './clients/tokens';
3
+ import { BalancesClient } from './clients/balances';
4
+ import { SwapsClient } from './clients/swaps';
5
+ import { TransfersClient } from './clients/transfers';
6
+ import { RelayClient } from './clients/relay';
7
+ export interface HaruOptions extends BaseHaruOptions {
8
+ apiKey: string;
9
+ }
10
+ /**
11
+ * Haru SDK v1 - Namespaced Client
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * const haru = new Haru({
16
+ * apiKey: 'haru_live_demo123',
17
+ * config: { chains: ['arbitrum'] },
18
+ * });
19
+ *
20
+ * // Tokens
21
+ * const tokens = await haru.tokens.search('USDC');
22
+ *
23
+ * // Balances
24
+ * const balances = await haru.balances.get('0x...');
25
+ *
26
+ * // Swaps
27
+ * const quote = await haru.swaps.getQuoteByUsd({
28
+ * userAddress: '0x...',
29
+ * fromSymbol: 'USDC',
30
+ * toSymbol: 'WETH',
31
+ * usdValue: '1000',
32
+ * });
33
+ *
34
+ * // Build transaction calls
35
+ * const calls = haru.swaps.buildCalls(quote);
36
+ * ```
37
+ */
38
+ export declare class Haru {
39
+ readonly tokens: TokensClient;
40
+ readonly balances: BalancesClient;
41
+ readonly swaps: SwapsClient;
42
+ readonly transfers: TransfersClient;
43
+ readonly relay: RelayClient;
44
+ constructor(options: HaruOptions);
45
+ setConfig(config: Config): void;
46
+ /**
47
+ * Get current config
48
+ */
49
+ getConfig(): Config;
50
+ }
51
+ export * from './clients/tokens';
52
+ export * from './clients/balances';
53
+ export * from './clients/swaps';
54
+ export * from './clients/transfers';
55
+ export * from './clients/relay';
56
+ //# sourceMappingURL=haru-v1.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"haru-v1.d.ts","sourceRoot":"","sources":["../src/haru-v1.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE9C,MAAM,WAAW,WAAY,SAAQ,eAAe;IAClD,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,qBAAa,IAAI;IACf,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;gBAEhB,OAAO,EAAE,WAAW;IAehC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAQ/B;;OAEG;IACH,SAAS,IAAI,MAAM;CAGpB;AAED,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC"}
@@ -0,0 +1,71 @@
1
+ import { TokensClient } from './clients/tokens';
2
+ import { BalancesClient } from './clients/balances';
3
+ import { SwapsClient } from './clients/swaps';
4
+ import { TransfersClient } from './clients/transfers';
5
+ import { RelayClient } from './clients/relay';
6
+ /**
7
+ * Haru SDK v1 - Namespaced Client
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * const haru = new Haru({
12
+ * apiKey: 'haru_live_demo123',
13
+ * config: { chains: ['arbitrum'] },
14
+ * });
15
+ *
16
+ * // Tokens
17
+ * const tokens = await haru.tokens.search('USDC');
18
+ *
19
+ * // Balances
20
+ * const balances = await haru.balances.get('0x...');
21
+ *
22
+ * // Swaps
23
+ * const quote = await haru.swaps.getQuoteByUsd({
24
+ * userAddress: '0x...',
25
+ * fromSymbol: 'USDC',
26
+ * toSymbol: 'WETH',
27
+ * usdValue: '1000',
28
+ * });
29
+ *
30
+ * // Build transaction calls
31
+ * const calls = haru.swaps.buildCalls(quote);
32
+ * ```
33
+ */
34
+ export class Haru {
35
+ tokens;
36
+ balances;
37
+ swaps;
38
+ transfers;
39
+ relay;
40
+ constructor(options) {
41
+ const baseUrl = options.baseUrl || 'https://api.haruapi.com';
42
+ const clientOptions = {
43
+ apiKey: options.apiKey,
44
+ baseUrl,
45
+ config: options.config,
46
+ };
47
+ this.tokens = new TokensClient(clientOptions);
48
+ this.balances = new BalancesClient(clientOptions);
49
+ this.swaps = new SwapsClient(clientOptions);
50
+ this.transfers = new TransfersClient(clientOptions);
51
+ this.relay = new RelayClient(clientOptions);
52
+ }
53
+ setConfig(config) {
54
+ this.tokens.setConfig(config);
55
+ this.balances.setConfig(config);
56
+ this.swaps.setConfig(config);
57
+ this.transfers.setConfig(config);
58
+ this.relay.setConfig(config);
59
+ }
60
+ /**
61
+ * Get current config
62
+ */
63
+ getConfig() {
64
+ return this.tokens.getConfig();
65
+ }
66
+ }
67
+ export * from './clients/tokens';
68
+ export * from './clients/balances';
69
+ export * from './clients/swaps';
70
+ export * from './clients/transfers';
71
+ export * from './clients/relay';
@@ -0,0 +1,8 @@
1
+ export { Haru7702 } from './haru-7702';
2
+ export type { Haru7702Options, ChainCallBundle } from '@harukit/types';
3
+ export { Haru, type HaruOptions } from './haru-v1';
4
+ export { BalancesClient } from './clients/balances';
5
+ export { SwapsClient, type SwapByUsdParams, type SwapByAmountParams } from './clients/swaps';
6
+ export { TransfersClient, type TransferByUsdParams, type TransferByAmountParams } from './clients/transfers';
7
+ export type { Config, HydratedToken, CategorizedBalanceResult, CleanSwapQuote, CleanTransfer, } from '@harukit/types';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGvE,OAAO,EAAE,IAAI,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,KAAK,eAAe,EAAE,KAAK,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC7F,OAAO,EAAE,eAAe,EAAE,KAAK,mBAAmB,EAAE,KAAK,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAG7G,YAAY,EACV,MAAM,EACN,aAAa,EACb,wBAAwB,EACxB,cAAc,EACd,aAAa,GACd,MAAM,gBAAgB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ // v1 SDK - Namespaced client with EIP-7702 batch transactions
2
+ export { Haru7702 } from './haru-7702';
3
+ // v1 SDK - Namespaced client for swaps, transfers, and balances
4
+ export { Haru } from './haru-v1';
5
+ export { BalancesClient } from './clients/balances';
6
+ export { SwapsClient } from './clients/swaps';
7
+ export { TransfersClient } from './clients/transfers';
@@ -0,0 +1,4 @@
1
+ import type { SwapQuoteStep, EIP7702Call, PrivyCall } from '@harukit/types';
2
+ export declare function extractCallsFromSteps(steps: SwapQuoteStep[]): EIP7702Call[];
3
+ export declare function extractPrivyCalls(steps: SwapQuoteStep[]): PrivyCall[];
4
+ //# sourceMappingURL=callBuilder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"callBuilder.d.ts","sourceRoot":"","sources":["../../src/utils/callBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE5E,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,WAAW,EAAE,CAS3E;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,SAAS,EAAE,CASrE"}
@@ -0,0 +1,20 @@
1
+ export function extractCallsFromSteps(steps) {
2
+ if (!steps || steps.length === 0) {
3
+ return [];
4
+ }
5
+ return steps.map((step) => ({
6
+ to: step.data.to,
7
+ value: BigInt(step.data.value || '0'),
8
+ data: step.data.data,
9
+ }));
10
+ }
11
+ export function extractPrivyCalls(steps) {
12
+ if (!steps || steps.length === 0) {
13
+ return [];
14
+ }
15
+ return steps.map((step) => ({
16
+ to: step.data.to,
17
+ data: step.data.data,
18
+ value: BigInt(step.data.value || '0'),
19
+ }));
20
+ }
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "@harukit/sdk",
3
+ "version": "1.0.0",
4
+ "description": "Haru SDK for chain abstraction",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "default": "./dist/index.js"
12
+ }
13
+ },
14
+ "scripts": {
15
+ "build": "tsc",
16
+ "typecheck": "tsc --noEmit",
17
+ "test": "bun test",
18
+ "clean": "rm -rf dist",
19
+ "prepublishOnly": "bun run build"
20
+ },
21
+ "files": ["dist"],
22
+ "dependencies": {
23
+ "@harukit/types": "workspace:*",
24
+ "@harukit/shared": "workspace:*",
25
+ "viem": "^2.0.0"
26
+ },
27
+ "devDependencies": {
28
+ "typescript": "^5.4.0"
29
+ }
30
+ }