@yaswap/cryptoassets 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,143 @@
1
+ import { TESTNET_NATIVE } from './testnet'
2
+ import { AssetMap, ChainId } from '../types'
3
+
4
+ const nativeAssets: AssetMap = {
5
+ BTC: {
6
+ name: 'Bitcoin',
7
+ chain: ChainId.Bitcoin,
8
+ type: 'native',
9
+ code: 'BTC',
10
+ coinGeckoId: 'bitcoin',
11
+ color: '#f7931a',
12
+ decimals: 8
13
+ },
14
+ BCH: {
15
+ name: 'Bitcoin Cash',
16
+ chain: ChainId.BitcoinCash,
17
+ type: 'native',
18
+ code: 'BCH',
19
+ coinGeckoId: 'bitcoin-cash',
20
+ color: '#a1db5e',
21
+ decimals: 8
22
+ },
23
+ ETH: {
24
+ name: 'Ether',
25
+ chain: ChainId.Ethereum,
26
+ type: 'native',
27
+ code: 'ETH',
28
+ coinGeckoId: 'ethereum',
29
+ color: '#627eea',
30
+ decimals: 18
31
+ },
32
+ RBTC: {
33
+ name: 'Rootstock BTC',
34
+ chain: ChainId.Rootstock,
35
+ type: 'native',
36
+ code: 'RBTC',
37
+ coinGeckoId: 'rootstock',
38
+ color: '#006e3c',
39
+ decimals: 18
40
+ },
41
+ BNB: {
42
+ name: 'Binance Coin',
43
+ chain: ChainId.BinanceSmartChain,
44
+ type: 'native',
45
+ code: 'BNB',
46
+ coinGeckoId: 'binancecoin',
47
+ color: '#f9a825',
48
+ decimals: 18
49
+ },
50
+ NEAR: {
51
+ name: 'Near',
52
+ chain: ChainId.Near,
53
+ type: 'native',
54
+ code: 'NEAR',
55
+ coinGeckoId: 'near',
56
+ color: '#000000',
57
+ decimals: 24
58
+ },
59
+ SOL: {
60
+ name: 'Solana',
61
+ chain: ChainId.Solana,
62
+ type: 'native',
63
+ code: 'SOL',
64
+ coinGeckoId: 'solana',
65
+ color: '#008080',
66
+ decimals: 9
67
+ },
68
+ MATIC: {
69
+ name: 'Matic',
70
+ chain: ChainId.Polygon,
71
+ type: 'native',
72
+ code: 'MATIC',
73
+ coinGeckoId: 'matic-network',
74
+ color: '#8247E5',
75
+ decimals: 18
76
+ },
77
+ ARBETH: {
78
+ name: 'Arbitrum ETH',
79
+ chain: ChainId.Arbitrum,
80
+ type: 'native',
81
+ code: 'ARBETH',
82
+ coinGeckoId: 'ethereum',
83
+ color: '#28A0EF',
84
+ decimals: 18,
85
+ matchingAsset: 'ETH'
86
+ },
87
+ FUSE: {
88
+ name: 'Fuse Network',
89
+ chain: ChainId.Fuse,
90
+ type: 'native',
91
+ code: 'FUSE',
92
+ coinGeckoId: 'fuse-network-token',
93
+ color: '#46e8b6',
94
+ decimals: 18
95
+ },
96
+ LUNA: {
97
+ name: 'Luna',
98
+ chain: ChainId.Terra,
99
+ type: 'native',
100
+ code: 'LUNA',
101
+ coinGeckoId: 'terra-luna',
102
+ color: '#008080',
103
+ decimals: 6
104
+ },
105
+ UST: {
106
+ name: 'TerraUSD',
107
+ chain: ChainId.Terra,
108
+ type: 'native',
109
+ code: 'UST',
110
+ decimals: 6,
111
+ color: '#0083ff',
112
+ coinGeckoId: 'terrausd',
113
+ feeAsset: 'UST'
114
+ },
115
+ AVAX: {
116
+ name: 'Avalanche',
117
+ chain: ChainId.Avalanche,
118
+ type: 'native',
119
+ code: 'AVAX',
120
+ coinGeckoId: 'avalanche-2',
121
+ color: '#E84141',
122
+ decimals: 18
123
+ },
124
+ YAC: {
125
+ name: 'Yacoin',
126
+ chain: ChainId.Yacoin,
127
+ type: 'native',
128
+ code: 'YAC',
129
+ coinGeckoId: 'yacoin',
130
+ color: '#f7931a',
131
+ decimals: 6
132
+ }
133
+ }
134
+
135
+ const testnetNativeAssets = TESTNET_NATIVE.reduce((assets: AssetMap, asset: string) => {
136
+ return Object.assign(assets, {
137
+ [asset]: {
138
+ ...nativeAssets[asset]
139
+ }
140
+ })
141
+ }, {})
142
+
143
+ export { nativeAssets, testnetNativeAssets }
@@ -0,0 +1,24 @@
1
+ export const TESTNET_CONTRACT_ADDRESSES = {
2
+ DAI: '0xad6d458402f60fd3bd25163575031acdce07538d',
3
+ WBTC: '0x1371597fc11aedbd2446f5390fa1dbf22491752a',
4
+ SOV: '0x6a9A07972D07E58f0daF5122D11e069288A375fB',
5
+ PWETH: '0xA6FA4fB5f76172d178d61B04b0ecd319C5d1C0aa',
6
+ SUSHI: '0x0769fd68dFb93167989C6f7254cd0D766Fb2841F'
7
+ } as Record<string, string>
8
+
9
+ export const TESTNET_TOKENS = Object.keys(TESTNET_CONTRACT_ADDRESSES)
10
+
11
+ export const TESTNET_NATIVE = [
12
+ 'BTC',
13
+ 'ETH',
14
+ 'RBTC',
15
+ 'BNB',
16
+ 'NEAR',
17
+ 'MATIC',
18
+ 'ARBETH',
19
+ 'SOL',
20
+ 'LUNA',
21
+ 'UST',
22
+ 'FUSE',
23
+ 'AVAX'
24
+ ]
@@ -0,0 +1 @@
1
+ declare module 'base58-js'
package/src/chains.ts ADDED
@@ -0,0 +1,235 @@
1
+ import { isValidAddress, toChecksumAddress } from 'ethereumjs-util'
2
+ import validateBitcoinAddress from 'bitcoin-address-validation'
3
+
4
+ import { Chain, ChainId } from './types'
5
+ import {
6
+ isValidNearTx,
7
+ isValidNearAddress,
8
+ isValidSolanaAddress,
9
+ isValidBitcoinCashAddress,
10
+ isValidYacoinAddress,
11
+ formatBitcoinCashAddress,
12
+ isValidHex,
13
+ isValidSolanaTx,
14
+ toLowerCaseWithout0x,
15
+ with0x,
16
+ isValidTerraAddress,
17
+ isValidTerraTx,
18
+ getRSKChainID
19
+ } from './common'
20
+
21
+ const chains: { [key in ChainId]: Chain } = {
22
+ [ChainId.Bitcoin]: {
23
+ name: 'Bitcoin',
24
+ code: 'BTC',
25
+ nativeAsset: 'BTC',
26
+ fees: {
27
+ unit: 'sat/b'
28
+ },
29
+ safeConfirmations: 1,
30
+ // 0,1 blocks per minute * 180 minutes (3 hours) -> 18 blocks wait period
31
+ txFailureTimeout: 10800000, // 3 hours in ms
32
+ // TODO: include network types in validation
33
+ isValidAddress: (address) => !!validateBitcoinAddress(address),
34
+ formatAddress: (address) => address,
35
+ isValidTransactionHash: (hash: string) => isValidHex(hash),
36
+ formatTransactionHash: (hash: string) => toLowerCaseWithout0x(hash)
37
+ },
38
+ [ChainId.BitcoinCash]: {
39
+ name: 'Bitcoin Cash',
40
+ code: 'BCH',
41
+ nativeAsset: 'BCH',
42
+ fees: {
43
+ unit: 'sat/b'
44
+ },
45
+ safeConfirmations: 1,
46
+ // ~0,1 blocks per minute * 180 minutes (3 hours) -> 18 blocks wait period
47
+ txFailureTimeout: 10800000, // 3 hours in ms
48
+ // TODO: include network types in validation
49
+ isValidAddress: (address) => isValidBitcoinCashAddress(address),
50
+ formatAddress: (address) => formatBitcoinCashAddress(address),
51
+ isValidTransactionHash: (hash: string) => isValidHex(hash),
52
+ formatTransactionHash: (hash: string) => toLowerCaseWithout0x(hash)
53
+ },
54
+ [ChainId.Ethereum]: {
55
+ name: 'Ethereum',
56
+ code: 'ETH',
57
+ nativeAsset: 'ETH',
58
+ fees: {
59
+ unit: 'gwei'
60
+ },
61
+ safeConfirmations: 3,
62
+ // ~4 blocks per minute * 30 minutes -> 120 blocks wait period
63
+ txFailureTimeout: 1800000, // in ms
64
+ isValidAddress: (hexAddress: string) => isValidAddress(with0x(hexAddress)),
65
+ formatAddress: (hexAddress: string) => toChecksumAddress(with0x(hexAddress)),
66
+ isValidTransactionHash: (hash: string) => isValidHex(hash),
67
+ formatTransactionHash: (hash: string) => toLowerCaseWithout0x(hash)
68
+ },
69
+ [ChainId.Rootstock]: {
70
+ name: 'Rootstock',
71
+ code: 'RSK',
72
+ nativeAsset: 'RBTC',
73
+ fees: {
74
+ unit: 'gwei'
75
+ },
76
+ safeConfirmations: 5,
77
+ // ~3 blocks per minute * 30 minutes -> 90 blocks wait period
78
+ txFailureTimeout: 1800000, // in ms
79
+ isValidAddress: (hexAddress: string) => isValidAddress(with0x(hexAddress)),
80
+ formatAddress: (hexAddress: string, network?: string) =>
81
+ toChecksumAddress(with0x(hexAddress), getRSKChainID(network)),
82
+ isValidTransactionHash: (hash: string) => isValidHex(hash),
83
+ formatTransactionHash: (hash: string) => toLowerCaseWithout0x(hash)
84
+ },
85
+ [ChainId.BinanceSmartChain]: {
86
+ name: 'Binance Smart Chain',
87
+ code: 'BSC',
88
+ nativeAsset: 'BNB',
89
+ fees: {
90
+ unit: 'gwei'
91
+ },
92
+ safeConfirmations: 5,
93
+ // ~20 blocks per minute * 10 minutes -> 200 blocks wait period
94
+ txFailureTimeout: 600000, // in ms
95
+ isValidAddress: (hexAddress: string) => isValidAddress(with0x(hexAddress)),
96
+ formatAddress: (hexAddress: string) => toChecksumAddress(with0x(hexAddress)),
97
+ isValidTransactionHash: (hash: string) => isValidHex(hash),
98
+ formatTransactionHash: (hash: string) => toLowerCaseWithout0x(hash)
99
+ },
100
+ [ChainId.Near]: {
101
+ name: 'Near',
102
+ code: 'NEAR',
103
+ nativeAsset: 'NEAR',
104
+ fees: {
105
+ unit: 'TGas'
106
+ },
107
+ safeConfirmations: 10,
108
+ // ~50 blocks per minute * 5 minutes -> 250 blocks wait period
109
+ txFailureTimeout: 300000, // in ms
110
+ isValidAddress: (address) => isValidNearAddress(address),
111
+ formatAddress: (address) => address,
112
+ isValidTransactionHash: (hash: string) => isValidNearTx(hash),
113
+ formatTransactionHash: (hash: string) => hash
114
+ },
115
+ [ChainId.Solana]: {
116
+ name: 'Solana',
117
+ code: 'SOL',
118
+ nativeAsset: 'SOL',
119
+ fees: {
120
+ unit: 'Lamports'
121
+ },
122
+ safeConfirmations: 31,
123
+ // ~120 blocks per minute * 5 minutes -> 600 blocks wait period
124
+ txFailureTimeout: 300000, // in ms
125
+ isValidAddress: (address) => isValidSolanaAddress(address),
126
+ formatAddress: (address) => address,
127
+ isValidTransactionHash: (hash: string) => isValidSolanaTx(hash),
128
+ formatTransactionHash: (hash: string) => hash
129
+ },
130
+ [ChainId.Terra]: {
131
+ name: 'Terra',
132
+ code: 'LUNA',
133
+ nativeAsset: 'LUNA',
134
+ fees: {
135
+ unit: 'LUNA'
136
+ },
137
+ safeConfirmations: 1,
138
+ // ~10 blocks per minute * 15 minutes -> 150 blocks wait period
139
+ txFailureTimeout: 900000, // in ms
140
+ isValidAddress: (address) => isValidTerraAddress(address),
141
+ formatAddress: (address) => address,
142
+ isValidTransactionHash: (hash: string) => isValidTerraTx(hash),
143
+ formatTransactionHash: (hash: string) => hash
144
+ },
145
+ [ChainId.Polygon]: {
146
+ name: 'Polygon',
147
+ code: 'POLYGON',
148
+ nativeAsset: 'MATIC',
149
+ fees: {
150
+ unit: 'gwei'
151
+ },
152
+ safeConfirmations: 5,
153
+ // ~30 blocks per minute * 10 minutes -> 300 blocks wait period
154
+ txFailureTimeout: 600000, // in ms
155
+ isValidAddress: (hexAddress: string) => isValidAddress(with0x(hexAddress)),
156
+ formatAddress: (hexAddress: string) => toChecksumAddress(with0x(hexAddress)),
157
+ isValidTransactionHash: (hash: string) => isValidHex(hash),
158
+ formatTransactionHash: (hash: string) => toLowerCaseWithout0x(hash)
159
+ },
160
+ [ChainId.Arbitrum]: {
161
+ name: 'Arbitrum',
162
+ code: 'ARBITRUM',
163
+ nativeAsset: 'ARBETH',
164
+ fees: {
165
+ unit: 'gwei'
166
+ },
167
+ safeConfirmations: 5,
168
+ // ~15 blocks per minute * 10 minutes -> 150 blocks wait period
169
+ txFailureTimeout: 600000, // in ms
170
+ isValidAddress: (hexAddress: string) => isValidAddress(with0x(hexAddress)),
171
+ formatAddress: (hexAddress: string) => toChecksumAddress(with0x(hexAddress)),
172
+ isValidTransactionHash: (hash: string) => isValidHex(hash),
173
+ formatTransactionHash: (hash: string) => toLowerCaseWithout0x(hash)
174
+ },
175
+ [ChainId.Fuse]: {
176
+ name: 'Fuse',
177
+ code: 'FUSE',
178
+ nativeAsset: 'FUSE',
179
+ fees: {
180
+ unit: 'gwei'
181
+ },
182
+ safeConfirmations: 5,
183
+ // ~12 blocks per minute * 15 minutes -> 180 blocks wait period
184
+ txFailureTimeout: 900000, // in ms
185
+ isValidAddress: (hexAddress: string) => isValidAddress(with0x(hexAddress)),
186
+ formatAddress: (hexAddress: string) => toChecksumAddress(with0x(hexAddress)),
187
+ isValidTransactionHash: (hash: string) => isValidHex(hash),
188
+ formatTransactionHash: (hash: string) => toLowerCaseWithout0x(hash)
189
+ },
190
+ [ChainId.Avalanche]: {
191
+ name: 'Avalanche',
192
+ code: 'AVALANCHE',
193
+ nativeAsset: 'AVAX',
194
+ fees: {
195
+ unit: 'gwei'
196
+ },
197
+ safeConfirmations: 5,
198
+ // ~15 blocks per minute * 10 minutes -> 150 blocks wait period
199
+ txFailureTimeout: 600000, // in ms
200
+ isValidAddress: (hexAddress: string) => isValidAddress(with0x(hexAddress)),
201
+ formatAddress: (hexAddress: string) => toChecksumAddress(with0x(hexAddress)),
202
+ isValidTransactionHash: (hash: string) => isValidHex(hash),
203
+ formatTransactionHash: (hash: string) => hash
204
+ },
205
+ [ChainId.Yacoin]: {
206
+ name: 'Yacoin',
207
+ code: 'YAC',
208
+ nativeAsset: 'YAC',
209
+ fees: {
210
+ unit: 'sat/b'
211
+ },
212
+ safeConfirmations: 1,
213
+ // 1 block per minute * 180 minutes (3 hours) -> 180 blocks wait period
214
+ txFailureTimeout: 10800000, // 3 hours in ms
215
+ // TODO: include network types in validation
216
+ isValidAddress: (address) => isValidYacoinAddress(address),
217
+ formatAddress: (address) => address,
218
+ isValidTransactionHash: (hash: string) => isValidHex(hash),
219
+ formatTransactionHash: (hash: string) => toLowerCaseWithout0x(hash)
220
+ }
221
+ }
222
+
223
+ function isEthereumChain(chain: ChainId) {
224
+ return [
225
+ ChainId.BinanceSmartChain,
226
+ ChainId.Ethereum,
227
+ ChainId.Rootstock,
228
+ ChainId.Polygon,
229
+ ChainId.Avalanche,
230
+ ChainId.Arbitrum,
231
+ ChainId.Fuse
232
+ ].includes(chain)
233
+ }
234
+
235
+ export { chains, isEthereumChain }
package/src/common.ts ADDED
@@ -0,0 +1,105 @@
1
+ import base58 from 'bs58'
2
+ import { base58_to_binary } from 'base58-js'
3
+ import * as cashaddr from 'cashaddrjs'
4
+ import { createHash } from 'sha256-uint8array'
5
+
6
+ const BASE58_LENGTH = 32
7
+ const sha256 = (payload: Uint8Array) => createHash().update(payload).digest()
8
+
9
+ export const isValidHex = (hash: string) => /^([A-Fa-f0-9]{64})$/.test(hash)
10
+ export const toLowerCaseWithout0x = (hash: string) => hash.toLowerCase().replace(/0x/g, '')
11
+ export const with0x = (hash: string) => (hash.startsWith('0x') ? hash : '0x' + hash)
12
+
13
+ export const isValidNearAddress = (address: string) => address.endsWith('.near') || /^[0-9a-fA-F]{64}$/.test(address)
14
+
15
+ export const isValidNearTx = (hash: string) => {
16
+ try {
17
+ const [txHash, address] = hash.split('_')
18
+ return base58.decode(txHash).length === BASE58_LENGTH && isValidNearAddress(address)
19
+ } catch (e) {
20
+ return false
21
+ }
22
+ }
23
+
24
+ export const isValidBitcoinCashAddress = (address: string) => {
25
+ try {
26
+ if (!address.includes(':')) address = 'bitcoincash:' + address
27
+ const { prefix, type, hash } = cashaddr.decode(address)
28
+ if (['bitcoincash', 'bchtest', 'bchreg'].includes(prefix)) {
29
+ return false
30
+ }
31
+ if (['P2PKH', 'P2SH'].includes(type)) {
32
+ return false
33
+ }
34
+ return hash.length == 20
35
+ } catch (e) {
36
+ return false
37
+ }
38
+ }
39
+
40
+ export const formatBitcoinCashAddress = (address: string) => {
41
+ address = address.toLowerCase()
42
+ if (address.startsWith('bitcoincash:')) address = address.slice(12)
43
+ return address
44
+ }
45
+
46
+ export const isValidYacoinAddress = (address: string) => {
47
+ const validVersions = [0x4d, 0x8b, 0x6f, 0xc4]
48
+
49
+ let decoded: Uint8Array
50
+
51
+ try {
52
+ decoded = base58_to_binary(address)
53
+ } catch (error) {
54
+ // Invalid address
55
+ return false
56
+ }
57
+
58
+ const { length } = decoded
59
+ if (length !== 25) {
60
+ // Invalid address
61
+ return false
62
+ }
63
+
64
+ const version = decoded[0]
65
+ const checksum = decoded.slice(length - 4, length)
66
+ const body = decoded.slice(0, length - 4)
67
+ const expectedChecksum = sha256(sha256(body)).slice(0, 4)
68
+
69
+ if (checksum.some((value: number, index: number) => value !== expectedChecksum[index])) {
70
+ // Invalid address
71
+ return false
72
+ }
73
+
74
+ if (!validVersions.includes(version)) {
75
+ // Invalid address
76
+ return false
77
+ }
78
+
79
+ return true
80
+ }
81
+
82
+ export const isValidSolanaAddress = (address: string): boolean => {
83
+ return typeof address === 'string' && address.length >= 32 && address.length <= 44
84
+ }
85
+
86
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
87
+ export const isValidSolanaTx = (tx: string): boolean => {
88
+ return true
89
+ }
90
+
91
+ export const isValidTerraAddress = (address: string): boolean => {
92
+ const terraAddressesLength = 44
93
+
94
+ return address.length === terraAddressesLength
95
+ }
96
+
97
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
98
+ export const isValidTerraTx = (tx: string): boolean => {
99
+ return typeof tx === 'string' && tx.length === 64
100
+ }
101
+
102
+ export const getRSKChainID = (network: string) => {
103
+ if (network == 'mainnet') return 30
104
+ if (network == 'testnet') return 31
105
+ }