@awarizon/web3 1.3.0 → 1.3.2
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.mts +102 -2
- package/dist/index.d.ts +102 -2
- package/dist/index.js +332 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +330 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +14 -14
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Chain, WalletClient, Address, Abi,
|
|
1
|
+
import { PublicClient, Chain, WalletClient, Address, Abi, Hex, Transport } from 'viem';
|
|
2
2
|
export { Abi, Address, Chain, Hash, TransactionReceipt, WalletClient } from 'viem';
|
|
3
3
|
import { WalletEngine, CreatedWallet, ImportedWalletFromMnemonic, ImportedWalletFromPrivateKey, ConnectorInfo, ExternalWalletClient, EIP1193Provider, SignTypedDataParams, WalletChangeEvent, ChainChangeEvent } from '@awarizon/wallet-engine';
|
|
4
4
|
export { ChainChangeEvent, ChainMismatchError, ChainSwitchError, ConnectorInfo, CreatedWallet, EIP1193Provider, ImportedWalletFromMnemonic, ImportedWalletFromPrivateKey, InvalidMnemonicError, InvalidPrivateKeyError, SignTypedDataParams, WalletChangeEvent, WalletEngine, WalletNotConnectedError } from '@awarizon/wallet-engine';
|
|
@@ -6,6 +6,78 @@ import { TransactionResult } from '@awarizon/tx-engine';
|
|
|
6
6
|
export { ContractExecutionError, GasEstimationError, SimulationError, TransactionEngine, TransactionResult, TransactionTimeoutError } from '@awarizon/tx-engine';
|
|
7
7
|
export { DuplicateFunctionError, InvalidABIError, UnsupportedABIItemError, generateAllMethodSignatures, generateMethodSignature, isPayableFunction, isWriteFunction, parseABI } from '@awarizon/abi-engine';
|
|
8
8
|
|
|
9
|
+
interface PriceResult {
|
|
10
|
+
/** Uppercase token symbol (e.g. "ETH", "USDC") */
|
|
11
|
+
symbol: string;
|
|
12
|
+
/** Current USD price */
|
|
13
|
+
price: number;
|
|
14
|
+
/** Where the price came from */
|
|
15
|
+
source: 'chainlink' | 'coingecko';
|
|
16
|
+
/** Unix timestamp of the last update (only set for chainlink source) */
|
|
17
|
+
updatedAt?: number;
|
|
18
|
+
/** True when chainlink data is older than 2 hours */
|
|
19
|
+
stale?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Fetches USD prices via Chainlink on-chain feeds (primary) with automatic
|
|
23
|
+
* fallback to CoinGecko's free API when no feed exists for the current chain.
|
|
24
|
+
*
|
|
25
|
+
* Attached to the SDK as `awarizon.price`.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* const { price } = await awarizon.price.get('ETH')
|
|
30
|
+
* // → { symbol: 'ETH', price: 3421.57, source: 'chainlink', updatedAt: 1720000000 }
|
|
31
|
+
*
|
|
32
|
+
* const prices = await awarizon.price.getMany(['ETH', 'BTC', 'USDC', 'ARB'])
|
|
33
|
+
* // → { ETH: { price: 3421 }, BTC: { price: 68200 }, ... }
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
declare class PriceEngine {
|
|
37
|
+
private readonly publicClient;
|
|
38
|
+
private readonly chainId;
|
|
39
|
+
constructor(publicClient: PublicClient, chainId: number);
|
|
40
|
+
/**
|
|
41
|
+
* Get the current USD price of a single token by symbol.
|
|
42
|
+
* Tries Chainlink first; falls back to CoinGecko on failure or missing feed.
|
|
43
|
+
*
|
|
44
|
+
* @param symbol - Token symbol: 'ETH', 'BTC', 'USDC', 'LINK', etc.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* const { price, source } = await awarizon.price.get('ETH')
|
|
48
|
+
*/
|
|
49
|
+
get(symbol: string): Promise<PriceResult>;
|
|
50
|
+
/**
|
|
51
|
+
* Get USD prices for multiple tokens in one call.
|
|
52
|
+
* Chainlink feeds are read in parallel; CoinGecko batch-fetches all remaining
|
|
53
|
+
* symbols in a single HTTP request — efficient even for large lists.
|
|
54
|
+
*
|
|
55
|
+
* @param symbols - Array of token symbols: ['ETH', 'BTC', 'USDC']
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* const prices = await awarizon.price.getMany(['ETH', 'BTC', 'USDC', 'ARB'])
|
|
59
|
+
* console.log(prices.ETH.price) // 3421.57
|
|
60
|
+
* console.log(prices.ARB.source) // 'coingecko' (no feed on most chains)
|
|
61
|
+
*/
|
|
62
|
+
getMany(symbols: string[]): Promise<Record<string, PriceResult>>;
|
|
63
|
+
/**
|
|
64
|
+
* Check whether a Chainlink feed exists for the given symbol on the current chain.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* awarizon.price.hasFeed('ETH') // true on mainnet, base, polygon, etc.
|
|
68
|
+
* awarizon.price.hasFeed('ARB') // true on Arbitrum, false elsewhere
|
|
69
|
+
*/
|
|
70
|
+
hasFeed(symbol: string): boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Return all symbols that have a Chainlink feed on the current chain.
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* awarizon.price.supportedSymbols()
|
|
76
|
+
* // → ['ETH', 'BTC', 'LINK', 'USDC', 'USDT', 'DAI'] on Base
|
|
77
|
+
*/
|
|
78
|
+
supportedSymbols(): string[];
|
|
79
|
+
}
|
|
80
|
+
|
|
9
81
|
interface AwarizonConfig {
|
|
10
82
|
/**
|
|
11
83
|
* Target chain. Accepts:
|
|
@@ -723,6 +795,14 @@ declare class AwarizonWeb3 {
|
|
|
723
795
|
readonly publicClient: PublicClient;
|
|
724
796
|
/** Wallet management — create, import, or connect external wallets */
|
|
725
797
|
readonly wallet: WalletProxy;
|
|
798
|
+
/**
|
|
799
|
+
* Token price engine — Chainlink on-chain feeds with CoinGecko fallback.
|
|
800
|
+
*
|
|
801
|
+
* @example
|
|
802
|
+
* const { price } = await awarizon.price.get('ETH')
|
|
803
|
+
* const prices = await awarizon.price.getMany(['ETH', 'BTC', 'USDC'])
|
|
804
|
+
*/
|
|
805
|
+
readonly price: PriceEngine;
|
|
726
806
|
private readonly _engine;
|
|
727
807
|
private readonly _txEngine;
|
|
728
808
|
private readonly _telemetry;
|
|
@@ -1024,6 +1104,26 @@ declare const CHAINS: Record<string, Chain>;
|
|
|
1024
1104
|
declare function resolveChain(chain: Chain | string): Chain;
|
|
1025
1105
|
/** Returns a list of all unique supported chain IDs */
|
|
1026
1106
|
declare function getSupportedChainIds(): number[];
|
|
1107
|
+
/**
|
|
1108
|
+
* Build the viem Transport for a chain.
|
|
1109
|
+
*
|
|
1110
|
+
* Priority:
|
|
1111
|
+
* 1. If the caller supplied an explicit `rpcUrlOverride`, use it directly.
|
|
1112
|
+
* 2. For chains with a known-unreliable default RPC, wrap primary + fallback
|
|
1113
|
+
* in viem's `fallback()` transport — primary is always tried first.
|
|
1114
|
+
* 3. All other chains: plain `http()` with viem's chain default.
|
|
1115
|
+
*
|
|
1116
|
+
* @example
|
|
1117
|
+
* // Fallback kicks in automatically for mantle, celo, gnosis, fantom, moonbeam
|
|
1118
|
+
* const transport = getChainTransport(mantle)
|
|
1119
|
+
*
|
|
1120
|
+
* // User override bypasses fallback entirely — they know what they want
|
|
1121
|
+
* const transport = getChainTransport(mantle, "https://my-own-rpc.example.com")
|
|
1122
|
+
*/
|
|
1123
|
+
declare function getChainTransport(chain: Chain, rpcUrlOverride?: string): Transport;
|
|
1124
|
+
|
|
1125
|
+
declare const CHAINLINK_FEEDS: Record<number, Record<string, Address>>;
|
|
1126
|
+
declare const COINGECKO_IDS: Record<string, string>;
|
|
1027
1127
|
|
|
1028
1128
|
type TelemetryEventType = 'contract.read' | 'contract.write' | 'contract.gas_estimate' | 'wallet.create' | 'wallet.import' | 'chain.switch';
|
|
1029
1129
|
interface TelemetryEvent {
|
|
@@ -1083,4 +1183,4 @@ declare class TelemetryClient {
|
|
|
1083
1183
|
private _flushBeacon;
|
|
1084
1184
|
}
|
|
1085
1185
|
|
|
1086
|
-
export { ApiKeyRequiredError, type AwarizonConfig, AwarizonWeb3, CHAINS, type ContractConfig, type ContractInstance, ContractNotLoadedError, type ContractRegistryEntry, ERC1155_ABI, ERC20_ABI, ERC721_ABI, type Erc1155Contract, type Erc20Contract, type Erc721Contract, type EventUnsubscribe, InvalidApiKeyError, NetworkMismatchError, type PayableOptions, ProviderError, type SDKWalletInfo, TelemetryClient, type TelemetryEvent, type TelemetryEventType, UnsupportedChainError, getSupportedChainIds, resolveChain };
|
|
1186
|
+
export { ApiKeyRequiredError, type AwarizonConfig, AwarizonWeb3, CHAINLINK_FEEDS, CHAINS, COINGECKO_IDS, type ContractConfig, type ContractInstance, ContractNotLoadedError, type ContractRegistryEntry, ERC1155_ABI, ERC20_ABI, ERC721_ABI, type Erc1155Contract, type Erc20Contract, type Erc721Contract, type EventUnsubscribe, InvalidApiKeyError, NetworkMismatchError, type PayableOptions, PriceEngine, type PriceResult, ProviderError, type SDKWalletInfo, TelemetryClient, type TelemetryEvent, type TelemetryEventType, UnsupportedChainError, getChainTransport, getSupportedChainIds, resolveChain };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Chain, WalletClient, Address, Abi,
|
|
1
|
+
import { PublicClient, Chain, WalletClient, Address, Abi, Hex, Transport } from 'viem';
|
|
2
2
|
export { Abi, Address, Chain, Hash, TransactionReceipt, WalletClient } from 'viem';
|
|
3
3
|
import { WalletEngine, CreatedWallet, ImportedWalletFromMnemonic, ImportedWalletFromPrivateKey, ConnectorInfo, ExternalWalletClient, EIP1193Provider, SignTypedDataParams, WalletChangeEvent, ChainChangeEvent } from '@awarizon/wallet-engine';
|
|
4
4
|
export { ChainChangeEvent, ChainMismatchError, ChainSwitchError, ConnectorInfo, CreatedWallet, EIP1193Provider, ImportedWalletFromMnemonic, ImportedWalletFromPrivateKey, InvalidMnemonicError, InvalidPrivateKeyError, SignTypedDataParams, WalletChangeEvent, WalletEngine, WalletNotConnectedError } from '@awarizon/wallet-engine';
|
|
@@ -6,6 +6,78 @@ import { TransactionResult } from '@awarizon/tx-engine';
|
|
|
6
6
|
export { ContractExecutionError, GasEstimationError, SimulationError, TransactionEngine, TransactionResult, TransactionTimeoutError } from '@awarizon/tx-engine';
|
|
7
7
|
export { DuplicateFunctionError, InvalidABIError, UnsupportedABIItemError, generateAllMethodSignatures, generateMethodSignature, isPayableFunction, isWriteFunction, parseABI } from '@awarizon/abi-engine';
|
|
8
8
|
|
|
9
|
+
interface PriceResult {
|
|
10
|
+
/** Uppercase token symbol (e.g. "ETH", "USDC") */
|
|
11
|
+
symbol: string;
|
|
12
|
+
/** Current USD price */
|
|
13
|
+
price: number;
|
|
14
|
+
/** Where the price came from */
|
|
15
|
+
source: 'chainlink' | 'coingecko';
|
|
16
|
+
/** Unix timestamp of the last update (only set for chainlink source) */
|
|
17
|
+
updatedAt?: number;
|
|
18
|
+
/** True when chainlink data is older than 2 hours */
|
|
19
|
+
stale?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Fetches USD prices via Chainlink on-chain feeds (primary) with automatic
|
|
23
|
+
* fallback to CoinGecko's free API when no feed exists for the current chain.
|
|
24
|
+
*
|
|
25
|
+
* Attached to the SDK as `awarizon.price`.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* const { price } = await awarizon.price.get('ETH')
|
|
30
|
+
* // → { symbol: 'ETH', price: 3421.57, source: 'chainlink', updatedAt: 1720000000 }
|
|
31
|
+
*
|
|
32
|
+
* const prices = await awarizon.price.getMany(['ETH', 'BTC', 'USDC', 'ARB'])
|
|
33
|
+
* // → { ETH: { price: 3421 }, BTC: { price: 68200 }, ... }
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
declare class PriceEngine {
|
|
37
|
+
private readonly publicClient;
|
|
38
|
+
private readonly chainId;
|
|
39
|
+
constructor(publicClient: PublicClient, chainId: number);
|
|
40
|
+
/**
|
|
41
|
+
* Get the current USD price of a single token by symbol.
|
|
42
|
+
* Tries Chainlink first; falls back to CoinGecko on failure or missing feed.
|
|
43
|
+
*
|
|
44
|
+
* @param symbol - Token symbol: 'ETH', 'BTC', 'USDC', 'LINK', etc.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* const { price, source } = await awarizon.price.get('ETH')
|
|
48
|
+
*/
|
|
49
|
+
get(symbol: string): Promise<PriceResult>;
|
|
50
|
+
/**
|
|
51
|
+
* Get USD prices for multiple tokens in one call.
|
|
52
|
+
* Chainlink feeds are read in parallel; CoinGecko batch-fetches all remaining
|
|
53
|
+
* symbols in a single HTTP request — efficient even for large lists.
|
|
54
|
+
*
|
|
55
|
+
* @param symbols - Array of token symbols: ['ETH', 'BTC', 'USDC']
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* const prices = await awarizon.price.getMany(['ETH', 'BTC', 'USDC', 'ARB'])
|
|
59
|
+
* console.log(prices.ETH.price) // 3421.57
|
|
60
|
+
* console.log(prices.ARB.source) // 'coingecko' (no feed on most chains)
|
|
61
|
+
*/
|
|
62
|
+
getMany(symbols: string[]): Promise<Record<string, PriceResult>>;
|
|
63
|
+
/**
|
|
64
|
+
* Check whether a Chainlink feed exists for the given symbol on the current chain.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* awarizon.price.hasFeed('ETH') // true on mainnet, base, polygon, etc.
|
|
68
|
+
* awarizon.price.hasFeed('ARB') // true on Arbitrum, false elsewhere
|
|
69
|
+
*/
|
|
70
|
+
hasFeed(symbol: string): boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Return all symbols that have a Chainlink feed on the current chain.
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* awarizon.price.supportedSymbols()
|
|
76
|
+
* // → ['ETH', 'BTC', 'LINK', 'USDC', 'USDT', 'DAI'] on Base
|
|
77
|
+
*/
|
|
78
|
+
supportedSymbols(): string[];
|
|
79
|
+
}
|
|
80
|
+
|
|
9
81
|
interface AwarizonConfig {
|
|
10
82
|
/**
|
|
11
83
|
* Target chain. Accepts:
|
|
@@ -723,6 +795,14 @@ declare class AwarizonWeb3 {
|
|
|
723
795
|
readonly publicClient: PublicClient;
|
|
724
796
|
/** Wallet management — create, import, or connect external wallets */
|
|
725
797
|
readonly wallet: WalletProxy;
|
|
798
|
+
/**
|
|
799
|
+
* Token price engine — Chainlink on-chain feeds with CoinGecko fallback.
|
|
800
|
+
*
|
|
801
|
+
* @example
|
|
802
|
+
* const { price } = await awarizon.price.get('ETH')
|
|
803
|
+
* const prices = await awarizon.price.getMany(['ETH', 'BTC', 'USDC'])
|
|
804
|
+
*/
|
|
805
|
+
readonly price: PriceEngine;
|
|
726
806
|
private readonly _engine;
|
|
727
807
|
private readonly _txEngine;
|
|
728
808
|
private readonly _telemetry;
|
|
@@ -1024,6 +1104,26 @@ declare const CHAINS: Record<string, Chain>;
|
|
|
1024
1104
|
declare function resolveChain(chain: Chain | string): Chain;
|
|
1025
1105
|
/** Returns a list of all unique supported chain IDs */
|
|
1026
1106
|
declare function getSupportedChainIds(): number[];
|
|
1107
|
+
/**
|
|
1108
|
+
* Build the viem Transport for a chain.
|
|
1109
|
+
*
|
|
1110
|
+
* Priority:
|
|
1111
|
+
* 1. If the caller supplied an explicit `rpcUrlOverride`, use it directly.
|
|
1112
|
+
* 2. For chains with a known-unreliable default RPC, wrap primary + fallback
|
|
1113
|
+
* in viem's `fallback()` transport — primary is always tried first.
|
|
1114
|
+
* 3. All other chains: plain `http()` with viem's chain default.
|
|
1115
|
+
*
|
|
1116
|
+
* @example
|
|
1117
|
+
* // Fallback kicks in automatically for mantle, celo, gnosis, fantom, moonbeam
|
|
1118
|
+
* const transport = getChainTransport(mantle)
|
|
1119
|
+
*
|
|
1120
|
+
* // User override bypasses fallback entirely — they know what they want
|
|
1121
|
+
* const transport = getChainTransport(mantle, "https://my-own-rpc.example.com")
|
|
1122
|
+
*/
|
|
1123
|
+
declare function getChainTransport(chain: Chain, rpcUrlOverride?: string): Transport;
|
|
1124
|
+
|
|
1125
|
+
declare const CHAINLINK_FEEDS: Record<number, Record<string, Address>>;
|
|
1126
|
+
declare const COINGECKO_IDS: Record<string, string>;
|
|
1027
1127
|
|
|
1028
1128
|
type TelemetryEventType = 'contract.read' | 'contract.write' | 'contract.gas_estimate' | 'wallet.create' | 'wallet.import' | 'chain.switch';
|
|
1029
1129
|
interface TelemetryEvent {
|
|
@@ -1083,4 +1183,4 @@ declare class TelemetryClient {
|
|
|
1083
1183
|
private _flushBeacon;
|
|
1084
1184
|
}
|
|
1085
1185
|
|
|
1086
|
-
export { ApiKeyRequiredError, type AwarizonConfig, AwarizonWeb3, CHAINS, type ContractConfig, type ContractInstance, ContractNotLoadedError, type ContractRegistryEntry, ERC1155_ABI, ERC20_ABI, ERC721_ABI, type Erc1155Contract, type Erc20Contract, type Erc721Contract, type EventUnsubscribe, InvalidApiKeyError, NetworkMismatchError, type PayableOptions, ProviderError, type SDKWalletInfo, TelemetryClient, type TelemetryEvent, type TelemetryEventType, UnsupportedChainError, getSupportedChainIds, resolveChain };
|
|
1186
|
+
export { ApiKeyRequiredError, type AwarizonConfig, AwarizonWeb3, CHAINLINK_FEEDS, CHAINS, COINGECKO_IDS, type ContractConfig, type ContractInstance, ContractNotLoadedError, type ContractRegistryEntry, ERC1155_ABI, ERC20_ABI, ERC721_ABI, type Erc1155Contract, type Erc20Contract, type Erc721Contract, type EventUnsubscribe, InvalidApiKeyError, NetworkMismatchError, type PayableOptions, PriceEngine, type PriceResult, ProviderError, type SDKWalletInfo, TelemetryClient, type TelemetryEvent, type TelemetryEventType, UnsupportedChainError, getChainTransport, getSupportedChainIds, resolveChain };
|
package/dist/index.js
CHANGED
|
@@ -82,6 +82,27 @@ function getSupportedChainIds() {
|
|
|
82
82
|
return true;
|
|
83
83
|
}).map((c) => c.id);
|
|
84
84
|
}
|
|
85
|
+
var FALLBACK_RPCS = {
|
|
86
|
+
5e3: "https://mantle-mainnet.public.blastapi.io",
|
|
87
|
+
// mantle
|
|
88
|
+
42220: "https://celo.drpc.org",
|
|
89
|
+
// celo
|
|
90
|
+
100: "https://gnosis.drpc.org",
|
|
91
|
+
// gnosis
|
|
92
|
+
250: "https://rpc.fantom.network",
|
|
93
|
+
// fantom
|
|
94
|
+
1284: "https://moonbeam.drpc.org"
|
|
95
|
+
// moonbeam
|
|
96
|
+
};
|
|
97
|
+
function getChainTransport(chain, rpcUrlOverride) {
|
|
98
|
+
if (rpcUrlOverride) return viem.http(rpcUrlOverride);
|
|
99
|
+
const fallbackUrl = FALLBACK_RPCS[chain.id];
|
|
100
|
+
if (fallbackUrl) {
|
|
101
|
+
const primaryUrl = chain.rpcUrls.default.http[0];
|
|
102
|
+
return viem.fallback([viem.http(primaryUrl), viem.http(fallbackUrl)]);
|
|
103
|
+
}
|
|
104
|
+
return viem.http();
|
|
105
|
+
}
|
|
85
106
|
function trackEvent(telemetry, type, chain, functionName, success, start) {
|
|
86
107
|
telemetry?.track({
|
|
87
108
|
type,
|
|
@@ -361,6 +382,309 @@ var TelemetryClient = class {
|
|
|
361
382
|
);
|
|
362
383
|
}
|
|
363
384
|
};
|
|
385
|
+
|
|
386
|
+
// src/price/feeds.ts
|
|
387
|
+
var AGGREGATOR_ABI = [
|
|
388
|
+
{
|
|
389
|
+
inputs: [],
|
|
390
|
+
name: "latestRoundData",
|
|
391
|
+
outputs: [
|
|
392
|
+
{ name: "roundId", type: "uint80" },
|
|
393
|
+
{ name: "answer", type: "int256" },
|
|
394
|
+
{ name: "startedAt", type: "uint256" },
|
|
395
|
+
{ name: "updatedAt", type: "uint256" },
|
|
396
|
+
{ name: "answeredInRound", type: "uint80" }
|
|
397
|
+
],
|
|
398
|
+
stateMutability: "view",
|
|
399
|
+
type: "function"
|
|
400
|
+
},
|
|
401
|
+
{
|
|
402
|
+
inputs: [],
|
|
403
|
+
name: "decimals",
|
|
404
|
+
outputs: [{ name: "", type: "uint8" }],
|
|
405
|
+
stateMutability: "view",
|
|
406
|
+
type: "function"
|
|
407
|
+
}
|
|
408
|
+
];
|
|
409
|
+
var CHAINLINK_FEEDS = {
|
|
410
|
+
// Ethereum Mainnet
|
|
411
|
+
1: {
|
|
412
|
+
ETH: "0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419",
|
|
413
|
+
BTC: "0xF4030086522a5bEEa4988F8cA5B36dbC97BeE88b",
|
|
414
|
+
BNB: "0x14e613AC84a31f709eadbEF3bf98585328207896",
|
|
415
|
+
MATIC: "0x7bAC85A8a13A4BcD8abb3eB7d6b4d632c895a5f6",
|
|
416
|
+
AVAX: "0xFF3EEb22B5E3dE6e705b44749C2559d704923FD7",
|
|
417
|
+
LINK: "0x2c1d072e956AFFC0D435Cb7AC308d97936742191",
|
|
418
|
+
UNI: "0x553303d460EE0afB37EdFf9bE42922D8FF63220e",
|
|
419
|
+
AAVE: "0x547a514d5e3769680Ce22B2361c10Ea13619e8a9",
|
|
420
|
+
MKR: "0xec1D1B3b0443256cc3860e24a46F108e699484Aa",
|
|
421
|
+
SNX: "0xDC3EA94CD0AC27d9A86C180091e7f78C683d3699",
|
|
422
|
+
CRV: "0xCd627aA160A6fA45Eb793D19Ef54f5062F20f33",
|
|
423
|
+
USDC: "0x8fFfFfd4AfB6115b954Bd326cbe7B4BA576818f6",
|
|
424
|
+
USDT: "0x3E7d1eAB13ad0104d2750B8863b489D65364e32D",
|
|
425
|
+
DAI: "0xAed0c38402a5d19df6E4c03F4E2DceD6e29c1ee9",
|
|
426
|
+
FRAX: "0xB9E1E3A9feFf48998E45Fa90847ed4D467E8BcfD"
|
|
427
|
+
},
|
|
428
|
+
// Base
|
|
429
|
+
8453: {
|
|
430
|
+
ETH: "0x71041dddad3595F9CEd3dCCFBe3D1F4b0a16Bb70",
|
|
431
|
+
BTC: "0x64c911996D3c6aC71f9b455B1E8E7266BcFBF15F",
|
|
432
|
+
LINK: "0x56a43EB56Da12C0dc1D972ACb089c06a5dEF8e69",
|
|
433
|
+
USDC: "0x7e860098F58bBFC8648a4311b374B1D669a2bc9b"
|
|
434
|
+
},
|
|
435
|
+
// Polygon
|
|
436
|
+
137: {
|
|
437
|
+
ETH: "0xF9680D99D6C9589e2a93a78A04A279e509205945",
|
|
438
|
+
BTC: "0xc907E116054Ad103354f2D350FD2514433D57F6f",
|
|
439
|
+
MATIC: "0xAB594600376Ec9fD91F8e885dADF0CE036862dE0",
|
|
440
|
+
LINK: "0xd9FFdb71EbE7496cC440152d43986Aae0AB76665",
|
|
441
|
+
AAVE: "0x72484B12719E23115761D5DA1646945632979bB6",
|
|
442
|
+
UNI: "0xdf0Fb4e4F928d2dCB76f438575fDD8682386e13C",
|
|
443
|
+
USDC: "0xfE4A8cc5b5B2366C1B58Bea3858e81843581b2F7",
|
|
444
|
+
USDT: "0x0A6513e40db6EB1b165753AD52E80663aea50545",
|
|
445
|
+
DAI: "0x4746DeC9e833A82EC7C2C1356372CcF2cfcD2F3D"
|
|
446
|
+
},
|
|
447
|
+
// Arbitrum One
|
|
448
|
+
42161: {
|
|
449
|
+
ETH: "0x639Fe6ab55C921f74e7fac1ee960C0B6293ba612",
|
|
450
|
+
BTC: "0x6ce185860a4963106506C203335A2910413708e9",
|
|
451
|
+
LINK: "0x86E53CF1B873786aC9Cc60cde71fFd0035d6df2d",
|
|
452
|
+
ARB: "0xb2A824043730FE05F3DA2efaFa1CBbe83fa548D6",
|
|
453
|
+
USDC: "0x50834F3163758fcC1Df9973b6e91f0F0F0434aD3",
|
|
454
|
+
USDT: "0x3f3f5dF88dC9F13eac63DF89EC16ef6e7E25DdE7"
|
|
455
|
+
},
|
|
456
|
+
// Optimism
|
|
457
|
+
10: {
|
|
458
|
+
ETH: "0x13e3Ee699D1909E989722E753853AE30b17e08c5",
|
|
459
|
+
BTC: "0xD702DD976Fb76Fffc2D3963D037dfDae5b04E593",
|
|
460
|
+
LINK: "0xCc232dcFAAE6354cE191Bd574108c1aD03f86450",
|
|
461
|
+
OP: "0x0D276FC14719f9292D5C1eA2198673d1f4269246",
|
|
462
|
+
USDC: "0x16a9FA2FDa030272Ce99B29CF780dFA30361d35f",
|
|
463
|
+
USDT: "0xECef79E109e997bCA29c1c0897ec9d7b03647F5E"
|
|
464
|
+
},
|
|
465
|
+
// BNB Smart Chain
|
|
466
|
+
56: {
|
|
467
|
+
BNB: "0x0567F2323251f0Aab15c8dFb1967E4e8A7D42aeE",
|
|
468
|
+
ETH: "0x9ef1B8c0E4F7dc8bF5719Ea496883DC6401d5b2",
|
|
469
|
+
BTC: "0x264990fbd0A4796A3E3d8E37C4d5F87a3aCa5Ebf",
|
|
470
|
+
LINK: "0xca236E327F629f9Fc2c30A4E95775EbF0B89fac8",
|
|
471
|
+
USDT: "0xB97Ad0E74fa7d920791E90258A6E2085088b4320",
|
|
472
|
+
DAI: "0x132d3C0B1D2cEa0BC552588063bdBb210FDeecfA"
|
|
473
|
+
},
|
|
474
|
+
// Avalanche C-Chain
|
|
475
|
+
43114: {
|
|
476
|
+
ETH: "0x976B3D034E162d8bD72D6b9C989d545b839003b0",
|
|
477
|
+
BTC: "0x2779D32d5166BAaa2B2b658333bA7e6Ec0C65743",
|
|
478
|
+
AVAX: "0x0A77230d17318075983913bC2145DB16C7366156",
|
|
479
|
+
LINK: "0x49ccd9ca821EfEab2b98c60DC60F518E765eDe9a",
|
|
480
|
+
USDC: "0xF096872672F44d6EBA71527d2277B6f4B77Ea29A",
|
|
481
|
+
USDT: "0xEBE676ee90Fe1112671f19b6B7459bC678B67e8a"
|
|
482
|
+
}
|
|
483
|
+
};
|
|
484
|
+
var COINGECKO_IDS = {
|
|
485
|
+
// Native tokens
|
|
486
|
+
ETH: "ethereum",
|
|
487
|
+
BTC: "bitcoin",
|
|
488
|
+
BNB: "binancecoin",
|
|
489
|
+
MATIC: "matic-network",
|
|
490
|
+
POL: "matic-network",
|
|
491
|
+
AVAX: "avalanche-2",
|
|
492
|
+
FTM: "fantom",
|
|
493
|
+
GLMR: "moonbeam",
|
|
494
|
+
CELO: "celo",
|
|
495
|
+
XDAI: "xdai",
|
|
496
|
+
GNO: "gnosis",
|
|
497
|
+
MNT: "mantle",
|
|
498
|
+
// Major stables
|
|
499
|
+
USDC: "usd-coin",
|
|
500
|
+
USDT: "tether",
|
|
501
|
+
DAI: "dai",
|
|
502
|
+
BUSD: "binance-usd",
|
|
503
|
+
FRAX: "frax",
|
|
504
|
+
LUSD: "liquity-usd",
|
|
505
|
+
GUSD: "gemini-dollar",
|
|
506
|
+
TUSD: "true-usd",
|
|
507
|
+
USDD: "usdd",
|
|
508
|
+
FDUSD: "first-digital-usd",
|
|
509
|
+
// DeFi blue chips
|
|
510
|
+
LINK: "chainlink",
|
|
511
|
+
UNI: "uniswap",
|
|
512
|
+
AAVE: "aave",
|
|
513
|
+
MKR: "maker",
|
|
514
|
+
SNX: "havven",
|
|
515
|
+
CRV: "curve-dao-token",
|
|
516
|
+
LDO: "lido-dao",
|
|
517
|
+
RPL: "rocket-pool",
|
|
518
|
+
BAL: "balancer",
|
|
519
|
+
COMP: "compound-governance-token",
|
|
520
|
+
YFI: "yearn-finance",
|
|
521
|
+
SUSHI: "sushi",
|
|
522
|
+
// L2 tokens
|
|
523
|
+
ARB: "arbitrum",
|
|
524
|
+
OP: "optimism",
|
|
525
|
+
IMX: "immutable-x",
|
|
526
|
+
// Other popular alts
|
|
527
|
+
DOGE: "dogecoin",
|
|
528
|
+
SHIB: "shiba-inu",
|
|
529
|
+
PEPE: "pepe",
|
|
530
|
+
WLD: "worldcoin-wld",
|
|
531
|
+
APE: "apecoin",
|
|
532
|
+
GRT: "the-graph",
|
|
533
|
+
ENS: "ethereum-name-service",
|
|
534
|
+
BLUR: "blur"
|
|
535
|
+
};
|
|
536
|
+
|
|
537
|
+
// src/price/index.ts
|
|
538
|
+
var TWO_HOURS_SECS = 7200;
|
|
539
|
+
async function fetchChainlink(publicClient, chainId, symbol) {
|
|
540
|
+
const feeds = CHAINLINK_FEEDS[chainId];
|
|
541
|
+
if (!feeds) return null;
|
|
542
|
+
const address = feeds[symbol.toUpperCase()];
|
|
543
|
+
if (!address) return null;
|
|
544
|
+
try {
|
|
545
|
+
const [roundData, rawDecimals] = await Promise.all([
|
|
546
|
+
publicClient.readContract({
|
|
547
|
+
address,
|
|
548
|
+
abi: AGGREGATOR_ABI,
|
|
549
|
+
functionName: "latestRoundData"
|
|
550
|
+
}),
|
|
551
|
+
publicClient.readContract({
|
|
552
|
+
address,
|
|
553
|
+
abi: AGGREGATOR_ABI,
|
|
554
|
+
functionName: "decimals"
|
|
555
|
+
})
|
|
556
|
+
]);
|
|
557
|
+
const answer = roundData[1];
|
|
558
|
+
const updatedAt = Number(roundData[3]);
|
|
559
|
+
const decimals = Number(rawDecimals);
|
|
560
|
+
if (answer <= 0n) return null;
|
|
561
|
+
const price = Number(answer) / 10 ** decimals;
|
|
562
|
+
const stale = Date.now() / 1e3 - updatedAt > TWO_HOURS_SECS;
|
|
563
|
+
return { symbol: symbol.toUpperCase(), price, source: "chainlink", updatedAt, stale };
|
|
564
|
+
} catch {
|
|
565
|
+
return null;
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
var CG_BASE = "https://api.coingecko.com/api/v3";
|
|
569
|
+
async function fetchCoinGecko(symbols) {
|
|
570
|
+
const ids = symbols.map((s) => COINGECKO_IDS[s.toUpperCase()]).filter(Boolean);
|
|
571
|
+
if (ids.length === 0) return {};
|
|
572
|
+
const url = `${CG_BASE}/simple/price?ids=${ids.join(",")}&vs_currencies=usd`;
|
|
573
|
+
const res = await fetch(url);
|
|
574
|
+
if (!res.ok) throw new Error(`[awarizon/price] CoinGecko returned ${res.status}`);
|
|
575
|
+
const data = await res.json();
|
|
576
|
+
const out = {};
|
|
577
|
+
for (const sym of symbols) {
|
|
578
|
+
const id = COINGECKO_IDS[sym.toUpperCase()];
|
|
579
|
+
const price = id ? data[id]?.usd : void 0;
|
|
580
|
+
if (price !== void 0) out[sym.toUpperCase()] = price;
|
|
581
|
+
}
|
|
582
|
+
return out;
|
|
583
|
+
}
|
|
584
|
+
var PriceEngine = class {
|
|
585
|
+
constructor(publicClient, chainId) {
|
|
586
|
+
this.publicClient = publicClient;
|
|
587
|
+
this.chainId = chainId;
|
|
588
|
+
}
|
|
589
|
+
/**
|
|
590
|
+
* Get the current USD price of a single token by symbol.
|
|
591
|
+
* Tries Chainlink first; falls back to CoinGecko on failure or missing feed.
|
|
592
|
+
*
|
|
593
|
+
* @param symbol - Token symbol: 'ETH', 'BTC', 'USDC', 'LINK', etc.
|
|
594
|
+
*
|
|
595
|
+
* @example
|
|
596
|
+
* const { price, source } = await awarizon.price.get('ETH')
|
|
597
|
+
*/
|
|
598
|
+
async get(symbol) {
|
|
599
|
+
const sym = symbol.toUpperCase();
|
|
600
|
+
const chainlink = await fetchChainlink(this.publicClient, this.chainId, sym);
|
|
601
|
+
if (chainlink && !chainlink.stale) return chainlink;
|
|
602
|
+
if (COINGECKO_IDS[sym]) {
|
|
603
|
+
try {
|
|
604
|
+
const cgPrices = await fetchCoinGecko([sym]);
|
|
605
|
+
const price = cgPrices[sym];
|
|
606
|
+
if (price !== void 0) {
|
|
607
|
+
return { symbol: sym, price, source: "coingecko" };
|
|
608
|
+
}
|
|
609
|
+
} catch {
|
|
610
|
+
if (chainlink) return chainlink;
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
if (chainlink) return chainlink;
|
|
614
|
+
throw new Error(
|
|
615
|
+
`[awarizon/price] No price available for "${sym}". No Chainlink feed on chain ${this.chainId} and CoinGecko ID not registered. Supported symbols: ETH, BTC, BNB, MATIC, AVAX, LINK, UNI, AAVE, USDC, USDT, DAI, and more.`
|
|
616
|
+
);
|
|
617
|
+
}
|
|
618
|
+
/**
|
|
619
|
+
* Get USD prices for multiple tokens in one call.
|
|
620
|
+
* Chainlink feeds are read in parallel; CoinGecko batch-fetches all remaining
|
|
621
|
+
* symbols in a single HTTP request — efficient even for large lists.
|
|
622
|
+
*
|
|
623
|
+
* @param symbols - Array of token symbols: ['ETH', 'BTC', 'USDC']
|
|
624
|
+
*
|
|
625
|
+
* @example
|
|
626
|
+
* const prices = await awarizon.price.getMany(['ETH', 'BTC', 'USDC', 'ARB'])
|
|
627
|
+
* console.log(prices.ETH.price) // 3421.57
|
|
628
|
+
* console.log(prices.ARB.source) // 'coingecko' (no feed on most chains)
|
|
629
|
+
*/
|
|
630
|
+
async getMany(symbols) {
|
|
631
|
+
const syms = symbols.map((s) => s.toUpperCase());
|
|
632
|
+
const chainlinkResults = await Promise.all(
|
|
633
|
+
syms.map((sym) => fetchChainlink(this.publicClient, this.chainId, sym))
|
|
634
|
+
);
|
|
635
|
+
const out = {};
|
|
636
|
+
const needsCG = [];
|
|
637
|
+
for (let i = 0; i < syms.length; i++) {
|
|
638
|
+
const sym = syms[i];
|
|
639
|
+
const cl = chainlinkResults[i];
|
|
640
|
+
if (cl && !cl.stale) {
|
|
641
|
+
out[sym] = cl;
|
|
642
|
+
} else {
|
|
643
|
+
needsCG.push(sym);
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
if (needsCG.length > 0) {
|
|
647
|
+
try {
|
|
648
|
+
const cgPrices = await fetchCoinGecko(needsCG);
|
|
649
|
+
for (const sym of needsCG) {
|
|
650
|
+
const price = cgPrices[sym];
|
|
651
|
+
if (price !== void 0) {
|
|
652
|
+
out[sym] = { symbol: sym, price, source: "coingecko" };
|
|
653
|
+
} else {
|
|
654
|
+
const cl = chainlinkResults[syms.indexOf(sym)];
|
|
655
|
+
if (cl) out[sym] = cl;
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
} catch {
|
|
659
|
+
for (const sym of needsCG) {
|
|
660
|
+
const cl = chainlinkResults[syms.indexOf(sym)];
|
|
661
|
+
if (cl) out[sym] = cl;
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
return out;
|
|
666
|
+
}
|
|
667
|
+
/**
|
|
668
|
+
* Check whether a Chainlink feed exists for the given symbol on the current chain.
|
|
669
|
+
*
|
|
670
|
+
* @example
|
|
671
|
+
* awarizon.price.hasFeed('ETH') // true on mainnet, base, polygon, etc.
|
|
672
|
+
* awarizon.price.hasFeed('ARB') // true on Arbitrum, false elsewhere
|
|
673
|
+
*/
|
|
674
|
+
hasFeed(symbol) {
|
|
675
|
+
return !!CHAINLINK_FEEDS[this.chainId]?.[symbol.toUpperCase()];
|
|
676
|
+
}
|
|
677
|
+
/**
|
|
678
|
+
* Return all symbols that have a Chainlink feed on the current chain.
|
|
679
|
+
*
|
|
680
|
+
* @example
|
|
681
|
+
* awarizon.price.supportedSymbols()
|
|
682
|
+
* // → ['ETH', 'BTC', 'LINK', 'USDC', 'USDT', 'DAI'] on Base
|
|
683
|
+
*/
|
|
684
|
+
supportedSymbols() {
|
|
685
|
+
return Object.keys(CHAINLINK_FEEDS[this.chainId] ?? {});
|
|
686
|
+
}
|
|
687
|
+
};
|
|
364
688
|
var ERC20_ABI = viem.erc20Abi;
|
|
365
689
|
var ERC721_ABI = [
|
|
366
690
|
{ type: "function", name: "name", stateMutability: "view", inputs: [], outputs: [{ type: "string" }] },
|
|
@@ -481,12 +805,13 @@ var AwarizonWeb3 = class {
|
|
|
481
805
|
this.chain = resolveChain(config.chain);
|
|
482
806
|
this.publicClient = viem.createPublicClient({
|
|
483
807
|
chain: this.chain,
|
|
484
|
-
transport:
|
|
808
|
+
transport: getChainTransport(this.chain, config.rpcUrl)
|
|
485
809
|
});
|
|
486
810
|
this._engine = new walletEngine.WalletEngine({
|
|
487
811
|
chain: this.chain,
|
|
488
812
|
publicClient: this.publicClient,
|
|
489
|
-
rpcUrl: config.rpcUrl
|
|
813
|
+
rpcUrl: config.rpcUrl,
|
|
814
|
+
getTransport: (chain) => getChainTransport(chain, config.rpcUrl)
|
|
490
815
|
});
|
|
491
816
|
this._txEngine = new txEngine.TransactionEngine(
|
|
492
817
|
this.publicClient,
|
|
@@ -498,6 +823,7 @@ var AwarizonWeb3 = class {
|
|
|
498
823
|
this._engine,
|
|
499
824
|
() => this._telemetry.ensureValidated()
|
|
500
825
|
);
|
|
826
|
+
this.price = new PriceEngine(this.publicClient, this.chain.id);
|
|
501
827
|
if (config.signer) {
|
|
502
828
|
this._engine.connectExternal(config.signer);
|
|
503
829
|
}
|
|
@@ -1054,16 +1380,20 @@ Object.defineProperty(exports, "parseABI", {
|
|
|
1054
1380
|
});
|
|
1055
1381
|
exports.ApiKeyRequiredError = ApiKeyRequiredError;
|
|
1056
1382
|
exports.AwarizonWeb3 = AwarizonWeb3;
|
|
1383
|
+
exports.CHAINLINK_FEEDS = CHAINLINK_FEEDS;
|
|
1057
1384
|
exports.CHAINS = CHAINS;
|
|
1385
|
+
exports.COINGECKO_IDS = COINGECKO_IDS;
|
|
1058
1386
|
exports.ContractNotLoadedError = ContractNotLoadedError;
|
|
1059
1387
|
exports.ERC1155_ABI = ERC1155_ABI;
|
|
1060
1388
|
exports.ERC20_ABI = ERC20_ABI;
|
|
1061
1389
|
exports.ERC721_ABI = ERC721_ABI;
|
|
1062
1390
|
exports.InvalidApiKeyError = InvalidApiKeyError;
|
|
1063
1391
|
exports.NetworkMismatchError = NetworkMismatchError;
|
|
1392
|
+
exports.PriceEngine = PriceEngine;
|
|
1064
1393
|
exports.ProviderError = ProviderError;
|
|
1065
1394
|
exports.TelemetryClient = TelemetryClient;
|
|
1066
1395
|
exports.UnsupportedChainError = UnsupportedChainError;
|
|
1396
|
+
exports.getChainTransport = getChainTransport;
|
|
1067
1397
|
exports.getSupportedChainIds = getSupportedChainIds;
|
|
1068
1398
|
exports.resolveChain = resolveChain;
|
|
1069
1399
|
//# sourceMappingURL=index.js.map
|