@provex/utils 1.0.16
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 +287 -0
- package/dist/scripts/convert-svg.d.ts +1 -0
- package/dist/scripts/convert-svg.js +17 -0
- package/dist/src/chain.d.ts +14 -0
- package/dist/src/chain.js +18 -0
- package/dist/src/contracts.d.ts +30 -0
- package/dist/src/contracts.js +64 -0
- package/dist/src/conversionRates.d.ts +124 -0
- package/dist/src/conversionRates.js +219 -0
- package/dist/src/currencies.d.ts +144 -0
- package/dist/src/currencies.js +234 -0
- package/dist/src/data/countries.json +1099 -0
- package/dist/src/deposit.d.ts +1 -0
- package/dist/src/deposit.js +1 -0
- package/dist/src/events.d.ts +3 -0
- package/dist/src/events.js +16 -0
- package/dist/src/flags.d.ts +2 -0
- package/dist/src/flags.js +3 -0
- package/dist/src/ids.d.ts +72 -0
- package/dist/src/ids.js +81 -0
- package/dist/src/index.d.ts +16 -0
- package/dist/src/index.js +16 -0
- package/dist/src/input.d.ts +7 -0
- package/dist/src/input.js +35 -0
- package/dist/src/intent.d.ts +14 -0
- package/dist/src/intent.js +1 -0
- package/dist/src/json.d.ts +18 -0
- package/dist/src/json.js +44 -0
- package/dist/src/participants.d.ts +7 -0
- package/dist/src/participants.js +13 -0
- package/dist/src/payment.d.ts +164 -0
- package/dist/src/payment.js +439 -0
- package/dist/src/profit.d.ts +28 -0
- package/dist/src/profit.js +34 -0
- package/dist/src/sort.d.ts +36 -0
- package/dist/src/sort.js +39 -0
- package/dist/src/stats.d.ts +7 -0
- package/dist/src/stats.js +8 -0
- package/dist/src/time.d.ts +54 -0
- package/dist/src/time.js +106 -0
- package/dist/src/tokens.d.ts +3675 -0
- package/dist/src/tokens.js +134 -0
- package/dist/src/units.d.ts +17 -0
- package/dist/src/units.js +79 -0
- package/dist/src/zkp2p-types.d.ts +48 -0
- package/dist/src/zkp2p-types.js +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +45 -0
- package/scripts/convert-svg.ts +22 -0
- package/src/chain.ts +27 -0
- package/src/contracts.ts +89 -0
- package/src/conversionRates.ts +356 -0
- package/src/currencies.ts +286 -0
- package/src/data/countries.json +1099 -0
- package/src/deposit.ts +2 -0
- package/src/events.ts +21 -0
- package/src/flags/eur.svg +4 -0
- package/src/flags/usd.svg +25 -0
- package/src/flags.ts +4 -0
- package/src/global.d.ts +9 -0
- package/src/ids.ts +137 -0
- package/src/index.ts +16 -0
- package/src/input.ts +35 -0
- package/src/intent.ts +15 -0
- package/src/json.ts +42 -0
- package/src/participants.ts +14 -0
- package/src/payment.ts +573 -0
- package/src/profit.ts +55 -0
- package/src/sort.ts +49 -0
- package/src/stats.ts +10 -0
- package/src/time.ts +123 -0
- package/src/tokens.ts +159 -0
- package/src/units.ts +120 -0
- package/src/zkp2p-types.ts +55 -0
- package/tsconfig.json +18 -0
package/src/time.ts
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/** Interval in milliseconds */
|
|
2
|
+
export const intervalIn = {
|
|
3
|
+
yearInDays: 365,
|
|
4
|
+
quarterInMonths: 3,
|
|
5
|
+
monthInDays: 30,
|
|
6
|
+
hourInDays: 24,
|
|
7
|
+
daysInWeek: 7,
|
|
8
|
+
minuteInHours: 60,
|
|
9
|
+
secondInMinutes: 60,
|
|
10
|
+
millisecondInSecond: 1000,
|
|
11
|
+
} as const
|
|
12
|
+
const second = intervalIn.millisecondInSecond
|
|
13
|
+
const minute = intervalIn.secondInMinutes * second
|
|
14
|
+
const hour = intervalIn.minuteInHours * minute
|
|
15
|
+
const day = intervalIn.hourInDays * hour
|
|
16
|
+
const month = intervalIn.monthInDays * day
|
|
17
|
+
const year = intervalIn.yearInDays * month
|
|
18
|
+
|
|
19
|
+
/** Intervals in milliseconds */
|
|
20
|
+
export const interval = {
|
|
21
|
+
second,
|
|
22
|
+
minute,
|
|
23
|
+
hour,
|
|
24
|
+
day,
|
|
25
|
+
month,
|
|
26
|
+
year,
|
|
27
|
+
} as const
|
|
28
|
+
|
|
29
|
+
/** Default display intervals */
|
|
30
|
+
export const defaultDisplayInterval = {
|
|
31
|
+
hour: 7 * 24,
|
|
32
|
+
day: 6 * 30,
|
|
33
|
+
month: 60,
|
|
34
|
+
} as const
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Format a timestamp
|
|
38
|
+
* @param timestamp - The timestamp to format
|
|
39
|
+
* @param param1.anchor - The anchor date
|
|
40
|
+
* @param param1.showSeconds - Whether to show seconds
|
|
41
|
+
* @returns The formatted timestamp
|
|
42
|
+
*/
|
|
43
|
+
export const formatTimestamp = (timestamp: number | Date | string, {
|
|
44
|
+
anchor = new Date(),
|
|
45
|
+
showSeconds = false,
|
|
46
|
+
}: {
|
|
47
|
+
anchor?: Date,
|
|
48
|
+
showSeconds?: boolean,
|
|
49
|
+
} = {}) => {
|
|
50
|
+
const date = new Date(timestamp)
|
|
51
|
+
const diffMs = anchor.getTime() - date.getTime()
|
|
52
|
+
const diffMins = Math.floor(diffMs / interval.minute)
|
|
53
|
+
const diffHours = Math.floor(diffMs / interval.hour)
|
|
54
|
+
const diffDays = Math.floor(diffMs / interval.day)
|
|
55
|
+
const diffMonths = Math.floor(diffDays / interval.month)
|
|
56
|
+
if (diffMonths > 0) {
|
|
57
|
+
if (diffMonths < intervalIn.quarterInMonths) {
|
|
58
|
+
return `${diffMonths}mo ${diffDays % intervalIn.monthInDays}d ago`
|
|
59
|
+
}
|
|
60
|
+
return `${diffMonths}mo ago`
|
|
61
|
+
}
|
|
62
|
+
if (diffMins < 1) {
|
|
63
|
+
if (showSeconds) {
|
|
64
|
+
if (diffMs < 10 * interval.second) {
|
|
65
|
+
return 'Just now'
|
|
66
|
+
}
|
|
67
|
+
return `${Math.floor(diffMs / interval.second)}s ago`
|
|
68
|
+
}
|
|
69
|
+
return 'Just now'
|
|
70
|
+
}
|
|
71
|
+
if (diffMins < intervalIn.secondInMinutes) {
|
|
72
|
+
return `${diffMins}m ago`
|
|
73
|
+
} else if (diffHours < intervalIn.hourInDays) {
|
|
74
|
+
if (diffHours < 6) {
|
|
75
|
+
return `${diffHours}h ${diffMins % intervalIn.minuteInHours}m ago`
|
|
76
|
+
}
|
|
77
|
+
return `${diffHours}h ago`
|
|
78
|
+
} else {
|
|
79
|
+
if (diffDays < intervalIn.daysInWeek) {
|
|
80
|
+
return `${diffDays}d ${diffHours % intervalIn.hourInDays}h ago`
|
|
81
|
+
}
|
|
82
|
+
return `${diffDays}d ago`
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Format a duration
|
|
88
|
+
* @param param0.start - The start date
|
|
89
|
+
* @param param0.until - The end date
|
|
90
|
+
* @returns The formatted duration
|
|
91
|
+
*/
|
|
92
|
+
export const formatDuration = ({
|
|
93
|
+
start = new Date(),
|
|
94
|
+
until = new Date(),
|
|
95
|
+
}: {
|
|
96
|
+
start?: Date,
|
|
97
|
+
until?: Date,
|
|
98
|
+
} = {}) => {
|
|
99
|
+
const diffMs = until.getTime() - start.getTime()
|
|
100
|
+
const diffMins = Math.floor(diffMs / interval.minute)
|
|
101
|
+
const diffHours = Math.floor(diffMs / interval.hour)
|
|
102
|
+
const diffDays = Math.floor(diffMs / interval.day)
|
|
103
|
+
const diffMonths = Math.floor(diffDays / intervalIn.monthInDays)
|
|
104
|
+
if (diffMonths > 0) {
|
|
105
|
+
return `${diffMonths}mo ${diffDays % intervalIn.monthInDays}d`
|
|
106
|
+
}
|
|
107
|
+
if (diffDays > 0) {
|
|
108
|
+
return `${diffDays}d ${diffHours % intervalIn.hourInDays}h`
|
|
109
|
+
}
|
|
110
|
+
if (diffHours > 0) {
|
|
111
|
+
return `${diffHours}h ${diffMins % intervalIn.minuteInHours}m`
|
|
112
|
+
}
|
|
113
|
+
return `${diffMins % intervalIn.minuteInHours}m`
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Sleep for a given number of milliseconds
|
|
118
|
+
* @param ms - The number of milliseconds to sleep
|
|
119
|
+
* @returns A promise that resolves after the given number of milliseconds
|
|
120
|
+
*/
|
|
121
|
+
export const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms))
|
|
122
|
+
|
|
123
|
+
export type TimeResolutionKey = "hour" | "day" | "month"
|
package/src/tokens.ts
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createPublicClient, getAddress, http, type Chain
|
|
3
|
+
} from 'viem'
|
|
4
|
+
import { base, pulsechain } from 'viem/chains'
|
|
5
|
+
import { chains, type ChainId } from './chain.js'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Complete token information including address, symbol, name, and decimals.
|
|
9
|
+
* This is the root interface for all token-related operations.
|
|
10
|
+
*/
|
|
11
|
+
export interface TokenInfo {
|
|
12
|
+
address: string
|
|
13
|
+
decimals: number
|
|
14
|
+
symbol: string
|
|
15
|
+
name: string
|
|
16
|
+
chainId: ChainId
|
|
17
|
+
mainnetAddress?: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const BASE_USDC = {
|
|
21
|
+
address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
|
|
22
|
+
decimals: 6,
|
|
23
|
+
symbol: 'USDC',
|
|
24
|
+
name: 'USD Coin',
|
|
25
|
+
chainId: base.id,
|
|
26
|
+
} as TokenInfo
|
|
27
|
+
|
|
28
|
+
export const PULSECHAIN_USDC = {
|
|
29
|
+
address: '0x15D38573d2feeb82e7ad5187aB8c1D52810B1f07',
|
|
30
|
+
decimals: 6,
|
|
31
|
+
symbol: 'USDC',
|
|
32
|
+
name: 'USD Coin from Ethereum',
|
|
33
|
+
chainId: pulsechain.id,
|
|
34
|
+
mainnetAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
|
|
35
|
+
} as TokenInfo
|
|
36
|
+
|
|
37
|
+
/** All tokens info */
|
|
38
|
+
export const allTokensInfo = {
|
|
39
|
+
[base.id]: {
|
|
40
|
+
// Base Network Tokens
|
|
41
|
+
USDC: BASE_USDC,
|
|
42
|
+
// USDT: {
|
|
43
|
+
// address: '0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2',
|
|
44
|
+
// decimals: 6,
|
|
45
|
+
// symbol: 'USDT',
|
|
46
|
+
// name: 'Tether USD',
|
|
47
|
+
// chainId: base.id,
|
|
48
|
+
// } as TokenInfo,
|
|
49
|
+
// ETH: {
|
|
50
|
+
// address: '0x4200000000000000000000000000000000000006',
|
|
51
|
+
// decimals: 18,
|
|
52
|
+
// symbol: 'WETH',
|
|
53
|
+
// name: 'Wrapped Ether',
|
|
54
|
+
// chainId: base.id,
|
|
55
|
+
// } as TokenInfo,
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
// [mainnet.id]: {
|
|
59
|
+
// // Ethereum Mainnet Tokens
|
|
60
|
+
// USDC: {
|
|
61
|
+
// address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
|
|
62
|
+
// decimals: 6,
|
|
63
|
+
// symbol: 'USDC',
|
|
64
|
+
// name: 'USD Coin',
|
|
65
|
+
// chainId: mainnet.id,
|
|
66
|
+
// } as TokenInfo,
|
|
67
|
+
// USDT: {
|
|
68
|
+
// address: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
|
|
69
|
+
// decimals: 6,
|
|
70
|
+
// symbol: 'USDT',
|
|
71
|
+
// name: 'Tether USD',
|
|
72
|
+
// chainId: mainnet.id,
|
|
73
|
+
// } as TokenInfo,
|
|
74
|
+
// WETH: {
|
|
75
|
+
// address: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
|
|
76
|
+
// decimals: 18,
|
|
77
|
+
// symbol: 'WETH',
|
|
78
|
+
// name: 'Wrapped Ether',
|
|
79
|
+
// chainId: mainnet.id,
|
|
80
|
+
// } as TokenInfo,
|
|
81
|
+
// ETH: {
|
|
82
|
+
// address: zeroAddress,
|
|
83
|
+
// decimals: 18,
|
|
84
|
+
// symbol: 'ETH',
|
|
85
|
+
// name: 'Ether',
|
|
86
|
+
// chainId: mainnet.id,
|
|
87
|
+
// } as TokenInfo,
|
|
88
|
+
// DAI: {
|
|
89
|
+
// address: '0x6B175474E89094C44Da98b954EedeAC495271d0F',
|
|
90
|
+
// decimals: 18,
|
|
91
|
+
// symbol: 'DAI',
|
|
92
|
+
// name: 'Dai Stablecoin',
|
|
93
|
+
// chainId: mainnet.id,
|
|
94
|
+
// } as TokenInfo,
|
|
95
|
+
// },
|
|
96
|
+
[pulsechain.id]: {
|
|
97
|
+
USDC: PULSECHAIN_USDC,
|
|
98
|
+
},
|
|
99
|
+
// USDT: {
|
|
100
|
+
// address: '0x0Cb6F5a34ad42ec934882A05265A7d5F59b51A2f',
|
|
101
|
+
// decimals: 6,
|
|
102
|
+
// symbol: 'USDT',
|
|
103
|
+
// name: 'Tether USD from Ethereum',
|
|
104
|
+
// chainId: pulsechain.id,
|
|
105
|
+
// mainnetAddress: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
|
|
106
|
+
// } as TokenInfo,
|
|
107
|
+
// ETH: {
|
|
108
|
+
// address: '0x02DcdD04e3F455D838cd1249292C58f3B79e3C3C',
|
|
109
|
+
// decimals: 18,
|
|
110
|
+
// symbol: 'WETH',
|
|
111
|
+
// name: 'Wrapped Ether from Ethereum',
|
|
112
|
+
// chainId: pulsechain.id,
|
|
113
|
+
// mainnetAddress: '0x0000000000000000000000000000000000000000',
|
|
114
|
+
// } as TokenInfo,
|
|
115
|
+
} as Record<ChainId, Record<string, TokenInfo>>
|
|
116
|
+
|
|
117
|
+
export const getDefaultToken = (chainId: ChainId | null) => {
|
|
118
|
+
return allTokensInfo[chainId ?? pulsechain.id]?.USDC ?? null
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export const getDefaultTokens = (chainIds: ChainId[]) => {
|
|
122
|
+
return chainIds.length ? chainIds.map((chainId) => getDefaultToken(chainId)) : chains.map((chain) => getDefaultToken(chain.id))
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Get tokens by chain ID
|
|
127
|
+
* @param chainId - The chain ID
|
|
128
|
+
* @returns Array of tokens for that chain
|
|
129
|
+
*/
|
|
130
|
+
export const getTokensByChainId = (chainId: ChainId): TokenInfo[] => {
|
|
131
|
+
return Object.values(allTokensInfo[chainId] ?? {})
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Get a token by address
|
|
136
|
+
* @param address - The address of the token
|
|
137
|
+
* @returns The token info
|
|
138
|
+
*/
|
|
139
|
+
export const tokenByAddress = (chainId: ChainId, address: string | undefined): TokenInfo | null => {
|
|
140
|
+
return !address ? null : Object.values(allTokensInfo[chainId] ?? {}).find(token => getAddress(token.address) === getAddress(address)) ?? null
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Create a public client for reading from contracts
|
|
145
|
+
* @param chain - The chain
|
|
146
|
+
* @returns The public client
|
|
147
|
+
*/
|
|
148
|
+
export const publicClient = (chain: Chain) => createPublicClient({
|
|
149
|
+
chain,
|
|
150
|
+
transport: http()
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
// export const pulseChainTokenToMainnet = (pulsechainToken: TokenInfo) => {
|
|
154
|
+
// const tokens = allTokensInfo[mainnet.id]
|
|
155
|
+
// const token = Object.values(tokens).find((t) => (
|
|
156
|
+
// getAddress(t.address) === getAddress(pulsechainToken.mainnetAddress!)
|
|
157
|
+
// ))
|
|
158
|
+
// return token!
|
|
159
|
+
// }
|
package/src/units.ts
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { formatUnits as viemFormatUnits, parseUnits as viemParseUnits } from 'viem'
|
|
2
|
+
import type { TokenInfo } from './tokens.js'
|
|
3
|
+
|
|
4
|
+
export const oneEther = 10n ** 18n
|
|
5
|
+
|
|
6
|
+
// Add thousands separators to a number string
|
|
7
|
+
export function addThousandsSeparator(numberString: string, delimiter: string = ','): string {
|
|
8
|
+
let [integerPart, fractionalPart] = numberString.split('.')
|
|
9
|
+
|
|
10
|
+
integerPart = integerPart || '0'
|
|
11
|
+
fractionalPart = fractionalPart || ''
|
|
12
|
+
|
|
13
|
+
// Add thousands separators to integer part
|
|
14
|
+
const formattedInteger = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, delimiter)
|
|
15
|
+
|
|
16
|
+
// Return with fractional part if it exists
|
|
17
|
+
return fractionalPart ? `${formattedInteger}.${fractionalPart}` : formattedInteger
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// // Format currency amounts with exactly 2 decimal places and thousands separators
|
|
21
|
+
// export function formatCurrencyDisplay(amount: bigint, decimals: number): string {
|
|
22
|
+
// const formatted = formatUnits(amount, decimals)
|
|
23
|
+
// const [integerPart, fractionalPart = ''] = formatted.split('.')
|
|
24
|
+
|
|
25
|
+
// // Ensure exactly 2 decimal places for currency
|
|
26
|
+
// const paddedFractional = fractionalPart.padEnd(2, '0').substring(0, 2)
|
|
27
|
+
// const numberString = `${integerPart}.${paddedFractional}`
|
|
28
|
+
|
|
29
|
+
// // Add thousands separators for better readability
|
|
30
|
+
// return addThousandsSeparator(numberString)
|
|
31
|
+
// }
|
|
32
|
+
|
|
33
|
+
// Options for formatRateDisplay function
|
|
34
|
+
export interface FormatRateDisplayOptions {
|
|
35
|
+
decimals: number
|
|
36
|
+
truncateDecimals?: number
|
|
37
|
+
padDecimals?: number
|
|
38
|
+
cutoff?: bigint
|
|
39
|
+
delimiter?: string
|
|
40
|
+
roundUp?: boolean
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export const parseUnits = (amount: string, options: Pick<FormatRateDisplayOptions, 'decimals' | 'delimiter'>): bigint => {
|
|
44
|
+
return viemParseUnits(amount.split(options.delimiter ?? ',').join(''), options.decimals)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Format exchange rates with natural precision, minimum 2 decimal places and thousands separators
|
|
48
|
+
export function formatUnits(amount: bigint, options: FormatRateDisplayOptions): string {
|
|
49
|
+
const { decimals, truncateDecimals, padDecimals = 0, delimiter = ',', cutoff, roundUp = false } = options
|
|
50
|
+
if (cutoff && amount < cutoff) {
|
|
51
|
+
return `<${formatUnits(cutoff, { ...options, truncateDecimals: 0, cutoff: undefined })}`
|
|
52
|
+
}
|
|
53
|
+
if (roundUp && truncateDecimals !== undefined) {
|
|
54
|
+
// const minimumDecimal = decimals - truncateDecimals
|
|
55
|
+
const minimumDecimal = BigInt(decimals - truncateDecimals)
|
|
56
|
+
const minimalMod = amount % (10n ** minimumDecimal)
|
|
57
|
+
const halfMinimalDecimal = (10n ** minimumDecimal) / 2n
|
|
58
|
+
if (minimalMod >= halfMinimalDecimal) {
|
|
59
|
+
amount = amount + (10n ** minimumDecimal) - minimalMod
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const formatted = viemFormatUnits(amount, decimals)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
const [integerPart, fractionalPart = ''] = formatted.split('.')
|
|
66
|
+
|
|
67
|
+
// If truncateDecimals is specified, limit decimal places
|
|
68
|
+
let finalFractionalPart = fractionalPart
|
|
69
|
+
if (truncateDecimals !== undefined) {
|
|
70
|
+
finalFractionalPart = fractionalPart.slice(0, truncateDecimals)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Always pad to at least 2 decimal places (or padDecimals)
|
|
74
|
+
if (finalFractionalPart.length < padDecimals) {
|
|
75
|
+
finalFractionalPart = finalFractionalPart.padEnd(padDecimals, '0')
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// If there are no decimals, still show .00
|
|
79
|
+
const numberString = `${integerPart}.${finalFractionalPart}`
|
|
80
|
+
return addThousandsSeparator(numberString, delimiter)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function formatTokenAmountForDisplay(amount: bigint, options: FormatRateDisplayOptions): string {
|
|
84
|
+
return formatUnits(amount, { truncateDecimals: 2, ...options })
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Safe integer parsing without using Number()
|
|
88
|
+
export function parseIntegerSafe(value: string): number | null {
|
|
89
|
+
// Use parseInt instead of Number() for integer parsing
|
|
90
|
+
const parsed = parseInt(value, 10)
|
|
91
|
+
return isNaN(parsed) ? null : parsed
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// // Get display title for limits (shows original user limits on hover)
|
|
95
|
+
// export function getLimitsDisplayTitle(deposit: { formattedMinAmount: string; formattedMaxAmount: string }): string {
|
|
96
|
+
// return `User set: ${deposit.formattedMinAmount} - ${deposit.formattedMaxAmount}`
|
|
97
|
+
// }
|
|
98
|
+
|
|
99
|
+
// Convert blockchain timestamp (seconds) to Date object
|
|
100
|
+
export function timestampToDate(timestamp: string | number | bigint | undefined | null): Date | null {
|
|
101
|
+
if (!timestamp) return null
|
|
102
|
+
|
|
103
|
+
// Convert seconds to milliseconds for Date constructor
|
|
104
|
+
const timestampMs = Number(timestamp) * 1000
|
|
105
|
+
return new Date(timestampMs)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// export function formatTokenAmountForDisplay(amount: bigint, tokenInfo: TokenInfo): string {
|
|
109
|
+
// return formatUnits(amount, { decimals: tokenInfo.decimals })
|
|
110
|
+
// }
|
|
111
|
+
|
|
112
|
+
export const formatAmount = (token: TokenInfo, amount: bigint | null, options: Partial<FormatRateDisplayOptions> = {}) => {
|
|
113
|
+
if (!amount) return null
|
|
114
|
+
return formatUnits(amount, {
|
|
115
|
+
decimals: token.decimals,
|
|
116
|
+
truncateDecimals: Math.min(token.decimals - 4, 8),
|
|
117
|
+
padDecimals: 2,
|
|
118
|
+
...options,
|
|
119
|
+
})
|
|
120
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { Hex } from "viem"
|
|
2
|
+
|
|
3
|
+
import type { ProviderKey, ValidationDepositData } from "./payment.js"
|
|
4
|
+
|
|
5
|
+
export type ValidationOptions = {
|
|
6
|
+
providerKey: ProviderKey
|
|
7
|
+
telegramHandle: string
|
|
8
|
+
providerId: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export type Zkp2pResponse<T> = {
|
|
12
|
+
success: boolean
|
|
13
|
+
message: string
|
|
14
|
+
statusCode: number
|
|
15
|
+
responseObject: T
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export type CreateResponse = {
|
|
19
|
+
id: number
|
|
20
|
+
processorName: string
|
|
21
|
+
depositData: string
|
|
22
|
+
hashedOnchainId: Hex
|
|
23
|
+
createdAt: string
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export type PayeeDetails = {
|
|
27
|
+
id: number
|
|
28
|
+
processorName: string
|
|
29
|
+
createdAt: string
|
|
30
|
+
hashedOnchainId: Hex
|
|
31
|
+
depositData: ValidationDepositData
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export type IntentValidationOptions = {
|
|
35
|
+
processorName: ProviderKey
|
|
36
|
+
depositId: string
|
|
37
|
+
tokenAmount: string
|
|
38
|
+
payeeDetails: Hex
|
|
39
|
+
toAddress: Hex
|
|
40
|
+
fiatCurrencyCode: Hex
|
|
41
|
+
chainId: string
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export type IntentValidation = {
|
|
45
|
+
signedIntent: Hex
|
|
46
|
+
intentData: {
|
|
47
|
+
depositId: string
|
|
48
|
+
tokenAmount: string
|
|
49
|
+
recipientAddress: Hex
|
|
50
|
+
verifierAddress: Hex
|
|
51
|
+
currencyCodeHash: Hex
|
|
52
|
+
gatingServiceSignature: Hex
|
|
53
|
+
},
|
|
54
|
+
depositData: ValidationDepositData
|
|
55
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ESNext",
|
|
4
|
+
"useDefineForClassFields": true,
|
|
5
|
+
"module": "NodeNext",
|
|
6
|
+
"composite": true,
|
|
7
|
+
"allowJs": true,
|
|
8
|
+
"outDir": "./dist",
|
|
9
|
+
"strict": true,
|
|
10
|
+
"isolatedModules": true,
|
|
11
|
+
"skipLibCheck": true,
|
|
12
|
+
"moduleDetection": "force",
|
|
13
|
+
"esModuleInterop": true,
|
|
14
|
+
"resolveJsonModule": true,
|
|
15
|
+
"moduleResolution": "nodenext"
|
|
16
|
+
},
|
|
17
|
+
"include": ["src/**/*.ts", "src/**/*.json", "src/**/*.svg", "scripts/**/*.ts"]
|
|
18
|
+
}
|