· 4 years ago · Apr 05, 2021, 09:00 AM
1import axios from 'axios
2import { generateMnemonic, validateMnemonic, mnemonicToEntropy } from 'bip39-light'
3
4const apiClient = axios.create({
5 baseURL: 'https://graphql.rraayy.com'
6})
7
8export async function GetAdressesUTXO(addresses) {
9 return apiClient
10 .post('/', {
11 query: `
12 query utxoSetForAddress($addresses: [String]) {
13 utxos(order_by: { value: desc }, where: { address: { _in: $addresses } }) {
14 address
15 value
16 tokens {
17 assetId
18 assetName
19 policyId
20 quantity
21 }
22 }
23 }
24 `,
25 variables: {
26 addresses,
27 },
28 })
29 .then((response) => {
30 if (response) {
31 return response.data
32 }
33 return false
34 })
35 .catch((err) => console.log(err))
36}
37
38class CardanoWasmModule {
39 async load() {
40 this.wasm = await import('@emurgo/cardano-serialization-lib-browser/cardano_serialization_lib')
41 }
42
43 get API() {
44 return this.wasm
45 }
46}
47
48
49/**
50 * Mnemonic generation
51 * @return {string}
52 */
53
54export const CardanoGenerateMnemonic = (length = 24) => {
55 return generateMnemonic((32 * length) / 3)
56}
57
58/**
59 * Get private key, public key, reward address
60 * @return {object}
61 */
62
63export const CardanoGetAccountInfo = async (network, mnemonic) => {
64 await CardanoWasm.load()
65
66 const harden = (num) => {
67 return 0x80000000 + num
68 }
69
70 const entropy = mnemonicToEntropy(mnemonic)
71 const rootKey = CardanoWasm.API.Bip32PrivateKey.from_bip39_entropy(
72 Buffer.from(entropy, 'hex'),
73 Buffer.from(''),
74 )
75
76 const privateKey = rootKey.derive(harden(1852)).derive(harden(1815)).derive(harden(0))
77
78 const stakeKey = privateKey.derive(2).derive(0).to_public()
79
80 const currentNetwork = network === 'testnet'
81 ? CardanoWasm.API.NetworkInfo.testnet().network_id()
82 : CardanoWasm.API.NetworkInfo.mainnet().network_id()
83
84 const rewardAddress = CardanoWasm.API.RewardAddress.new(
85 currentNetwork,
86 CardanoWasm.API.StakeCredential.from_keyhash(stakeKey.to_raw_key().hash()),
87 )
88 const rewardAddressBech32 = rewardAddress.to_address().to_bech32()
89 const privateKeyBech32 = privateKey.to_bech32()
90 const publicKeyBech32 = privateKey.to_public().to_bech32()
91
92 return { rewardAddressBech32, privateKeyBech32, publicKeyBech32 }
93}
94
95/**
96 * Generate address pack related to Private Key
97 * @param {string} publicKeyBech32 private key
98 * @param {string} type external internal / all derives
99 * @param {number} shift shifting addresses by page size
100 * @param {number} page page size
101 * @return {array} adresses array
102 */
103
104export const CardanoGetAccountAdresses = async (
105 network,
106 publicKeyBech32,
107 type = 'external',
108 shift = 0,
109 page = 20,
110) => {
111 await CardanoWasm.load()
112
113 const publicKey = CardanoWasm.API.Bip32PublicKey.from_bech32(publicKeyBech32)
114 const accountAdresses = []
115
116 const currentNetwork = network === 'testnet'
117 ? CardanoWasm.API.NetworkInfo.testnet().network_id()
118 : CardanoWasm.API.NetworkInfo.mainnet().network_id()
119
120 const generateAddresses = (addressType) => {
121 const tmpAddresses = []
122 for (let i = 0 + page * shift; i < page + page * shift; i += 1) {
123 const utxoPubKey = publicKey
124 .derive(addressType) // 0 external / 1 internal
125 .derive(i)
126 const stakeKey = publicKey
127 .derive(2) // chimeric
128 .derive(0)
129 const baseAddr = CardanoWasm.API.BaseAddress.new(
130 currentNetwork,
131 CardanoWasm.API.StakeCredential.from_keyhash(utxoPubKey.to_raw_key().hash()),
132 CardanoWasm.API.StakeCredential.from_keyhash(stakeKey.to_raw_key().hash()),
133 )
134 const baseAddrBech32 = baseAddr.to_address().to_bech32()
135 tmpAddresses.push(baseAddrBech32)
136 }
137 return tmpAddresses
138 }
139
140 switch (type) {
141 case 'external':
142 accountAdresses.push(...generateAddresses(0))
143 break
144 case 'internal':
145 accountAdresses.push(...generateAddresses(1))
146 break
147 case 'all':
148 accountAdresses.push(...generateAddresses(0))
149 accountAdresses.push(...generateAddresses(1))
150 break
151 default:
152 break
153 }
154
155 return accountAdresses
156}
157
158function* checkAddresses(type, shift, pageSize) {
159 const tmpAddresses = yield call(
160 Cardano.CardanoGetAccountAdresses,
161 CARDANO_NETWORK,
162 publicKey,
163 type,
164 shift,
165 pageSize,
166 )
167 const tmpAddresssesUTXO = yield call(Explorer.GetAdressesUTXO, tmpAddresses)
168 return [tmpAddresssesUTXO, tmpAddresses]
169}
170
171const UTXOArray = []
172const adressesArray = []
173const pageSize = 20
174const type = 'all'
175const maxShiftIndex = 10
176let shiftIndex = 0
177function* getAddressesWithShift(shift) {
178 const [adresssesWithUTXOs, checkedAdresses] = yield call(checkAddresses, type, shift, pageSize)
179 adressesArray.push(...checkedAdresses)
180 if (adresssesWithUTXOs.data && shiftIndex < maxShiftIndex) {
181 if (adresssesWithUTXOs.data.utxos.length) {
182 shiftIndex += 1
183 UTXOArray.push(...adresssesWithUTXOs.data.utxos)
184 yield call(getAddressesWithShift, shiftIndex)
185 }
186 }
187}
188yield call(getAddressesWithShift, shiftIndex)