@armory-sh/base 0.2.28 → 0.2.29

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.
@@ -1,4 +1,4 @@
1
- import type { PaymentPayload, PaymentRequirements, VerifyResponse, SettlementResponse } from "./types/x402";
1
+ import type { PaymentPayload, PaymentRequirements, SettlementResponse, VerifyResponse } from "./types/x402";
2
2
  export interface FacilitatorClientConfig {
3
3
  url: string;
4
4
  createHeaders?: () => Record<string, string> | Promise<Record<string, string>>;
@@ -0,0 +1,29 @@
1
+ import type { NetworkId, TokenId, ValidationError } from "./types/api";
2
+ import type { Address, PaymentRequirementsV2 } from "./types/v2";
3
+ export interface PaymentConfig {
4
+ payTo: Address | string;
5
+ chains?: NetworkId[];
6
+ chain?: NetworkId;
7
+ tokens?: TokenId[];
8
+ token?: TokenId;
9
+ amount?: string;
10
+ maxTimeoutSeconds?: number;
11
+ payToByChain?: Record<string, Address | string>;
12
+ payToByToken?: Record<string, Record<string, Address | string>>;
13
+ facilitatorUrl?: string;
14
+ facilitatorUrlByChain?: Record<string, string>;
15
+ facilitatorUrlByToken?: Record<string, Record<string, string>>;
16
+ }
17
+ export interface ResolvedRequirementsConfig {
18
+ requirements: PaymentRequirementsV2[];
19
+ error?: ValidationError;
20
+ }
21
+ export declare function createPaymentRequirements(config: PaymentConfig): ResolvedRequirementsConfig;
22
+ export declare function findRequirementByNetwork(requirements: PaymentRequirementsV2[], network: string): PaymentRequirementsV2 | undefined;
23
+ export declare function findRequirementByAccepted(requirements: PaymentRequirementsV2[], accepted: {
24
+ scheme: string;
25
+ network: string;
26
+ amount: string;
27
+ asset: string;
28
+ payTo: string;
29
+ }): PaymentRequirementsV2 | undefined;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * X402 Protocol Utilities (V2 Only)
3
+ *
4
+ * Shared protocol utilities for x402 client implementations.
5
+ * These functions are protocol-level and don't depend on wallet libraries.
6
+ */
7
+ /**
8
+ * Parse JSON or Base64-encoded JSON
9
+ * Handles both raw JSON and Base64URL-encoded JSON
10
+ */
11
+ export declare function parseJsonOrBase64(value: string): unknown;
12
+ /**
13
+ * Detect x402 protocol version from response
14
+ * V2-only: Always returns 2
15
+ */
16
+ export declare function detectX402Version(_response: Response): 2;
17
+ /**
18
+ * Get payment header name for protocol version
19
+ * V2-only: Returns PAYMENT-SIGNATURE header name
20
+ */
21
+ export declare function getPaymentHeaderName(_version: 2): string;
22
+ /**
23
+ * Generate a timestamp-based nonce as hex string
24
+ * Matches Coinbase SDK format: "0x" + 64 hex characters
25
+ * Uses timestamp for reproducibility (vs random)
26
+ */
27
+ export declare function generateNonce(): `0x${string}`;
28
+ /**
29
+ * Calculate expiry timestamp
30
+ * @param expirySeconds - Seconds from now (default: 3600 = 1 hour)
31
+ * @returns Unix timestamp
32
+ */
33
+ export declare function calculateValidBefore(expirySeconds?: number): number;
@@ -2,8 +2,8 @@
2
2
  * Simple, developer-friendly API types for Armory
3
3
  * Focuses on DX/UX - "everything just magically works"
4
4
  */
5
+ import type { CustomToken, NetworkConfig } from "./networks";
5
6
  import type { Address, CAIPAssetId } from "./v2";
6
- import type { NetworkConfig, CustomToken } from "./networks";
7
7
  /**
8
8
  * Network identifier - flexible input that resolves to a chain
9
9
  * - Network name: "base", "ethereum", "skale-base"
@@ -7,11 +7,13 @@
7
7
  *
8
8
  * Hooks allow extensibility without custom code in each client package.
9
9
  */
10
- import type { PaymentPayloadV2, PaymentRequirementsV2, Extensions, Address } from "./v2";
10
+ import type { Address, Extensions, PaymentPayloadV2, PaymentRequirementsV2 } from "./v2";
11
11
  export interface PaymentRequiredContext {
12
12
  url: RequestInfo | URL;
13
13
  requestInit: RequestInit | undefined;
14
+ accepts: PaymentRequirementsV2[];
14
15
  requirements: PaymentRequirementsV2;
16
+ selectedRequirement?: PaymentRequirementsV2;
15
17
  serverExtensions: Extensions | undefined;
16
18
  fromAddress: Address;
17
19
  nonce: `0x${string}`;
@@ -33,3 +35,17 @@ export interface HookConfig<TWallet = unknown> {
33
35
  name?: string;
34
36
  }
35
37
  export type HookRegistry<TWallet = unknown> = Record<string, HookConfig<TWallet>>;
38
+ export interface ClientHookErrorContext {
39
+ error: unknown;
40
+ phase: "onPaymentRequired" | "selectRequirement" | "beforeSignPayment" | "afterPaymentResponse";
41
+ }
42
+ export interface ClientHook<TWallet = unknown> {
43
+ name?: string;
44
+ onPaymentRequired?: (context: PaymentRequiredContext) => HookResult;
45
+ selectRequirement?: (context: PaymentRequiredContext) => PaymentRequirementsV2 | undefined | Promise<PaymentRequirementsV2 | undefined>;
46
+ beforeSignPayment?: (context: PaymentPayloadContext<TWallet>) => HookResult;
47
+ afterPaymentResponse?: (context: PaymentPayloadContext<TWallet> & {
48
+ response: Response;
49
+ }) => HookResult;
50
+ onError?: (context: ClientHookErrorContext) => HookResult;
51
+ }
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Simplified to support only x402 V2 format (Coinbase compatible)
5
5
  */
6
- import type { PaymentPayloadV2, PaymentRequirementsV2, SettlementResponseV2, PaymentRequiredV2, Address } from "./v2";
6
+ import type { Address, PaymentPayloadV2, PaymentRequiredV2, PaymentRequirementsV2, SettlementResponseV2 } from "./v2";
7
7
  export type PaymentPayload = PaymentPayloadV2;
8
8
  export type PaymentRequirements = PaymentRequirementsV2;
9
9
  export type SettlementResponse = SettlementResponseV2;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Generic Wallet Adapter Interface
3
+ *
4
+ * This interface defines the minimum wallet operations required
5
+ * for x402 payment signing. Each client package implements this
6
+ * interface for their specific wallet library (viem, ethers, etc.).
7
+ */
8
+ export interface PaymentWallet {
9
+ /**
10
+ * Get the wallet address
11
+ * Can be synchronous or asynchronous depending on the wallet library
12
+ */
13
+ getAddress(): string | Promise<string>;
14
+ /**
15
+ * Sign EIP-712 typed data
16
+ * Used for EIP-3009 TransferWithAuthorization signatures
17
+ *
18
+ * @param domain - EIP-712 domain separator
19
+ * @param types - EIP-712 type definitions
20
+ * @param value - Message to sign
21
+ * @returns Signature as hex string (0x-prefixed)
22
+ */
23
+ signTypedData(domain: Record<string, unknown>, types: Record<string, unknown>, value: Record<string, unknown>): Promise<string>;
24
+ }
@@ -0,0 +1,4 @@
1
+ export declare function encodeUtf8ToBase64(value: string): string;
2
+ export declare function decodeBase64ToUtf8(value: string): string;
3
+ export declare function toBase64Url(base64: string): string;
4
+ export declare function normalizeBase64Url(value: string): string;
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Helper functions for nonce generation, amount conversion, and other utilities.
5
5
  */
6
- import type { Hex, Address } from "../types/x402";
6
+ import type { Address, Hex } from "../types/x402";
7
7
  /**
8
8
  * Generate a random 32-byte nonce as hex string
9
9
  * Matches Coinbase SDK format: "0x" + 64 hex characters
@@ -2,7 +2,7 @@
2
2
  * Comprehensive validation for Armory configurations
3
3
  * Ensures networks, tokens, and facilitators are compatible
4
4
  */
5
- import type { NetworkId, TokenId, FacilitatorConfig, ResolvedNetwork, ResolvedToken, ResolvedFacilitator, ResolvedPaymentConfig, ValidationError, PaymentErrorCode } from "./types/api";
5
+ import type { FacilitatorConfig, NetworkId, PaymentErrorCode, ResolvedFacilitator, ResolvedNetwork, ResolvedPaymentConfig, ResolvedToken, TokenId, ValidationError } from "./types/api";
6
6
  export declare const createError: (code: PaymentErrorCode, message: string, details?: Partial<ValidationError>) => ValidationError;
7
7
  export declare const normalizeNetworkName: (name: string) => string;
8
8
  export declare const resolveNetwork: (input: unknown) => ResolvedNetwork | ValidationError;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@armory-sh/base",
3
- "version": "0.2.28",
3
+ "version": "0.2.29",
4
4
  "license": "MIT",
5
5
  "author": "Sawyer Cutler <sawyer@dirtroad.dev>",
6
6
  "keywords": [
@@ -28,10 +28,21 @@
28
28
  "bun": "./dist/index.js",
29
29
  "default": "./dist/index.js"
30
30
  },
31
+ "./types/hooks": {
32
+ "types": "./src/types/hooks.ts",
33
+ "bun": "./src/types/hooks.ts",
34
+ "default": "./src/types/hooks.ts"
35
+ },
36
+ "./client-hooks-runtime": {
37
+ "types": "./src/client-hooks-runtime.ts",
38
+ "bun": "./src/client-hooks-runtime.ts",
39
+ "default": "./src/client-hooks-runtime.ts"
40
+ },
31
41
  "./dist/*": "./dist/*.js"
32
42
  },
33
43
  "files": [
34
44
  "dist",
45
+ "src",
35
46
  "README.md"
36
47
  ],
37
48
  "publishConfig": {
@@ -50,7 +61,9 @@
50
61
  },
51
62
  "scripts": {
52
63
  "build": "rm -rf dist && tsup && tsc --emitDeclarationOnly",
64
+ "lint": "bun run build",
65
+ "format": "bun run lint",
53
66
  "test": "bun test",
54
67
  "typecheck": "tsc --noEmit"
55
68
  }
56
- }
69
+ }
@@ -0,0 +1,84 @@
1
+ export type TransferWithAuthorizationParams = readonly [
2
+ from: `0x${string}`,
3
+ to: `0x${string}`,
4
+ amount: bigint,
5
+ validAfter: bigint,
6
+ expiry: bigint,
7
+ v: number,
8
+ r: `0x${string}`,
9
+ s: `0x${string}`,
10
+ ];
11
+
12
+ export type ReceiveWithAuthorizationParams = readonly [
13
+ from: `0x${string}`,
14
+ to: `0x${string}`,
15
+ amount: bigint,
16
+ validAfter: bigint,
17
+ expiry: bigint,
18
+ v: number,
19
+ r: `0x${string}`,
20
+ s: `0x${string}`,
21
+ ];
22
+
23
+ export type BalanceOfParams = readonly [account: `0x${string}`];
24
+ export type BalanceOfReturnType = bigint;
25
+ export type NameReturnType = string;
26
+ export type SymbolReturnType = string;
27
+
28
+ export const ERC20_ABI = [
29
+ {
30
+ type: "function",
31
+ name: "transferWithAuthorization",
32
+ stateMutability: "nonpayable",
33
+ inputs: [
34
+ { name: "from", type: "address" },
35
+ { name: "to", type: "address" },
36
+ { name: "amount", type: "uint256" },
37
+ { name: "validAfter", type: "uint256" },
38
+ { name: "expiry", type: "uint256" },
39
+ { name: "v", type: "uint8" },
40
+ { name: "r", type: "bytes32" },
41
+ { name: "s", type: "bytes32" },
42
+ ],
43
+ outputs: [],
44
+ },
45
+ {
46
+ type: "function",
47
+ name: "receiveWithAuthorization",
48
+ stateMutability: "nonpayable",
49
+ inputs: [
50
+ { name: "from", type: "address" },
51
+ { name: "to", type: "address" },
52
+ { name: "amount", type: "uint256" },
53
+ { name: "validAfter", type: "uint256" },
54
+ { name: "expiry", type: "uint256" },
55
+ { name: "v", type: "uint8" },
56
+ { name: "r", type: "bytes32" },
57
+ { name: "s", type: "bytes32" },
58
+ ],
59
+ outputs: [],
60
+ },
61
+ {
62
+ type: "function",
63
+ name: "balanceOf",
64
+ stateMutability: "view",
65
+ inputs: [{ name: "account", type: "address" }],
66
+ outputs: [{ name: "balance", type: "uint256" }],
67
+ },
68
+ {
69
+ type: "function",
70
+ name: "name",
71
+ stateMutability: "view",
72
+ inputs: [],
73
+ outputs: [{ name: "", type: "string" }],
74
+ },
75
+ {
76
+ type: "function",
77
+ name: "symbol",
78
+ stateMutability: "view",
79
+ inputs: [],
80
+ outputs: [{ name: "", type: "string" }],
81
+ },
82
+ ] as const;
83
+
84
+ export type ERC20Abi = typeof ERC20_ABI;
@@ -0,0 +1,153 @@
1
+ import type {
2
+ ClientHook,
3
+ ClientHookErrorContext,
4
+ PaymentPayloadContext,
5
+ PaymentRequiredContext,
6
+ } from "./types/hooks";
7
+ import type { PaymentRequirementsV2 } from "./types/v2";
8
+
9
+ const notifyError = async <TWallet>(
10
+ hooks: ClientHook<TWallet>[] | undefined,
11
+ context: ClientHookErrorContext,
12
+ ): Promise<void> => {
13
+ if (!hooks?.length) {
14
+ return;
15
+ }
16
+
17
+ for (const hook of hooks) {
18
+ if (!hook.onError) {
19
+ continue;
20
+ }
21
+ await hook.onError(context);
22
+ }
23
+ };
24
+
25
+ export const runOnPaymentRequiredHooks = async <TWallet>(
26
+ hooks: ClientHook<TWallet>[] | undefined,
27
+ context: PaymentRequiredContext,
28
+ ): Promise<void> => {
29
+ if (!hooks?.length) {
30
+ return;
31
+ }
32
+
33
+ for (const hook of hooks) {
34
+ if (!hook.onPaymentRequired) {
35
+ continue;
36
+ }
37
+ try {
38
+ await hook.onPaymentRequired(context);
39
+ } catch (error) {
40
+ await notifyError(hooks, { error, phase: "onPaymentRequired" });
41
+ throw error;
42
+ }
43
+ }
44
+ };
45
+
46
+ export const selectRequirementWithHooks = async <TWallet>(
47
+ hooks: ClientHook<TWallet>[] | undefined,
48
+ context: PaymentRequiredContext,
49
+ ): Promise<PaymentRequirementsV2> => {
50
+ if (!context.accepts.length) {
51
+ throw new Error("No payment requirements found in accepts array");
52
+ }
53
+
54
+ let selected = context.accepts[0];
55
+
56
+ if (!hooks?.length) {
57
+ context.selectedRequirement = selected;
58
+ context.requirements = selected;
59
+ return selected;
60
+ }
61
+
62
+ for (const hook of hooks) {
63
+ if (!hook.selectRequirement) {
64
+ continue;
65
+ }
66
+ try {
67
+ const override = await hook.selectRequirement({
68
+ ...context,
69
+ selectedRequirement: selected,
70
+ requirements: selected,
71
+ });
72
+ if (!override) {
73
+ continue;
74
+ }
75
+ const isValid = context.accepts.some((accept) => accept === override);
76
+ if (!isValid) {
77
+ throw new Error(
78
+ "Hook selectRequirement must return an item from accepts",
79
+ );
80
+ }
81
+ selected = override;
82
+ } catch (error) {
83
+ await notifyError(hooks, { error, phase: "selectRequirement" });
84
+ throw error;
85
+ }
86
+ }
87
+
88
+ context.selectedRequirement = selected;
89
+ context.requirements = selected;
90
+ return selected;
91
+ };
92
+
93
+ export const getRequirementAttemptOrderWithHooks = async <TWallet>(
94
+ hooks: ClientHook<TWallet>[] | undefined,
95
+ context: PaymentRequiredContext,
96
+ ): Promise<PaymentRequirementsV2[]> => {
97
+ if (!context.accepts.length) {
98
+ throw new Error("No payment requirements found in accepts array");
99
+ }
100
+
101
+ const hasSelectorHook = Boolean(hooks?.some((hook) => hook.selectRequirement));
102
+ if (!hasSelectorHook) {
103
+ const first = context.accepts[0];
104
+ context.selectedRequirement = first;
105
+ context.requirements = first;
106
+ return context.accepts;
107
+ }
108
+
109
+ const selected = await selectRequirementWithHooks(hooks, context);
110
+ return [selected];
111
+ };
112
+
113
+ export const runBeforeSignPaymentHooks = async <TWallet>(
114
+ hooks: ClientHook<TWallet>[] | undefined,
115
+ context: PaymentPayloadContext<TWallet>,
116
+ ): Promise<void> => {
117
+ if (!hooks?.length) {
118
+ return;
119
+ }
120
+
121
+ for (const hook of hooks) {
122
+ if (!hook.beforeSignPayment) {
123
+ continue;
124
+ }
125
+ try {
126
+ await hook.beforeSignPayment(context);
127
+ } catch (error) {
128
+ await notifyError(hooks, { error, phase: "beforeSignPayment" });
129
+ throw error;
130
+ }
131
+ }
132
+ };
133
+
134
+ export const runAfterPaymentResponseHooks = async <TWallet>(
135
+ hooks: ClientHook<TWallet>[] | undefined,
136
+ context: PaymentPayloadContext<TWallet> & { response: Response },
137
+ ): Promise<void> => {
138
+ if (!hooks?.length) {
139
+ return;
140
+ }
141
+
142
+ for (const hook of hooks) {
143
+ if (!hook.afterPaymentResponse) {
144
+ continue;
145
+ }
146
+ try {
147
+ await hook.afterPaymentResponse(context);
148
+ } catch (error) {
149
+ await notifyError(hooks, { error, phase: "afterPaymentResponse" });
150
+ throw error;
151
+ }
152
+ }
153
+ };
@@ -0,0 +1,199 @@
1
+ import type { CustomToken } from "../types/networks";
2
+
3
+ export const USDC_BASE: CustomToken = {
4
+ symbol: "USDC",
5
+ name: "USDC",
6
+ version: "2",
7
+ contractAddress:
8
+ "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" as `0x${string}`,
9
+ chainId: 8453,
10
+ decimals: 6,
11
+ };
12
+
13
+ export const EURC_BASE: CustomToken = {
14
+ symbol: "EURC",
15
+ name: "EURC",
16
+ version: "2",
17
+ contractAddress:
18
+ "0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42" as `0x${string}`,
19
+ chainId: 8453,
20
+ decimals: 6,
21
+ };
22
+
23
+ export const USDC_BASE_SEPOLIA: CustomToken = {
24
+ symbol: "USDC",
25
+ name: "USDC",
26
+ version: "2",
27
+ contractAddress:
28
+ "0x036CbD53842c5426634e7929541eC2318f3dCF7e" as `0x${string}`,
29
+ chainId: 84532,
30
+ decimals: 6,
31
+ };
32
+
33
+ export const USDC_SKALE_BASE: CustomToken = {
34
+ symbol: "USDC",
35
+ name: "Bridged USDC (SKALE Bridge)",
36
+ version: "2",
37
+ contractAddress:
38
+ "0x85889c8c714505E0c94b30fcfcF64fE3Ac8FCb20" as `0x${string}`,
39
+ chainId: 1187947933,
40
+ decimals: 6,
41
+ };
42
+
43
+ export const SKL_SKALE_BASE: CustomToken = {
44
+ symbol: "SKL",
45
+ name: "SKALE",
46
+ version: "1",
47
+ contractAddress:
48
+ "0xE0595a049d02b7674572b0d59cd4880Db60EDC50" as `0x${string}`,
49
+ chainId: 1187947933,
50
+ decimals: 18,
51
+ };
52
+
53
+ export const USDT_SKALE_BASE: CustomToken = {
54
+ symbol: "USDT",
55
+ name: "Tether USD",
56
+ version: "1",
57
+ contractAddress:
58
+ "0x2bF5bF154b515EaA82C31a65ec11554fF5aF7fCA" as `0x${string}`,
59
+ chainId: 1187947933,
60
+ decimals: 6,
61
+ };
62
+
63
+ export const WBTC_SKALE_BASE: CustomToken = {
64
+ symbol: "WBTC",
65
+ name: "Wrapped BTC",
66
+ version: "1",
67
+ contractAddress:
68
+ "0x1aeeCFE5454c83B42D8A316246CAc9739E7f690e" as `0x${string}`,
69
+ chainId: 1187947933,
70
+ decimals: 8,
71
+ };
72
+
73
+ export const WETH_SKALE_BASE: CustomToken = {
74
+ symbol: "WETH",
75
+ name: "Wrapped Ether",
76
+ version: "1",
77
+ contractAddress:
78
+ "0x7bD39ABBd0Dd13103542cAe3276C7fA332bCA486" as `0x${string}`,
79
+ chainId: 1187947933,
80
+ decimals: 18,
81
+ };
82
+
83
+ export const SKL_SKALE_BASE_SEPOLIA: CustomToken = {
84
+ symbol: "SKL",
85
+ name: "SKALE",
86
+ version: "1",
87
+ contractAddress:
88
+ "0xaf2e0ff5b5f51553fdb34ce7f04a6c3201cee57b" as `0x${string}`,
89
+ chainId: 324705682,
90
+ decimals: 18,
91
+ };
92
+
93
+ export const USDC_SKALE_BASE_SEPOLIA: CustomToken = {
94
+ symbol: "USDC",
95
+ name: "Bridged USDC (SKALE Bridge)",
96
+ version: "2",
97
+ contractAddress:
98
+ "0x2e08028E3C4c2356572E096d8EF835cD5C6030bD" as `0x${string}`,
99
+ chainId: 324705682,
100
+ decimals: 6,
101
+ };
102
+
103
+ export const USDT_SKALE_BASE_SEPOLIA: CustomToken = {
104
+ symbol: "USDT",
105
+ name: "Tether USD",
106
+ version: "1",
107
+ contractAddress:
108
+ "0x3ca0a49f511c2c89c4dcbbf1731120d8919050bf" as `0x${string}`,
109
+ chainId: 324705682,
110
+ decimals: 6,
111
+ };
112
+
113
+ export const WBTC_SKALE_BASE_SEPOLIA: CustomToken = {
114
+ symbol: "WBTC",
115
+ name: "Wrapped BTC",
116
+ version: "1",
117
+ contractAddress:
118
+ "0x4512eacd4186b025186e1cf6cc0d89497c530e87" as `0x${string}`,
119
+ chainId: 324705682,
120
+ decimals: 8,
121
+ };
122
+
123
+ export const WETH_SKALE_BASE_SEPOLIA: CustomToken = {
124
+ symbol: "WETH",
125
+ name: "Wrapped Ether",
126
+ version: "1",
127
+ contractAddress:
128
+ "0xf94056bd7f6965db3757e1b145f200b7346b4fc0" as `0x${string}`,
129
+ chainId: 324705682,
130
+ decimals: 18,
131
+ };
132
+
133
+ export const TOKENS = {
134
+ USDC_BASE,
135
+ USDC_BASE_SEPOLIA,
136
+ EURC_BASE,
137
+ USDC_SKALE_BASE,
138
+ USDT_SKALE_BASE,
139
+ WBTC_SKALE_BASE,
140
+ WETH_SKALE_BASE,
141
+ SKL_SKALE_BASE,
142
+ SKL_SKALE_BASE_SEPOLIA,
143
+ USDC_SKALE_BASE_SEPOLIA,
144
+ USDT_SKALE_BASE_SEPOLIA,
145
+ WBTC_SKALE_BASE_SEPOLIA,
146
+ WETH_SKALE_BASE_SEPOLIA,
147
+ } as const;
148
+
149
+ function getToken(
150
+ chainId: number,
151
+ contractAddress: string,
152
+ ): CustomToken | undefined {
153
+ const tokens = Object.values(TOKENS);
154
+ return tokens.find(
155
+ (t) =>
156
+ t.chainId === chainId &&
157
+ t.contractAddress.toLowerCase() === contractAddress.toLowerCase(),
158
+ );
159
+ }
160
+
161
+ function getAllTokens(): CustomToken[] {
162
+ return Object.values(TOKENS);
163
+ }
164
+
165
+ function getTokensBySymbol(symbol: string): CustomToken[] {
166
+ return getAllTokens().filter(
167
+ (t) => t.symbol.toUpperCase() === symbol.toUpperCase(),
168
+ );
169
+ }
170
+
171
+ function getTokensByChain(chainId: number): CustomToken[] {
172
+ return getAllTokens().filter((t) => t.chainId === chainId);
173
+ }
174
+
175
+ export function getUSDCTokens(): CustomToken[] {
176
+ return getTokensBySymbol("USDC");
177
+ }
178
+
179
+ export function getEURCTokens(): CustomToken[] {
180
+ return getTokensBySymbol("EURC");
181
+ }
182
+
183
+ export function getSKLTokens(): CustomToken[] {
184
+ return getTokensBySymbol("SKL");
185
+ }
186
+
187
+ export function getUSDTTokens(): CustomToken[] {
188
+ return getTokensBySymbol("USDT");
189
+ }
190
+
191
+ export function getWBTCTokens(): CustomToken[] {
192
+ return getTokensBySymbol("WBTC");
193
+ }
194
+
195
+ export function getWETHTokens(): CustomToken[] {
196
+ return getTokensBySymbol("WETH");
197
+ }
198
+
199
+ export { getToken, getAllTokens, getTokensBySymbol, getTokensByChain };