@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.
- package/dist/clients/balances.d.ts +12 -0
- package/dist/clients/balances.d.ts.map +1 -0
- package/dist/clients/balances.js +23 -0
- package/dist/clients/base.d.ts +16 -0
- package/dist/clients/base.d.ts.map +1 -0
- package/dist/clients/base.js +23 -0
- package/dist/clients/relay.d.ts +17 -0
- package/dist/clients/relay.d.ts.map +1 -0
- package/dist/clients/relay.js +66 -0
- package/dist/clients/swaps.d.ts +97 -0
- package/dist/clients/swaps.d.ts.map +1 -0
- package/dist/clients/swaps.js +150 -0
- package/dist/clients/tokens.d.ts +9 -0
- package/dist/clients/tokens.d.ts.map +1 -0
- package/dist/clients/tokens.js +52 -0
- package/dist/clients/transfers.d.ts +36 -0
- package/dist/clients/transfers.d.ts.map +1 -0
- package/dist/clients/transfers.js +43 -0
- package/dist/config/index.d.ts +2 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +1 -0
- package/dist/config/manager.d.ts +72 -0
- package/dist/config/manager.d.ts.map +1 -0
- package/dist/config/manager.js +221 -0
- package/dist/haru-7702.d.ts +85 -0
- package/dist/haru-7702.d.ts.map +1 -0
- package/dist/haru-7702.js +405 -0
- package/dist/haru-v1.d.ts +56 -0
- package/dist/haru-v1.d.ts.map +1 -0
- package/dist/haru-v1.js +71 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/utils/callBuilder.d.ts +4 -0
- package/dist/utils/callBuilder.d.ts.map +1 -0
- package/dist/utils/callBuilder.js +20 -0
- package/package.json +30 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { BaseClient } from './base';
|
|
2
|
+
import type { CategorizedBalanceResult, YoloBalanceResult } from '@harukit/types';
|
|
3
|
+
export declare class BalancesClient extends BaseClient {
|
|
4
|
+
get(userAddress: string): Promise<CategorizedBalanceResult>;
|
|
5
|
+
/**
|
|
6
|
+
* Get ALL token balances for a user (yolo mode).
|
|
7
|
+
* Returns every token with balance > 0, including unlisted tokens.
|
|
8
|
+
* Requires config.yoloMode = true.
|
|
9
|
+
*/
|
|
10
|
+
getAll(userAddress: string): Promise<YoloBalanceResult>;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=balances.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"balances.d.ts","sourceRoot":"","sources":["../../src/clients/balances.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,KAAK,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAElF,qBAAa,cAAe,SAAQ,UAAU;IACtC,GAAG,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,CAAC;IAajE;;;;OAIG;IACG,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;CAa9D"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { BaseClient } from './base';
|
|
2
|
+
export class BalancesClient extends BaseClient {
|
|
3
|
+
async get(userAddress) {
|
|
4
|
+
const response = await fetch(`${this.baseUrl}/v1/balances/${userAddress}`, { headers: this.getHeaders() });
|
|
5
|
+
if (!response.ok) {
|
|
6
|
+
throw new Error('Failed to fetch balances');
|
|
7
|
+
}
|
|
8
|
+
return response.json();
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Get ALL token balances for a user (yolo mode).
|
|
12
|
+
* Returns every token with balance > 0, including unlisted tokens.
|
|
13
|
+
* Requires config.yoloMode = true.
|
|
14
|
+
*/
|
|
15
|
+
async getAll(userAddress) {
|
|
16
|
+
const response = await fetch(`${this.baseUrl}/v1/balances/${userAddress}/all`, { headers: this.getHeaders() });
|
|
17
|
+
if (!response.ok) {
|
|
18
|
+
const error = await response.json().catch(() => ({ error: 'Unknown error' }));
|
|
19
|
+
throw new Error(error.error || 'Failed to fetch all balances');
|
|
20
|
+
}
|
|
21
|
+
return response.json();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Config } from '@harukit/types';
|
|
2
|
+
export interface BaseClientOptions {
|
|
3
|
+
apiKey: string;
|
|
4
|
+
baseUrl: string;
|
|
5
|
+
config: Config;
|
|
6
|
+
}
|
|
7
|
+
export declare abstract class BaseClient {
|
|
8
|
+
protected apiKey: string;
|
|
9
|
+
protected baseUrl: string;
|
|
10
|
+
protected config: Config;
|
|
11
|
+
constructor(options: BaseClientOptions);
|
|
12
|
+
protected getHeaders(): HeadersInit;
|
|
13
|
+
getConfig(): Config;
|
|
14
|
+
setConfig(config: Config): void;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=base.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/clients/base.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAE7C,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,8BAAsB,UAAU;IAC9B,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEb,OAAO,EAAE,iBAAiB;IAMtC,SAAS,CAAC,UAAU,IAAI,WAAW;IAQnC,SAAS,IAAI,MAAM;IAInB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;CAGhC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export class BaseClient {
|
|
2
|
+
apiKey;
|
|
3
|
+
baseUrl;
|
|
4
|
+
config;
|
|
5
|
+
constructor(options) {
|
|
6
|
+
this.apiKey = options.apiKey;
|
|
7
|
+
this.baseUrl = options.baseUrl.replace(/\/$/, '');
|
|
8
|
+
this.config = options.config;
|
|
9
|
+
}
|
|
10
|
+
getHeaders() {
|
|
11
|
+
return {
|
|
12
|
+
'Content-Type': 'application/json',
|
|
13
|
+
'X-API-Key': this.apiKey,
|
|
14
|
+
'X-Haru-Config': JSON.stringify(this.config),
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
getConfig() {
|
|
18
|
+
return this.config;
|
|
19
|
+
}
|
|
20
|
+
setConfig(config) {
|
|
21
|
+
this.config = config;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { BaseClient } from './base';
|
|
2
|
+
import type { SimulationResult, TxStatus } from '@harukit/types';
|
|
3
|
+
export interface RelayCall {
|
|
4
|
+
to: string;
|
|
5
|
+
data: string;
|
|
6
|
+
value?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare class RelayClient extends BaseClient {
|
|
9
|
+
getNonce(userAddress: string, chain?: string): Promise<bigint>;
|
|
10
|
+
getSponsorAddress(): Promise<string>;
|
|
11
|
+
simulate(calls: RelayCall[]): Promise<SimulationResult>;
|
|
12
|
+
execute(calls: RelayCall[]): Promise<{
|
|
13
|
+
txHash: string;
|
|
14
|
+
}>;
|
|
15
|
+
getStatus(txHash: string, chain?: string): Promise<TxStatus>;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=relay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relay.d.ts","sourceRoot":"","sources":["../../src/clients/relay.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAEpC,OAAO,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAEjE,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAaD,qBAAa,WAAY,SAAQ,UAAU;IACnC,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAc9D,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC;IAapC,QAAQ,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAcvD,OAAO,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAcxD,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;CAYnE"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { BaseClient } from './base';
|
|
2
|
+
import { CHAIN_NAME_TO_ID } from '@harukit/shared';
|
|
3
|
+
function resolveChainQueryParam(chain) {
|
|
4
|
+
if (!chain)
|
|
5
|
+
return '';
|
|
6
|
+
const id = CHAIN_NAME_TO_ID[chain.toLowerCase()];
|
|
7
|
+
if (id === undefined) {
|
|
8
|
+
throw new Error(`Unsupported chain: "${chain}". Supported: ${Object.keys(CHAIN_NAME_TO_ID).join(', ')}`);
|
|
9
|
+
}
|
|
10
|
+
return `?chainId=${id}`;
|
|
11
|
+
}
|
|
12
|
+
export class RelayClient extends BaseClient {
|
|
13
|
+
async getNonce(userAddress, chain) {
|
|
14
|
+
const query = resolveChainQueryParam(chain);
|
|
15
|
+
const response = await fetch(`${this.baseUrl}/v1/relay/nonce/${userAddress}${query}`, {
|
|
16
|
+
headers: this.getHeaders(),
|
|
17
|
+
});
|
|
18
|
+
if (!response.ok) {
|
|
19
|
+
throw new Error('Failed to get nonce');
|
|
20
|
+
}
|
|
21
|
+
const data = await response.json();
|
|
22
|
+
return BigInt(data.nonce);
|
|
23
|
+
}
|
|
24
|
+
async getSponsorAddress() {
|
|
25
|
+
const response = await fetch(`${this.baseUrl}/v1/relay/sponsor`, {
|
|
26
|
+
headers: this.getHeaders(),
|
|
27
|
+
});
|
|
28
|
+
if (!response.ok) {
|
|
29
|
+
throw new Error('Failed to get sponsor address');
|
|
30
|
+
}
|
|
31
|
+
const data = await response.json();
|
|
32
|
+
return data.sponsorAddress;
|
|
33
|
+
}
|
|
34
|
+
async simulate(calls) {
|
|
35
|
+
const response = await fetch(`${this.baseUrl}/v1/relay/simulate`, {
|
|
36
|
+
method: 'POST',
|
|
37
|
+
headers: this.getHeaders(),
|
|
38
|
+
body: JSON.stringify({ calls }),
|
|
39
|
+
});
|
|
40
|
+
if (!response.ok) {
|
|
41
|
+
throw new Error('Failed to simulate transaction');
|
|
42
|
+
}
|
|
43
|
+
return response.json();
|
|
44
|
+
}
|
|
45
|
+
async execute(calls) {
|
|
46
|
+
const response = await fetch(`${this.baseUrl}/v1/relay/execute`, {
|
|
47
|
+
method: 'POST',
|
|
48
|
+
headers: this.getHeaders(),
|
|
49
|
+
body: JSON.stringify({ calls }),
|
|
50
|
+
});
|
|
51
|
+
if (!response.ok) {
|
|
52
|
+
throw new Error('Failed to execute transaction');
|
|
53
|
+
}
|
|
54
|
+
return response.json();
|
|
55
|
+
}
|
|
56
|
+
async getStatus(txHash, chain) {
|
|
57
|
+
const query = resolveChainQueryParam(chain);
|
|
58
|
+
const response = await fetch(`${this.baseUrl}/v1/relay/transactions/${txHash}/status${query}`, {
|
|
59
|
+
headers: this.getHeaders(),
|
|
60
|
+
});
|
|
61
|
+
if (!response.ok) {
|
|
62
|
+
throw new Error('Failed to get transaction status');
|
|
63
|
+
}
|
|
64
|
+
return response.json();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { BaseClient } from './base';
|
|
2
|
+
import type { CleanSwapQuote, SwapCallList, SwapStepsLegacy, MultiInputSwapQuote } from '@harukit/types';
|
|
3
|
+
export interface SwapByUsdParams {
|
|
4
|
+
userAddress: string;
|
|
5
|
+
fromSymbol: string;
|
|
6
|
+
fromChain: string;
|
|
7
|
+
toSymbol: string;
|
|
8
|
+
toChain: string;
|
|
9
|
+
usdValue: string;
|
|
10
|
+
}
|
|
11
|
+
export interface SwapByAmountParams {
|
|
12
|
+
userAddress: string;
|
|
13
|
+
fromSymbol: string;
|
|
14
|
+
fromChain: string;
|
|
15
|
+
toSymbol: string;
|
|
16
|
+
toChain: string;
|
|
17
|
+
amount: string;
|
|
18
|
+
}
|
|
19
|
+
export interface SwapByAddressParams {
|
|
20
|
+
userAddress: string;
|
|
21
|
+
fromTokenAddress: string;
|
|
22
|
+
fromChain: string;
|
|
23
|
+
toTokenAddress: string;
|
|
24
|
+
toChain: string;
|
|
25
|
+
amount: string;
|
|
26
|
+
}
|
|
27
|
+
export interface MultiInputByUsdParams {
|
|
28
|
+
userAddress: string;
|
|
29
|
+
origins: {
|
|
30
|
+
chain: string;
|
|
31
|
+
currency: string;
|
|
32
|
+
usdValue: string;
|
|
33
|
+
}[];
|
|
34
|
+
destinationChain: string;
|
|
35
|
+
destinationCurrency: string;
|
|
36
|
+
partial?: boolean;
|
|
37
|
+
recipient?: string;
|
|
38
|
+
}
|
|
39
|
+
export interface MultiInputByAmountParams {
|
|
40
|
+
userAddress: string;
|
|
41
|
+
origins: {
|
|
42
|
+
chain: string;
|
|
43
|
+
currency: string;
|
|
44
|
+
amount: string;
|
|
45
|
+
}[];
|
|
46
|
+
destinationChain: string;
|
|
47
|
+
destinationCurrency: string;
|
|
48
|
+
partial?: boolean;
|
|
49
|
+
recipient?: string;
|
|
50
|
+
}
|
|
51
|
+
export interface MultiInputByAddressParams {
|
|
52
|
+
userAddress: string;
|
|
53
|
+
origins: {
|
|
54
|
+
chain: string;
|
|
55
|
+
tokenAddress: string;
|
|
56
|
+
amount: string;
|
|
57
|
+
}[];
|
|
58
|
+
destinationChain: string;
|
|
59
|
+
destinationTokenAddress: string;
|
|
60
|
+
partial?: boolean;
|
|
61
|
+
recipient?: string;
|
|
62
|
+
}
|
|
63
|
+
export interface Call {
|
|
64
|
+
to: string;
|
|
65
|
+
data: string;
|
|
66
|
+
value: bigint;
|
|
67
|
+
}
|
|
68
|
+
export declare class SwapsClient extends BaseClient {
|
|
69
|
+
getQuoteByUsd(params: SwapByUsdParams): Promise<CleanSwapQuote>;
|
|
70
|
+
getQuoteByAmount(params: SwapByAmountParams): Promise<CleanSwapQuote>;
|
|
71
|
+
/**
|
|
72
|
+
* YOLO MODE: Get swap quote using raw token addresses
|
|
73
|
+
* Requires yoloMode: true in config
|
|
74
|
+
*/
|
|
75
|
+
getQuoteByAddress(params: SwapByAddressParams): Promise<CleanSwapQuote>;
|
|
76
|
+
/**
|
|
77
|
+
* Multi-Input by USD - Swap from multiple origins by USD value
|
|
78
|
+
*/
|
|
79
|
+
getMultiInputByUsd(params: MultiInputByUsdParams): Promise<MultiInputSwapQuote>;
|
|
80
|
+
/**
|
|
81
|
+
* Multi-Input by Amount - Swap from multiple origins by formatted amount
|
|
82
|
+
*/
|
|
83
|
+
getMultiInputByAmount(params: MultiInputByAmountParams): Promise<MultiInputSwapQuote>;
|
|
84
|
+
/**
|
|
85
|
+
* Multi-Input by Address (YOLO) - Swap using raw token addresses
|
|
86
|
+
* Requires yoloMode: true in config
|
|
87
|
+
*/
|
|
88
|
+
getMultiInputByAddress(params: MultiInputByAddressParams): Promise<MultiInputSwapQuote>;
|
|
89
|
+
/**
|
|
90
|
+
* Build batch calls for EIP-7702 execution
|
|
91
|
+
* Groups all transactions on same chain into single batch
|
|
92
|
+
*/
|
|
93
|
+
buildMultiInputBatch(quote: MultiInputSwapQuote): Map<number, Call[]>;
|
|
94
|
+
buildCalls(quote: CleanSwapQuote): SwapCallList | null;
|
|
95
|
+
buildSteps(quote: CleanSwapQuote): SwapStepsLegacy | null;
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=swaps.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"swaps.d.ts","sourceRoot":"","sources":["../../src/clients/swaps.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { BaseClient } from './base';
|
|
2
|
+
import { extractPrivyCalls } from '../utils/callBuilder';
|
|
3
|
+
export class SwapsClient extends BaseClient {
|
|
4
|
+
async getQuoteByUsd(params) {
|
|
5
|
+
const response = await fetch(`${this.baseUrl}/v1/swaps/quote-by-usd`, {
|
|
6
|
+
method: 'POST',
|
|
7
|
+
headers: this.getHeaders(),
|
|
8
|
+
body: JSON.stringify(params),
|
|
9
|
+
});
|
|
10
|
+
if (!response.ok) {
|
|
11
|
+
const errorBody = await response.text();
|
|
12
|
+
throw new Error(`Failed to get swap quote by USD: ${response.status} ${errorBody}`);
|
|
13
|
+
}
|
|
14
|
+
return response.json();
|
|
15
|
+
}
|
|
16
|
+
async getQuoteByAmount(params) {
|
|
17
|
+
const response = await fetch(`${this.baseUrl}/v1/swaps/quote-by-amount`, {
|
|
18
|
+
method: 'POST',
|
|
19
|
+
headers: this.getHeaders(),
|
|
20
|
+
body: JSON.stringify(params),
|
|
21
|
+
});
|
|
22
|
+
if (!response.ok) {
|
|
23
|
+
const errorBody = await response.text();
|
|
24
|
+
throw new Error(`Failed to get swap quote by amount: ${response.status} ${errorBody}`);
|
|
25
|
+
}
|
|
26
|
+
return response.json();
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* YOLO MODE: Get swap quote using raw token addresses
|
|
30
|
+
* Requires yoloMode: true in config
|
|
31
|
+
*/
|
|
32
|
+
async getQuoteByAddress(params) {
|
|
33
|
+
const response = await fetch(`${this.baseUrl}/v1/swaps/quote-by-address`, {
|
|
34
|
+
method: 'POST',
|
|
35
|
+
headers: this.getHeaders(),
|
|
36
|
+
body: JSON.stringify(params),
|
|
37
|
+
});
|
|
38
|
+
if (!response.ok) {
|
|
39
|
+
const errorBody = await response.text();
|
|
40
|
+
throw new Error(`Failed to get swap quote by address: ${response.status} ${errorBody}`);
|
|
41
|
+
}
|
|
42
|
+
return response.json();
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Multi-Input by USD - Swap from multiple origins by USD value
|
|
46
|
+
*/
|
|
47
|
+
async getMultiInputByUsd(params) {
|
|
48
|
+
const response = await fetch(`${this.baseUrl}/v1/swaps/multi-input-by-usd`, {
|
|
49
|
+
method: 'POST',
|
|
50
|
+
headers: this.getHeaders(),
|
|
51
|
+
body: JSON.stringify(params),
|
|
52
|
+
});
|
|
53
|
+
if (!response.ok) {
|
|
54
|
+
const errorBody = await response.text();
|
|
55
|
+
throw new Error(`Failed to get multi-input by USD: ${response.status} ${errorBody}`);
|
|
56
|
+
}
|
|
57
|
+
return response.json();
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Multi-Input by Amount - Swap from multiple origins by formatted amount
|
|
61
|
+
*/
|
|
62
|
+
async getMultiInputByAmount(params) {
|
|
63
|
+
const response = await fetch(`${this.baseUrl}/v1/swaps/multi-input-by-amount`, {
|
|
64
|
+
method: 'POST',
|
|
65
|
+
headers: this.getHeaders(),
|
|
66
|
+
body: JSON.stringify(params),
|
|
67
|
+
});
|
|
68
|
+
if (!response.ok) {
|
|
69
|
+
const errorBody = await response.text();
|
|
70
|
+
throw new Error(`Failed to get multi-input by amount: ${response.status} ${errorBody}`);
|
|
71
|
+
}
|
|
72
|
+
return response.json();
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Multi-Input by Address (YOLO) - Swap using raw token addresses
|
|
76
|
+
* Requires yoloMode: true in config
|
|
77
|
+
*/
|
|
78
|
+
async getMultiInputByAddress(params) {
|
|
79
|
+
const response = await fetch(`${this.baseUrl}/v1/swaps/multi-input-by-address`, {
|
|
80
|
+
method: 'POST',
|
|
81
|
+
headers: this.getHeaders(),
|
|
82
|
+
body: JSON.stringify(params),
|
|
83
|
+
});
|
|
84
|
+
if (!response.ok) {
|
|
85
|
+
const errorBody = await response.text();
|
|
86
|
+
throw new Error(`Failed to get multi-input by address: ${response.status} ${errorBody}`);
|
|
87
|
+
}
|
|
88
|
+
return response.json();
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Build batch calls for EIP-7702 execution
|
|
92
|
+
* Groups all transactions on same chain into single batch
|
|
93
|
+
*/
|
|
94
|
+
buildMultiInputBatch(quote) {
|
|
95
|
+
const batches = new Map();
|
|
96
|
+
for (const step of quote.steps) {
|
|
97
|
+
if (step.kind !== 'transaction')
|
|
98
|
+
continue;
|
|
99
|
+
for (const item of step.items) {
|
|
100
|
+
const calls = batches.get(step.chainId) || [];
|
|
101
|
+
calls.push({
|
|
102
|
+
to: item.data.to,
|
|
103
|
+
data: item.data.data,
|
|
104
|
+
value: BigInt(item.data.value || '0'),
|
|
105
|
+
});
|
|
106
|
+
batches.set(step.chainId, calls);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return batches;
|
|
110
|
+
}
|
|
111
|
+
buildCalls(quote) {
|
|
112
|
+
if (!quote.txData?.steps || quote.txData.steps.length === 0) {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
const calls = extractPrivyCalls(quote.txData.steps);
|
|
116
|
+
const metadata = {
|
|
117
|
+
totalSteps: quote.txData.steps.length,
|
|
118
|
+
steps: quote.txData.steps.map((step) => ({
|
|
119
|
+
name: step.stage,
|
|
120
|
+
step: step.step,
|
|
121
|
+
description: step.stage === 'approve'
|
|
122
|
+
? `Approve ${quote.tokens.in.symbol}`
|
|
123
|
+
: `Swap ${quote.tokens.in.symbol} for ${quote.tokens.out.symbol}`,
|
|
124
|
+
})),
|
|
125
|
+
};
|
|
126
|
+
return { calls, metadata };
|
|
127
|
+
}
|
|
128
|
+
buildSteps(quote) {
|
|
129
|
+
if (!quote.txData?.steps || quote.txData.steps.length === 0) {
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
const steps = quote.txData.steps.map((step) => ({
|
|
133
|
+
name: step.stage,
|
|
134
|
+
step: step.step,
|
|
135
|
+
description: step.stage === 'approve'
|
|
136
|
+
? `Approve ${quote.tokens.in.symbol}`
|
|
137
|
+
: `Swap ${quote.tokens.in.symbol} for ${quote.tokens.out.symbol}`,
|
|
138
|
+
}));
|
|
139
|
+
const callList = quote.txData.steps.map((step) => ({
|
|
140
|
+
to: step.data.to,
|
|
141
|
+
data: step.data.data,
|
|
142
|
+
value: step.data.value,
|
|
143
|
+
chainId: step.data.chainId,
|
|
144
|
+
gas: step.data.gas,
|
|
145
|
+
maxFeePerGas: step.data.maxFeePerGas,
|
|
146
|
+
maxPriorityFeePerGas: step.data.maxPriorityFeePerGas,
|
|
147
|
+
}));
|
|
148
|
+
return { totalSteps: quote.txData.steps.length, steps, callList };
|
|
149
|
+
}
|
|
150
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { BaseClient } from './base';
|
|
2
|
+
import type { Token, TokenSearchOptions } from '@harukit/types';
|
|
3
|
+
export declare class TokensClient extends BaseClient {
|
|
4
|
+
search(query: string, options?: TokenSearchOptions): Promise<Token[]>;
|
|
5
|
+
getByAddress(address: string, chainId: number): Promise<Token[]>;
|
|
6
|
+
getDefaults(): Promise<Token[]>;
|
|
7
|
+
getPrice(address: string, chainId: number): Promise<number>;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=tokens.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../src/clients/tokens.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,KAAK,EAAE,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEhE,qBAAa,YAAa,SAAQ,UAAU;IACpC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IA4BrE,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAchE,WAAW,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;IAa/B,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAalE"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { BaseClient } from './base';
|
|
2
|
+
export class TokensClient extends BaseClient {
|
|
3
|
+
async search(query, options) {
|
|
4
|
+
const params = new URLSearchParams({ term: query });
|
|
5
|
+
if (options?.chainIds) {
|
|
6
|
+
options.chainIds.forEach(id => params.append('chainIds', id.toString()));
|
|
7
|
+
}
|
|
8
|
+
if (options?.verified !== undefined) {
|
|
9
|
+
params.append('verified', options.verified.toString());
|
|
10
|
+
}
|
|
11
|
+
if (options?.includeAllChains !== undefined) {
|
|
12
|
+
params.append('includeAllChains', options.includeAllChains.toString());
|
|
13
|
+
}
|
|
14
|
+
if (options?.limit) {
|
|
15
|
+
params.append('limit', options.limit.toString());
|
|
16
|
+
}
|
|
17
|
+
const response = await fetch(`${this.baseUrl}/v1/tokens/search?${params.toString()}`, {
|
|
18
|
+
headers: this.getHeaders(),
|
|
19
|
+
});
|
|
20
|
+
if (!response.ok) {
|
|
21
|
+
throw new Error('Failed to search tokens');
|
|
22
|
+
}
|
|
23
|
+
const data = await response.json();
|
|
24
|
+
return data.tokens;
|
|
25
|
+
}
|
|
26
|
+
async getByAddress(address, chainId) {
|
|
27
|
+
const response = await fetch(`${this.baseUrl}/v1/tokens/by-address/${address}?chainId=${chainId}`, { headers: this.getHeaders() });
|
|
28
|
+
if (!response.ok) {
|
|
29
|
+
throw new Error('Failed to get token by address');
|
|
30
|
+
}
|
|
31
|
+
const data = await response.json();
|
|
32
|
+
return data.tokens;
|
|
33
|
+
}
|
|
34
|
+
async getDefaults() {
|
|
35
|
+
const response = await fetch(`${this.baseUrl}/v1/tokens/defaults`, {
|
|
36
|
+
headers: this.getHeaders(),
|
|
37
|
+
});
|
|
38
|
+
if (!response.ok) {
|
|
39
|
+
throw new Error('Failed to get default tokens');
|
|
40
|
+
}
|
|
41
|
+
const data = await response.json();
|
|
42
|
+
return data.tokens;
|
|
43
|
+
}
|
|
44
|
+
async getPrice(address, chainId) {
|
|
45
|
+
const response = await fetch(`${this.baseUrl}/v1/tokens/${address}/price?chainId=${chainId}`, { headers: this.getHeaders() });
|
|
46
|
+
if (!response.ok) {
|
|
47
|
+
throw new Error('Failed to get token price');
|
|
48
|
+
}
|
|
49
|
+
const data = await response.json();
|
|
50
|
+
return data.price;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { BaseClient } from './base';
|
|
2
|
+
import type { CleanTransfer } from '@harukit/types';
|
|
3
|
+
export interface TransferByUsdParams {
|
|
4
|
+
fromUser: string;
|
|
5
|
+
toUser: string;
|
|
6
|
+
tokenSymbol: string;
|
|
7
|
+
fromChain: string;
|
|
8
|
+
toChain: string;
|
|
9
|
+
usdValue: string;
|
|
10
|
+
}
|
|
11
|
+
export interface TransferByAmountParams {
|
|
12
|
+
fromUser: string;
|
|
13
|
+
toUser: string;
|
|
14
|
+
tokenSymbol: string;
|
|
15
|
+
fromChain: string;
|
|
16
|
+
toChain: string;
|
|
17
|
+
amount: string;
|
|
18
|
+
}
|
|
19
|
+
export interface TransferByAddressParams {
|
|
20
|
+
fromUser: string;
|
|
21
|
+
toUser: string;
|
|
22
|
+
tokenAddress: string;
|
|
23
|
+
fromChain: string;
|
|
24
|
+
toChain: string;
|
|
25
|
+
amount: string;
|
|
26
|
+
}
|
|
27
|
+
export declare class TransfersClient extends BaseClient {
|
|
28
|
+
getByUsd(params: TransferByUsdParams): Promise<CleanTransfer>;
|
|
29
|
+
getByAmount(params: TransferByAmountParams): Promise<CleanTransfer>;
|
|
30
|
+
/**
|
|
31
|
+
* YOLO MODE: Get transfer using raw token address
|
|
32
|
+
* Requires yoloMode: true in config
|
|
33
|
+
*/
|
|
34
|
+
getByAddress(params: TransferByAddressParams): Promise<CleanTransfer>;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=transfers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transfers.d.ts","sourceRoot":"","sources":["../../src/clients/transfers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEpD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,eAAgB,SAAQ,UAAU;IACvC,QAAQ,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,aAAa,CAAC;IAe7D,WAAW,CAAC,MAAM,EAAE,sBAAsB,GAAG,OAAO,CAAC,aAAa,CAAC;IAezE;;;OAGG;IACG,YAAY,CAAC,MAAM,EAAE,uBAAuB,GAAG,OAAO,CAAC,aAAa,CAAC;CAc5E"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { BaseClient } from './base';
|
|
2
|
+
export class TransfersClient extends BaseClient {
|
|
3
|
+
async getByUsd(params) {
|
|
4
|
+
const response = await fetch(`${this.baseUrl}/v1/transfers/by-usd`, {
|
|
5
|
+
method: 'POST',
|
|
6
|
+
headers: this.getHeaders(),
|
|
7
|
+
body: JSON.stringify(params),
|
|
8
|
+
});
|
|
9
|
+
if (!response.ok) {
|
|
10
|
+
const errorBody = await response.text();
|
|
11
|
+
throw new Error(`Failed to get transfer by USD: ${response.status} ${errorBody}`);
|
|
12
|
+
}
|
|
13
|
+
return response.json();
|
|
14
|
+
}
|
|
15
|
+
async getByAmount(params) {
|
|
16
|
+
const response = await fetch(`${this.baseUrl}/v1/transfers/by-amount`, {
|
|
17
|
+
method: 'POST',
|
|
18
|
+
headers: this.getHeaders(),
|
|
19
|
+
body: JSON.stringify(params),
|
|
20
|
+
});
|
|
21
|
+
if (!response.ok) {
|
|
22
|
+
const errorBody = await response.text();
|
|
23
|
+
throw new Error(`Failed to get transfer by amount: ${response.status} ${errorBody}`);
|
|
24
|
+
}
|
|
25
|
+
return response.json();
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* YOLO MODE: Get transfer using raw token address
|
|
29
|
+
* Requires yoloMode: true in config
|
|
30
|
+
*/
|
|
31
|
+
async getByAddress(params) {
|
|
32
|
+
const response = await fetch(`${this.baseUrl}/v1/transfers/by-address`, {
|
|
33
|
+
method: 'POST',
|
|
34
|
+
headers: this.getHeaders(),
|
|
35
|
+
body: JSON.stringify(params),
|
|
36
|
+
});
|
|
37
|
+
if (!response.ok) {
|
|
38
|
+
const errorBody = await response.text();
|
|
39
|
+
throw new Error(`Failed to get transfer by address: ${response.status} ${errorBody}`);
|
|
40
|
+
}
|
|
41
|
+
return response.json();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,KAAK,gBAAgB,EAAE,KAAK,WAAW,EAAE,KAAK,oBAAoB,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { ConfigManager } from './manager';
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { Config, HydratedToken } from '@harukit/types';
|
|
2
|
+
export interface ValidationResult {
|
|
3
|
+
valid: boolean;
|
|
4
|
+
errors: string[];
|
|
5
|
+
config?: Partial<Config>;
|
|
6
|
+
hydratedTokens?: HydratedToken[];
|
|
7
|
+
}
|
|
8
|
+
export interface TestResults {
|
|
9
|
+
tokens: {
|
|
10
|
+
success: boolean;
|
|
11
|
+
error?: string;
|
|
12
|
+
};
|
|
13
|
+
balances: {
|
|
14
|
+
success: boolean;
|
|
15
|
+
error?: string;
|
|
16
|
+
};
|
|
17
|
+
swaps: {
|
|
18
|
+
success: boolean;
|
|
19
|
+
error?: string;
|
|
20
|
+
};
|
|
21
|
+
transfers: {
|
|
22
|
+
success: boolean;
|
|
23
|
+
error?: string;
|
|
24
|
+
};
|
|
25
|
+
yield: {
|
|
26
|
+
success: boolean;
|
|
27
|
+
error?: string;
|
|
28
|
+
};
|
|
29
|
+
relay: {
|
|
30
|
+
success: boolean;
|
|
31
|
+
error?: string;
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export interface ConfigManagerOptions {
|
|
35
|
+
apiKey: string;
|
|
36
|
+
baseUrl?: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* ConfigManager - Validate and test configs against the Haru API
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```typescript
|
|
43
|
+
* const result = await ConfigManager.validate(
|
|
44
|
+
* { chains: ['arbitrum'] },
|
|
45
|
+
* { apiKey: 'haru_live_demo123' }
|
|
46
|
+
* );
|
|
47
|
+
*
|
|
48
|
+
* if (result.valid) {
|
|
49
|
+
* console.log('Config is valid!');
|
|
50
|
+
* }
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
export declare class ConfigManager {
|
|
54
|
+
private static getBaseUrl;
|
|
55
|
+
private static getHeaders;
|
|
56
|
+
/**
|
|
57
|
+
* Validate a config against the API
|
|
58
|
+
* Checks if chains are allowed, tokens can be hydrated, etc.
|
|
59
|
+
*/
|
|
60
|
+
static validate(config: Config, options: ConfigManagerOptions): Promise<ValidationResult>;
|
|
61
|
+
/**
|
|
62
|
+
* Test a config by making dry-run calls to all endpoints
|
|
63
|
+
* This validates that the config works for all features
|
|
64
|
+
*/
|
|
65
|
+
static test(config: Config, options: ConfigManagerOptions): Promise<TestResults>;
|
|
66
|
+
/**
|
|
67
|
+
* Create a config from a template
|
|
68
|
+
* This is local-only, doesn't validate against API
|
|
69
|
+
*/
|
|
70
|
+
static create(template?: 'minimal' | 'default' | 'full'): Config;
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/config/manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE5D,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IACzB,cAAc,CAAC,EAAE,aAAa,EAAE,CAAC;CAClC;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,QAAQ,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,KAAK,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,SAAS,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAChD,KAAK,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,KAAK,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7C;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAC,UAAU;IAIzB,OAAO,CAAC,MAAM,CAAC,UAAU;IAOzB;;;OAGG;WACU,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAkC/F;;;OAGG;WACU,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,WAAW,CAAC;IAyHtF;;;OAGG;IACH,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM;CAiCjE"}
|