@octaflowlabs/onchain-sdk 1.4.2 → 1.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -1
- package/dist/cjs/constants/BASIC_TOKENS_REGISTRY.d.ts +1 -1
- package/dist/cjs/constants/BASIC_TOKENS_REGISTRY.js +935 -38
- package/dist/cjs/constants/NETWORKS_REGISTRY.js +156 -1
- package/dist/cjs/constants/STABLECOINS_REGISTRY.d.ts +13 -0
- package/dist/cjs/constants/STABLECOINS_REGISTRY.js +101 -0
- package/dist/cjs/index.d.ts +4 -1
- package/dist/cjs/index.js +10 -1
- package/dist/cjs/utils/activityDedupe.d.ts +7 -0
- package/dist/cjs/utils/activityDedupe.js +11 -0
- package/dist/cjs/utils/normalizeAddress.d.ts +1 -0
- package/dist/cjs/utils/normalizeAddress.js +12 -1
- package/dist/cjs/webhooks/alchemyAddressActivity.d.ts +39 -0
- package/dist/cjs/webhooks/alchemyAddressActivity.js +75 -0
- package/dist/constants/BASIC_TOKENS_REGISTRY.d.ts +1 -1
- package/dist/constants/BASIC_TOKENS_REGISTRY.js +935 -38
- package/dist/constants/NETWORKS_REGISTRY.js +156 -1
- package/dist/constants/STABLECOINS_REGISTRY.d.ts +13 -0
- package/dist/constants/STABLECOINS_REGISTRY.js +95 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +4 -1
- package/dist/utils/activityDedupe.d.ts +7 -0
- package/dist/utils/activityDedupe.js +7 -0
- package/dist/utils/normalizeAddress.d.ts +1 -0
- package/dist/utils/normalizeAddress.js +10 -0
- package/dist/webhooks/alchemyAddressActivity.d.ts +39 -0
- package/dist/webhooks/alchemyAddressActivity.js +72 -0
- package/package.json +5 -2
|
@@ -30,10 +30,10 @@ export const NETWORKS_REGISTRY = [
|
|
|
30
30
|
id: 'polygon-mainnet',
|
|
31
31
|
name: 'polygon-mainnet',
|
|
32
32
|
nameForDisplay: 'Polygon Mainnet',
|
|
33
|
-
iconUrl: 'https://assets.coingecko.com/coins/images/4713/large/matic-token-icon.png',
|
|
34
33
|
chainId: 137,
|
|
35
34
|
rpcUrl: 'https://polygon.publicnode.com',
|
|
36
35
|
explorerUrl: 'https://polygonscan.com',
|
|
36
|
+
iconUrl: 'https://assets.coingecko.com/coins/images/4713/large/matic-token-icon.png',
|
|
37
37
|
symbol: 'POL',
|
|
38
38
|
failoverRpcUrl: 'https://polygon.llamarpc.com',
|
|
39
39
|
blockTime: 2,
|
|
@@ -50,6 +50,161 @@ export const NETWORKS_REGISTRY = [
|
|
|
50
50
|
failoverRpcUrl: 'https://arb.llamarpc.com',
|
|
51
51
|
blockTime: 1,
|
|
52
52
|
},
|
|
53
|
+
{
|
|
54
|
+
id: 'optimism-mainnet',
|
|
55
|
+
name: 'op-mainnet',
|
|
56
|
+
nameForDisplay: 'Optimism Mainnet',
|
|
57
|
+
chainId: 10,
|
|
58
|
+
rpcUrl: 'https://mainnet.optimism.io',
|
|
59
|
+
explorerUrl: 'https://optimistic.etherscan.io',
|
|
60
|
+
iconUrl: 'https://assets.coingecko.com/coins/images/25244/large/Optimism.png',
|
|
61
|
+
symbol: 'ETH',
|
|
62
|
+
failoverRpcUrl: 'https://optimism.llamarpc.com',
|
|
63
|
+
blockTime: 2,
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
id: 'base-mainnet',
|
|
67
|
+
name: 'base-mainnet',
|
|
68
|
+
nameForDisplay: 'Base Mainnet',
|
|
69
|
+
chainId: 8453,
|
|
70
|
+
rpcUrl: 'https://mainnet.base.org',
|
|
71
|
+
explorerUrl: 'https://basescan.org',
|
|
72
|
+
iconUrl: 'https://assets.coingecko.com/coins/images/32480/large/base.png',
|
|
73
|
+
symbol: 'ETH',
|
|
74
|
+
failoverRpcUrl: 'https://base.llamarpc.com',
|
|
75
|
+
blockTime: 2,
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
id: 'avalanche-mainnet',
|
|
79
|
+
name: 'avax-mainnet',
|
|
80
|
+
nameForDisplay: 'Avalanche C-Chain',
|
|
81
|
+
chainId: 43114,
|
|
82
|
+
rpcUrl: 'https://api.avax.network/ext/bc/C/rpc',
|
|
83
|
+
explorerUrl: 'https://snowtrace.io',
|
|
84
|
+
iconUrl: 'https://assets.coingecko.com/coins/images/12559/large/Avalanche_Circle_RedWhite_Trans.png',
|
|
85
|
+
symbol: 'AVAX',
|
|
86
|
+
failoverRpcUrl: 'https://avalanche.llamarpc.com',
|
|
87
|
+
blockTime: 2,
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
id: 'hyperevm-mainnet',
|
|
91
|
+
name: 'hyperevm-mainnet',
|
|
92
|
+
nameForDisplay: 'HyperEVM',
|
|
93
|
+
chainId: 999,
|
|
94
|
+
rpcUrl: 'https://hyperliquid-mainnet.g.alchemy.com/v2/YOUR_KEY',
|
|
95
|
+
explorerUrl: 'https://purrsec.com',
|
|
96
|
+
iconUrl: 'https://assets.coingecko.com/coins/images/52510/large/hyperliquid.png',
|
|
97
|
+
symbol: 'HYPE',
|
|
98
|
+
failoverRpcUrl: 'https://rpc.hyperliquid.xyz/evm',
|
|
99
|
+
blockTime: 1,
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
id: 'unichain-mainnet',
|
|
103
|
+
name: 'unichain-mainnet',
|
|
104
|
+
nameForDisplay: 'Unichain Mainnet',
|
|
105
|
+
chainId: 130,
|
|
106
|
+
rpcUrl: 'https://mainnet.unichain.org',
|
|
107
|
+
explorerUrl: 'https://uniscan.xyz',
|
|
108
|
+
iconUrl: 'https://assets.coingecko.com/coins/images/25244/large/Optimism.png',
|
|
109
|
+
symbol: 'ETH',
|
|
110
|
+
failoverRpcUrl: 'https://unichain.llamarpc.com',
|
|
111
|
+
blockTime: 1,
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
id: 'gnosis-mainnet',
|
|
115
|
+
name: 'gnosis-mainnet',
|
|
116
|
+
nameForDisplay: 'Gnosis Chain',
|
|
117
|
+
chainId: 100,
|
|
118
|
+
rpcUrl: 'https://rpc.gnosischain.com',
|
|
119
|
+
explorerUrl: 'https://gnosisscan.io',
|
|
120
|
+
iconUrl: 'https://assets.coingecko.com/coins/images/662/large/logo_square_simple_300px.png',
|
|
121
|
+
symbol: 'xDAI',
|
|
122
|
+
failoverRpcUrl: 'https://gnosis.llamarpc.com',
|
|
123
|
+
blockTime: 5,
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
id: 'mantle-mainnet',
|
|
127
|
+
name: 'mantle-mainnet',
|
|
128
|
+
nameForDisplay: 'Mantle Mainnet',
|
|
129
|
+
chainId: 5000,
|
|
130
|
+
rpcUrl: 'https://rpc.mantle.xyz',
|
|
131
|
+
explorerUrl: 'https://mantlescan.xyz',
|
|
132
|
+
iconUrl: 'https://assets.coingecko.com/coins/images/30980/large/token-logo.png',
|
|
133
|
+
symbol: 'MNT',
|
|
134
|
+
failoverRpcUrl: 'https://mantle.llamarpc.com',
|
|
135
|
+
blockTime: 2,
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
id: 'celo-mainnet',
|
|
139
|
+
name: 'celo-mainnet',
|
|
140
|
+
nameForDisplay: 'Celo Mainnet',
|
|
141
|
+
chainId: 42220,
|
|
142
|
+
rpcUrl: 'https://forno.celo.org',
|
|
143
|
+
explorerUrl: 'https://celoscan.io',
|
|
144
|
+
iconUrl: 'https://assets.coingecko.com/coins/images/11090/large/InjXBNx9_400x400.jpg',
|
|
145
|
+
symbol: 'CELO',
|
|
146
|
+
failoverRpcUrl: 'https://celo.llamarpc.com',
|
|
147
|
+
blockTime: 5,
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
id: 'blast-mainnet',
|
|
151
|
+
name: 'blast-mainnet',
|
|
152
|
+
nameForDisplay: 'Blast Mainnet',
|
|
153
|
+
chainId: 81457,
|
|
154
|
+
rpcUrl: 'https://rpc.blast.io',
|
|
155
|
+
explorerUrl: 'https://blastscan.io',
|
|
156
|
+
iconUrl: 'https://assets.coingecko.com/coins/images/35494/large/Blast.jpg',
|
|
157
|
+
symbol: 'ETH',
|
|
158
|
+
failoverRpcUrl: 'https://blast.llamarpc.com',
|
|
159
|
+
blockTime: 2,
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
id: 'berachain-mainnet',
|
|
163
|
+
name: 'berachain-mainnet',
|
|
164
|
+
nameForDisplay: 'Berachain Mainnet',
|
|
165
|
+
chainId: 80094,
|
|
166
|
+
rpcUrl: 'https://rpc.berachain.com',
|
|
167
|
+
explorerUrl: 'https://berascan.com',
|
|
168
|
+
iconUrl: 'https://assets.coingecko.com/coins/images/36417/large/bera.png',
|
|
169
|
+
symbol: 'BERA',
|
|
170
|
+
failoverRpcUrl: 'https://berachain.llamarpc.com',
|
|
171
|
+
blockTime: 2,
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
id: 'linea-mainnet',
|
|
175
|
+
name: 'linea-mainnet',
|
|
176
|
+
nameForDisplay: 'Linea Mainnet',
|
|
177
|
+
chainId: 59144,
|
|
178
|
+
rpcUrl: 'https://rpc.linea.build',
|
|
179
|
+
explorerUrl: 'https://lineascan.build',
|
|
180
|
+
iconUrl: 'https://assets.coingecko.com/coins/images/32234/large/linea.png',
|
|
181
|
+
symbol: 'ETH',
|
|
182
|
+
failoverRpcUrl: 'https://linea.llamarpc.com',
|
|
183
|
+
blockTime: 2,
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
id: 'scroll-mainnet',
|
|
187
|
+
name: 'scroll-mainnet',
|
|
188
|
+
nameForDisplay: 'Scroll Mainnet',
|
|
189
|
+
chainId: 534352,
|
|
190
|
+
rpcUrl: 'https://rpc.scroll.io',
|
|
191
|
+
explorerUrl: 'https://scrollscan.com',
|
|
192
|
+
iconUrl: 'https://assets.coingecko.com/coins/images/32760/large/scroll.png',
|
|
193
|
+
symbol: 'ETH',
|
|
194
|
+
failoverRpcUrl: 'https://scroll.llamarpc.com',
|
|
195
|
+
blockTime: 3,
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
id: 'plasma-mainnet',
|
|
199
|
+
name: 'plasma-mainnet',
|
|
200
|
+
nameForDisplay: 'Plasma Mainnet',
|
|
201
|
+
chainId: 9745,
|
|
202
|
+
rpcUrl: 'https://rpc.plasma.to',
|
|
203
|
+
explorerUrl: 'https://plasmascan.to',
|
|
204
|
+
iconUrl: '',
|
|
205
|
+
symbol: 'XPL',
|
|
206
|
+
blockTime: 1,
|
|
207
|
+
},
|
|
53
208
|
],
|
|
54
209
|
},
|
|
55
210
|
{
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type StablecoinSymbol = 'USDC' | 'USDT' | 'OSC';
|
|
2
|
+
export interface StablecoinContractData {
|
|
3
|
+
chainId: number;
|
|
4
|
+
symbol: StablecoinSymbol;
|
|
5
|
+
name: string;
|
|
6
|
+
address: string;
|
|
7
|
+
decimals: number;
|
|
8
|
+
}
|
|
9
|
+
export type StablecoinContractsByChainId = Readonly<Record<number, readonly StablecoinContractData[]>>;
|
|
10
|
+
export declare const STABLECOIN_CONTRACTS_BY_CHAIN_ID: StablecoinContractsByChainId;
|
|
11
|
+
export declare const getStablecoinContractsByChainId: (chainId: number | null | undefined) => readonly StablecoinContractData[];
|
|
12
|
+
export declare const getStablecoinContractBySymbolAndChainId: (symbol: StablecoinSymbol, chainId: number | null | undefined) => StablecoinContractData | null;
|
|
13
|
+
export declare const isAllowedStablecoinContract: (chainId: number | null | undefined, contractAddress: string | null | undefined) => boolean;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/** local imports */
|
|
2
|
+
import { normalizeEvmAddress } from '../utils/normalizeAddress';
|
|
3
|
+
export const STABLECOIN_CONTRACTS_BY_CHAIN_ID = {
|
|
4
|
+
1: [
|
|
5
|
+
{
|
|
6
|
+
chainId: 1,
|
|
7
|
+
symbol: 'USDC',
|
|
8
|
+
name: 'USD Coin',
|
|
9
|
+
address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
|
|
10
|
+
decimals: 6,
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
chainId: 1,
|
|
14
|
+
symbol: 'USDT',
|
|
15
|
+
name: 'Tether USD',
|
|
16
|
+
address: '0xdac17f958d2ee523a2206206994597c13d831ec7',
|
|
17
|
+
decimals: 6,
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
56: [
|
|
21
|
+
{
|
|
22
|
+
chainId: 56,
|
|
23
|
+
symbol: 'USDC',
|
|
24
|
+
name: 'USD Coin',
|
|
25
|
+
address: '0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d',
|
|
26
|
+
decimals: 18,
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
chainId: 56,
|
|
30
|
+
symbol: 'USDT',
|
|
31
|
+
name: 'Tether USD',
|
|
32
|
+
address: '0x55d398326f99059ff775485246999027b3197955',
|
|
33
|
+
decimals: 18,
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
137: [
|
|
37
|
+
{
|
|
38
|
+
chainId: 137,
|
|
39
|
+
symbol: 'USDC',
|
|
40
|
+
name: 'USD Coin Bridged',
|
|
41
|
+
address: '0x2791bca1f2de4661ed88a30c99a7a9449aa84174',
|
|
42
|
+
decimals: 6,
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
chainId: 137,
|
|
46
|
+
symbol: 'USDC',
|
|
47
|
+
name: 'USD Coin',
|
|
48
|
+
address: '0x3c499c542cef5e3811e1192ce70d8cc03d5c3359',
|
|
49
|
+
decimals: 6,
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
chainId: 137,
|
|
53
|
+
symbol: 'USDT',
|
|
54
|
+
name: 'Tether USD',
|
|
55
|
+
address: '0xc2132d05d31c914a87c6611c10748aeb04b58e8f',
|
|
56
|
+
decimals: 6,
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
11155111: [
|
|
60
|
+
{
|
|
61
|
+
chainId: 11155111,
|
|
62
|
+
symbol: 'USDC',
|
|
63
|
+
name: 'Sepolia USDC',
|
|
64
|
+
address: '0x1c7d4b196cb0c7b01d743fbc6116a902379c7238',
|
|
65
|
+
decimals: 6,
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
chainId: 11155111,
|
|
69
|
+
symbol: 'OSC',
|
|
70
|
+
name: 'OSC Test Stablecoin',
|
|
71
|
+
address: '0x4357555de1c8ed60218dd42b0b4f404e31b6d744',
|
|
72
|
+
decimals: 6,
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
};
|
|
76
|
+
export const getStablecoinContractsByChainId = (chainId) => {
|
|
77
|
+
if (chainId == null)
|
|
78
|
+
return [];
|
|
79
|
+
return STABLECOIN_CONTRACTS_BY_CHAIN_ID[chainId] || [];
|
|
80
|
+
};
|
|
81
|
+
export const getStablecoinContractBySymbolAndChainId = (symbol, chainId) => {
|
|
82
|
+
const contracts = getStablecoinContractsByChainId(chainId);
|
|
83
|
+
return contracts.find((contract) => contract.symbol === symbol) || null;
|
|
84
|
+
};
|
|
85
|
+
export const isAllowedStablecoinContract = (chainId, contractAddress) => {
|
|
86
|
+
if (chainId == null)
|
|
87
|
+
return false;
|
|
88
|
+
const normalizedAddress = normalizeEvmAddress(contractAddress);
|
|
89
|
+
if (!normalizedAddress)
|
|
90
|
+
return false;
|
|
91
|
+
const allowedContracts = getStablecoinContractsByChainId(chainId);
|
|
92
|
+
if (!allowedContracts.length)
|
|
93
|
+
return false;
|
|
94
|
+
return allowedContracts.some((contract) => contract.address === normalizedAddress);
|
|
95
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export { ERC20_TOKEN_CONTRACT_ABI };
|
|
|
5
5
|
export { GAS_LIMIT_PER_TX_TYPE, MULTICALL3_ADDRESS } from './constants/constants';
|
|
6
6
|
export { NetworkField, NetworkRegistry, NETWORKS_REGISTRY } from './constants/NETWORKS_REGISTRY';
|
|
7
7
|
export { BASIC_TOKENS_BY_CHAIN, BasicTokenData, BasicTokenSymbol, ChainTokenDataMap, } from './constants/BASIC_TOKENS_REGISTRY';
|
|
8
|
+
export { STABLECOIN_CONTRACTS_BY_CHAIN_ID, getStablecoinContractBySymbolAndChainId, getStablecoinContractsByChainId, isAllowedStablecoinContract, StablecoinContractData, StablecoinContractsByChainId, StablecoinSymbol, } from './constants/STABLECOINS_REGISTRY';
|
|
8
9
|
/** basic blockchain exports */
|
|
9
10
|
export { buildBaseUnsignedTransferTx, buildMaxNativeTransferTx, buildUnsignedTransferTx, } from './blockchain/buildUnsignedTransferTx';
|
|
10
11
|
export { broadcastTransaction } from './blockchain/broadcastTransaction';
|
|
@@ -26,8 +27,10 @@ import NATIVE_TOKENS from './utils/tokens';
|
|
|
26
27
|
export { NATIVE_TOKENS };
|
|
27
28
|
export { formattedAmountForDisplay, parsedAmount } from './utils/formatAmount';
|
|
28
29
|
export { handleErrorMessages, errorMessagesForBroadcast, errorMessagesForGasLimitEstimation, } from './utils/handleErrorMessages';
|
|
29
|
-
export { normalizeAddress } from './utils/normalizeAddress';
|
|
30
|
+
export { normalizeAddress, normalizeEvmAddress } from './utils/normalizeAddress';
|
|
30
31
|
export { toGwei, tryParseGweiToWei, parseGasLimit } from './utils/parseGasFees';
|
|
31
32
|
export { getFeePresets, calcReserve, estimateSeconds, getBlockTime, BLOCK_TIME_BY_CHAIN, } from './utils/feePresets';
|
|
33
|
+
/** webhook exports */
|
|
34
|
+
export { extractPoolInboundStablecoinEvents } from './webhooks/alchemyAddressActivity';
|
|
32
35
|
/** types exports */
|
|
33
36
|
export { BroadcastTransactionOptions, BuildMaxNativeTransferTxOptions, BuildUnsignedTransferTxOptions, EstimateGasLimitFromProviderProps, GasEstimateResult, TxStatusOptions, BuildBaseUnsignedTransferTxParams, TxStatusResponse, EstimateTransactionOptions, EstimateTransactionResult, PrepareTransactionParams, PrepareTransactionResult, FormatAmountOptions, TransactionRequest, GetBalanceParams, GetBalancesParams, GetBalancesChainRequest, GetBalanceResult, ChainBalances, TokenBalance, ChainGroup, FeePreset, FeePresetLabel, FeeEstimateSeconds, ResolvedFees, EIP1559Fees, LegacyFees, FeeModel, FeeHistoryData, FeeDataInput, } from './types/common';
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@ export { ERC20_TOKEN_CONTRACT_ABI };
|
|
|
5
5
|
export { GAS_LIMIT_PER_TX_TYPE, MULTICALL3_ADDRESS } from './constants/constants';
|
|
6
6
|
export { NETWORKS_REGISTRY } from './constants/NETWORKS_REGISTRY';
|
|
7
7
|
export { BASIC_TOKENS_BY_CHAIN, } from './constants/BASIC_TOKENS_REGISTRY';
|
|
8
|
+
export { STABLECOIN_CONTRACTS_BY_CHAIN_ID, getStablecoinContractBySymbolAndChainId, getStablecoinContractsByChainId, isAllowedStablecoinContract, } from './constants/STABLECOINS_REGISTRY';
|
|
8
9
|
/** basic blockchain exports */
|
|
9
10
|
export { buildBaseUnsignedTransferTx, buildMaxNativeTransferTx, buildUnsignedTransferTx, } from './blockchain/buildUnsignedTransferTx';
|
|
10
11
|
export { broadcastTransaction } from './blockchain/broadcastTransaction';
|
|
@@ -25,6 +26,8 @@ import NATIVE_TOKENS from './utils/tokens';
|
|
|
25
26
|
export { NATIVE_TOKENS };
|
|
26
27
|
export { formattedAmountForDisplay, parsedAmount } from './utils/formatAmount';
|
|
27
28
|
export { handleErrorMessages, errorMessagesForBroadcast, errorMessagesForGasLimitEstimation, } from './utils/handleErrorMessages';
|
|
28
|
-
export { normalizeAddress } from './utils/normalizeAddress';
|
|
29
|
+
export { normalizeAddress, normalizeEvmAddress } from './utils/normalizeAddress';
|
|
29
30
|
export { toGwei, tryParseGweiToWei, parseGasLimit } from './utils/parseGasFees';
|
|
30
31
|
export { getFeePresets, calcReserve, estimateSeconds, getBlockTime, BLOCK_TIME_BY_CHAIN, } from './utils/feePresets';
|
|
32
|
+
/** webhook exports */
|
|
33
|
+
export { extractPoolInboundStablecoinEvents } from './webhooks/alchemyAddressActivity';
|
|
@@ -9,3 +9,13 @@ export const normalizeAddress = (address) => {
|
|
|
9
9
|
throw new Error('Error normalizing address: ' + (e instanceof Error ? e.message : String(e)));
|
|
10
10
|
}
|
|
11
11
|
};
|
|
12
|
+
export const normalizeEvmAddress = (address) => {
|
|
13
|
+
if (!address || typeof address !== 'string')
|
|
14
|
+
return null;
|
|
15
|
+
try {
|
|
16
|
+
return normalizeAddress(address.trim()).toLowerCase();
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export interface AlchemyAddressActivity {
|
|
2
|
+
category?: string;
|
|
3
|
+
asset?: string;
|
|
4
|
+
value?: number | null;
|
|
5
|
+
fromAddress?: string | null;
|
|
6
|
+
toAddress?: string | null;
|
|
7
|
+
hash?: string | null;
|
|
8
|
+
erc721TokenId?: string | number | null;
|
|
9
|
+
rawContract?: {
|
|
10
|
+
address?: string | null;
|
|
11
|
+
} | null;
|
|
12
|
+
log?: {
|
|
13
|
+
removed?: boolean;
|
|
14
|
+
logIndex?: string | null;
|
|
15
|
+
} | null;
|
|
16
|
+
}
|
|
17
|
+
export interface AlchemyAddressActivityPayload {
|
|
18
|
+
id?: string;
|
|
19
|
+
webhookId?: string;
|
|
20
|
+
type?: string;
|
|
21
|
+
event?: {
|
|
22
|
+
network?: string;
|
|
23
|
+
activity?: AlchemyAddressActivity[];
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export interface PoolInboundStablecoinEvent {
|
|
27
|
+
webhookDeliveryId?: string;
|
|
28
|
+
webhookId?: string;
|
|
29
|
+
alchemyNetwork: string;
|
|
30
|
+
chainId: number | null;
|
|
31
|
+
txHash: string;
|
|
32
|
+
fromAddress: string;
|
|
33
|
+
toAddress: string;
|
|
34
|
+
amount: number;
|
|
35
|
+
asset: string;
|
|
36
|
+
tokenContractAddress?: string | null;
|
|
37
|
+
dedupeKey: string;
|
|
38
|
+
}
|
|
39
|
+
export declare function extractPoolInboundStablecoinEvents(payload: AlchemyAddressActivityPayload, poolAddress: string | null | undefined): PoolInboundStablecoinEvent[];
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/** local imports */
|
|
2
|
+
import { isAllowedStablecoinContract } from '../constants/STABLECOINS_REGISTRY';
|
|
3
|
+
import { getTransactionActivityDedupeKey } from '../utils/activityDedupe';
|
|
4
|
+
import { normalizeEvmAddress } from '../utils/normalizeAddress';
|
|
5
|
+
const CHAIN_ID_TO_ALCHEMY_NETWORK = {
|
|
6
|
+
1: 'ETH_MAINNET',
|
|
7
|
+
56: 'BNB_MAINNET',
|
|
8
|
+
137: 'MATIC_MAINNET',
|
|
9
|
+
11155111: 'ETH_SEPOLIA',
|
|
10
|
+
};
|
|
11
|
+
const ALCHEMY_NETWORK_TO_CHAIN_ID = Object.fromEntries(Object.entries(CHAIN_ID_TO_ALCHEMY_NETWORK).map(([chainId, network]) => [
|
|
12
|
+
network,
|
|
13
|
+
Number(chainId),
|
|
14
|
+
]));
|
|
15
|
+
function chainIdFromAlchemyNetwork(network) {
|
|
16
|
+
if (!network)
|
|
17
|
+
return null;
|
|
18
|
+
const chainId = ALCHEMY_NETWORK_TO_CHAIN_ID[network];
|
|
19
|
+
return chainId === undefined ? null : chainId;
|
|
20
|
+
}
|
|
21
|
+
export function extractPoolInboundStablecoinEvents(payload, poolAddress) {
|
|
22
|
+
const poolAddressLower = normalizeEvmAddress(poolAddress);
|
|
23
|
+
if (!poolAddressLower)
|
|
24
|
+
return [];
|
|
25
|
+
if (payload.type !== 'ADDRESS_ACTIVITY')
|
|
26
|
+
return [];
|
|
27
|
+
const network = payload.event?.network;
|
|
28
|
+
const chainId = chainIdFromAlchemyNetwork(network);
|
|
29
|
+
const activity = payload.event?.activity;
|
|
30
|
+
if (!activity?.length)
|
|
31
|
+
return [];
|
|
32
|
+
const out = [];
|
|
33
|
+
for (const item of activity) {
|
|
34
|
+
if (item.category !== 'token')
|
|
35
|
+
continue;
|
|
36
|
+
if (item.log?.removed === true)
|
|
37
|
+
continue;
|
|
38
|
+
if (item.erc721TokenId != null && item.erc721TokenId !== '')
|
|
39
|
+
continue;
|
|
40
|
+
if (!isAllowedStablecoinContract(chainId, item.rawContract?.address))
|
|
41
|
+
continue;
|
|
42
|
+
const value = item.value;
|
|
43
|
+
if (value === undefined || value === null || typeof value !== 'number' || !(value > 0))
|
|
44
|
+
continue;
|
|
45
|
+
const to = normalizeEvmAddress(item.toAddress);
|
|
46
|
+
const from = normalizeEvmAddress(item.fromAddress);
|
|
47
|
+
if (!to || !from)
|
|
48
|
+
continue;
|
|
49
|
+
if (to !== poolAddressLower)
|
|
50
|
+
continue;
|
|
51
|
+
const txHash = item.hash?.trim();
|
|
52
|
+
if (!txHash)
|
|
53
|
+
continue;
|
|
54
|
+
const dedupeKey = getTransactionActivityDedupeKey(item);
|
|
55
|
+
if (!dedupeKey)
|
|
56
|
+
continue;
|
|
57
|
+
out.push({
|
|
58
|
+
webhookDeliveryId: payload.id,
|
|
59
|
+
webhookId: payload.webhookId,
|
|
60
|
+
alchemyNetwork: network || 'UNKNOWN',
|
|
61
|
+
chainId,
|
|
62
|
+
txHash,
|
|
63
|
+
fromAddress: from,
|
|
64
|
+
toAddress: to,
|
|
65
|
+
amount: value,
|
|
66
|
+
asset: item.asset || '',
|
|
67
|
+
tokenContractAddress: item.rawContract?.address,
|
|
68
|
+
dedupeKey,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
return out;
|
|
72
|
+
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@octaflowlabs/onchain-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.1",
|
|
4
4
|
"description": "onchain methods for web3",
|
|
5
|
-
"repository": {
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/octaflowlabs/onchain-sdk.git"
|
|
8
|
+
},
|
|
6
9
|
"license": "MIT",
|
|
7
10
|
"main": "dist/cjs/index.js",
|
|
8
11
|
"module": "dist/index.js",
|