@ecency/sdk 1.0.2 → 1.0.4
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/ecency-sdk.es.d.ts +4 -0
- package/dist/ecency-sdk.es.js +202 -100
- package/package.json +3 -2
package/dist/ecency-sdk.es.d.ts
CHANGED
@@ -62,6 +62,8 @@ declare interface Payload_3 {
|
|
62
62
|
privateKeyOrSeed: string;
|
63
63
|
}
|
64
64
|
|
65
|
+
export declare function useAccountUpdate(username: string): UseMutationResult<any, Error, any, unknown>;
|
66
|
+
|
65
67
|
declare function useCheckWalletExistence(): UseMutationResult<boolean, Error, Payload_2, unknown>;
|
66
68
|
|
67
69
|
export declare function useCoinGeckoPriceQuery(currency?: EcencyWalletCurrency): UseQueryResult<number, Error>;
|
@@ -86,6 +88,8 @@ address: any;
|
|
86
88
|
publicKey: string;
|
87
89
|
}, Error, Payload_3, unknown>;
|
88
90
|
|
91
|
+
export declare function useSaveWalletInformationToMetadata(username: string): UseMutationResult<any, Error, void, unknown>;
|
92
|
+
|
89
93
|
export declare function useSeedPhrase(username: string): UseQueryResult<string, Error>;
|
90
94
|
|
91
95
|
export declare function useWalletCreate(username: string, currency: EcencyWalletCurrency): {
|
package/dist/ecency-sdk.es.js
CHANGED
@@ -1,52 +1,53 @@
|
|
1
1
|
import { useCallback as O } from "react";
|
2
|
-
import { useQuery as p, useQueryClient as
|
3
|
-
import { BtcWallet as
|
4
|
-
import { EthWallet as
|
5
|
-
import { TrxWallet as
|
6
|
-
import { TonWallet as
|
2
|
+
import { useQuery as p, useQueryClient as f, useMutation as u } from "@tanstack/react-query";
|
3
|
+
import { BtcWallet as k } from "@okxweb3/coin-bitcoin";
|
4
|
+
import { EthWallet as R } from "@okxweb3/coin-ethereum";
|
5
|
+
import { TrxWallet as A } from "@okxweb3/coin-tron";
|
6
|
+
import { TonWallet as K } from "@okxweb3/coin-ton";
|
7
7
|
import { SolWallet as N } from "@okxweb3/coin-solana";
|
8
|
-
import { AtomWallet as
|
9
|
-
import { AptosWallet as
|
10
|
-
import
|
11
|
-
import { LRUCache as
|
12
|
-
import { PrivateKey as
|
8
|
+
import { AtomWallet as C } from "@okxweb3/coin-cosmos";
|
9
|
+
import { AptosWallet as _ } from "@okxweb3/coin-aptos";
|
10
|
+
import j, { mnemonicToSeedSync as x } from "bip39";
|
11
|
+
import { LRUCache as D } from "lru-cache";
|
12
|
+
import { PrivateKey as m, Client as H } from "@hiveio/dhive";
|
13
|
+
import B from "hivesigner";
|
13
14
|
var o = /* @__PURE__ */ ((e) => (e.BTC = "BTC", e.ETH = "ETH", e.APT = "APT", e.ATOM = "ATOM", e.TON = "TON", e.TRON = "TRX", e.SOL = "SOL", e))(o || {});
|
14
|
-
function
|
15
|
+
function W(e) {
|
15
16
|
return new Promise((t) => setTimeout(t, e));
|
16
17
|
}
|
17
|
-
function
|
18
|
+
function g(e) {
|
18
19
|
switch (e) {
|
19
20
|
case o.BTC:
|
20
|
-
return new
|
21
|
+
return new k();
|
21
22
|
case o.ETH:
|
22
|
-
return new
|
23
|
+
return new R();
|
23
24
|
case o.TRON:
|
24
|
-
return new k();
|
25
|
-
case o.TON:
|
26
25
|
return new A();
|
26
|
+
case o.TON:
|
27
|
+
return new K();
|
27
28
|
case o.SOL:
|
28
29
|
return new N();
|
29
30
|
case o.ATOM:
|
30
|
-
return new K();
|
31
|
-
case o.APT:
|
32
31
|
return new C();
|
32
|
+
case o.APT:
|
33
|
+
return new _();
|
33
34
|
default:
|
34
35
|
return;
|
35
36
|
}
|
36
37
|
}
|
37
|
-
function
|
38
|
-
return
|
38
|
+
function ye(e) {
|
39
|
+
return x(e).toString("hex");
|
39
40
|
}
|
40
|
-
function
|
41
|
+
function fe(e, t) {
|
41
42
|
return p({
|
42
43
|
queryKey: ["ecency-wallets", "external-wallet-balance", e, t],
|
43
44
|
queryFn: async () => {
|
44
45
|
switch (e) {
|
45
46
|
case o.BTC:
|
46
|
-
const
|
47
|
+
const s = await (await fetch(
|
47
48
|
`https://mempool.space/api/address/${t}`
|
48
49
|
)).json();
|
49
|
-
return (
|
50
|
+
return (s.chain_stats.funded_txo_sum - s.chain_stats.spent_txo_sum) / 1e8;
|
50
51
|
case o.ETH:
|
51
52
|
return +(await (await fetch("https://eth.llamarpc.com", {
|
52
53
|
method: "POST",
|
@@ -79,12 +80,12 @@ function ie(e, t) {
|
|
79
80
|
`https://tonapi.io/v1/blockchain/getAccount?account=${t}`
|
80
81
|
)).json()).balance / 1e9;
|
81
82
|
case o.APT:
|
82
|
-
const
|
83
|
+
const y = (await (await fetch(
|
83
84
|
`https://fullnode.mainnet.aptoslabs.com/v1/accounts/${t}/resources`
|
84
85
|
)).json()).find(
|
85
86
|
(S) => S.type.includes("coin::CoinStore")
|
86
87
|
);
|
87
|
-
return
|
88
|
+
return y ? parseInt(y.data.coin.value) / 1e8 : 0;
|
88
89
|
case o.ATOM:
|
89
90
|
return +(await (await fetch(
|
90
91
|
`https://rest.cosmos.directory/cosmoshub/auth/accounts/${t}`
|
@@ -93,13 +94,13 @@ function ie(e, t) {
|
|
93
94
|
}
|
94
95
|
});
|
95
96
|
}
|
96
|
-
function
|
97
|
+
function T(e) {
|
97
98
|
return p({
|
98
99
|
queryKey: ["ecency-wallets", "seed", e],
|
99
|
-
queryFn: async () =>
|
100
|
+
queryFn: async () => j.generateMnemonic(128)
|
100
101
|
});
|
101
102
|
}
|
102
|
-
const
|
103
|
+
const E = {
|
103
104
|
max: 500,
|
104
105
|
// how long to live in ms
|
105
106
|
ttl: 1e3 * 60 * 5,
|
@@ -107,11 +108,11 @@ const W = {
|
|
107
108
|
allowStale: !1,
|
108
109
|
updateAgeOnGet: !1,
|
109
110
|
updateAgeOnHas: !1
|
110
|
-
},
|
111
|
-
const t =
|
111
|
+
}, b = new D(E), w = Symbol("undefined"), F = (e, t) => b.set(e, t === void 0 ? w : t), M = (e) => {
|
112
|
+
const t = b.get(e);
|
112
113
|
return t === w ? void 0 : t;
|
113
114
|
};
|
114
|
-
function
|
115
|
+
function ge(e) {
|
115
116
|
return p({
|
116
117
|
queryKey: ["ecency-wallets", "coingecko-price", e],
|
117
118
|
queryFn: async () => {
|
@@ -132,11 +133,11 @@ function le(e) {
|
|
132
133
|
default:
|
133
134
|
t = e;
|
134
135
|
}
|
135
|
-
let n =
|
136
|
+
let n = M("gecko"), s;
|
136
137
|
if (n)
|
137
|
-
|
138
|
+
s = n;
|
138
139
|
else {
|
139
|
-
const
|
140
|
+
const r = await (await fetch(
|
140
141
|
"https://api.coingecko.com/api/v3/simple/price",
|
141
142
|
{
|
142
143
|
method: "POST",
|
@@ -148,30 +149,30 @@ function le(e) {
|
|
148
149
|
})
|
149
150
|
}
|
150
151
|
)).json();
|
151
|
-
|
152
|
+
F("gecko", r === void 0 ? w : r), s = r;
|
152
153
|
}
|
153
|
-
return 1 / +
|
154
|
+
return 1 / +s[Object.keys(s)[0]].usd;
|
154
155
|
},
|
155
156
|
enabled: !!e
|
156
157
|
});
|
157
158
|
}
|
158
|
-
function
|
159
|
-
const { data: t } =
|
159
|
+
function q(e) {
|
160
|
+
const { data: t } = T(e);
|
160
161
|
return p({
|
161
162
|
queryKey: ["ecencу-wallets", "hive-keys", e, t],
|
162
163
|
queryFn: async () => {
|
163
164
|
if (!t)
|
164
165
|
throw new Error("[Ecency][Wallets] - no seed to create Hive account");
|
165
|
-
const n =
|
166
|
+
const n = m.fromLogin(e, t, "owner"), s = m.fromLogin(e, t, "active"), a = m.fromLogin(e, t, "posting"), i = m.fromLogin(e, t, "memo");
|
166
167
|
return {
|
167
168
|
username: e,
|
168
169
|
owner: n.toString(),
|
169
|
-
active:
|
170
|
-
posting:
|
170
|
+
active: s.toString(),
|
171
|
+
posting: a.toString(),
|
171
172
|
memo: i.toString(),
|
172
173
|
ownerPubkey: n.createPublic().toString(),
|
173
|
-
activePubkey:
|
174
|
-
postingPubkey:
|
174
|
+
activePubkey: s.createPublic().toString(),
|
175
|
+
postingPubkey: a.createPublic().toString(),
|
175
176
|
memoPubkey: i.createPublic().toString()
|
176
177
|
};
|
177
178
|
}
|
@@ -193,18 +194,18 @@ const L = {
|
|
193
194
|
[o.ATOM]: "m/44'/118'/0'/0/0"
|
194
195
|
// Cosmos (BIP44)
|
195
196
|
};
|
196
|
-
function
|
197
|
-
const { data: n } =
|
197
|
+
function Te(e, t) {
|
198
|
+
const { data: n } = T(e), s = f(), a = u({
|
198
199
|
mutationKey: ["ecency-wallets", "create-wallet", e, t],
|
199
200
|
mutationFn: async () => {
|
200
201
|
if (!n)
|
201
202
|
throw new Error("[Ecency][Wallets] - No seed to create a wallet");
|
202
|
-
const
|
203
|
+
const r = g(t), c = await (r == null ? void 0 : r.getDerivedPrivateKey({
|
203
204
|
mnemonic: n,
|
204
205
|
hdPath: L[t]
|
205
206
|
}));
|
206
|
-
await
|
207
|
-
const l = await (
|
207
|
+
await W(1e3);
|
208
|
+
const l = await (r == null ? void 0 : r.getNewAddress({
|
208
209
|
privateKey: c
|
209
210
|
}));
|
210
211
|
return {
|
@@ -215,44 +216,68 @@ function pe(e, t) {
|
|
215
216
|
currency: t
|
216
217
|
};
|
217
218
|
},
|
218
|
-
onSuccess: (
|
219
|
-
|
220
|
-
["ecency-wallets", "wallets",
|
221
|
-
(c) => new Map(c ? Array.from(c.entries()) : []).set(
|
219
|
+
onSuccess: (r) => {
|
220
|
+
s.setQueryData(
|
221
|
+
["ecency-wallets", "wallets", r.username],
|
222
|
+
(c) => new Map(c ? Array.from(c.entries()) : []).set(r.currency, r)
|
222
223
|
);
|
223
224
|
}
|
224
225
|
}), i = O(() => {
|
225
226
|
}, []);
|
226
227
|
return {
|
227
|
-
createWallet:
|
228
|
+
createWallet: a,
|
228
229
|
importWallet: i
|
229
230
|
};
|
230
231
|
}
|
231
|
-
const
|
232
|
-
|
232
|
+
const d = {
|
233
|
+
privateApiHost: "https://ecency.com",
|
234
|
+
storage: localStorage,
|
235
|
+
storagePrefix: "ecency",
|
236
|
+
hiveClient: new H(
|
237
|
+
[
|
238
|
+
"https://api.hive.blog",
|
239
|
+
"https://api.deathwing.me",
|
240
|
+
"https://rpc.mahdiyari.info",
|
241
|
+
"https://api.openhive.network",
|
242
|
+
"https://techcoderx.com",
|
243
|
+
"https://hive-api.arcange.eu",
|
244
|
+
"https://api.syncad.com",
|
245
|
+
"https://anyx.io",
|
246
|
+
"https://api.c0ff33a.uk",
|
247
|
+
"https://hiveapi.actifit.io",
|
248
|
+
"https://hive-api.3speak.tv"
|
249
|
+
],
|
250
|
+
{
|
251
|
+
timeout: 2e3,
|
252
|
+
failoverThreshold: 2,
|
253
|
+
consoleOnFailover: !0
|
254
|
+
}
|
255
|
+
)
|
256
|
+
};
|
257
|
+
function J(e) {
|
233
258
|
const { data: t } = p({
|
234
259
|
queryKey: ["ecency-wallets", "wallets", e]
|
235
|
-
}), { data: n } =
|
236
|
-
return
|
260
|
+
}), { data: n } = q(e);
|
261
|
+
return u({
|
237
262
|
mutationKey: ["ecency-wallets", "create-account-with-wallets", e],
|
238
|
-
mutationFn: ({ currency:
|
263
|
+
mutationFn: ({ currency: s, address: a }) => fetch(d.privateApiHost + "/private-api/wallets-add", {
|
239
264
|
method: "POST",
|
240
265
|
headers: {
|
241
266
|
"Content-Type": "application/json"
|
242
267
|
},
|
243
268
|
body: JSON.stringify({
|
244
269
|
username: e,
|
245
|
-
token:
|
246
|
-
address:
|
270
|
+
token: s,
|
271
|
+
address: a,
|
247
272
|
meta: {
|
248
273
|
ownerPublicKey: n == null ? void 0 : n.ownerPubkey,
|
249
274
|
activePublicKey: n == null ? void 0 : n.activePubkey,
|
250
275
|
postingPublicKey: n == null ? void 0 : n.postingPubkey,
|
251
276
|
memoPublicKey: n == null ? void 0 : n.memoPubkey,
|
252
277
|
...Array.from((t == null ? void 0 : t.entries()) ?? []).reduce(
|
253
|
-
(i, [
|
278
|
+
(i, [r, c]) => ({
|
254
279
|
...i,
|
255
|
-
[
|
280
|
+
[r]: c.address
|
256
281
|
}),
|
257
282
|
{}
|
258
283
|
)
|
@@ -261,11 +286,11 @@ function q(e) {
|
|
261
286
|
})
|
262
287
|
});
|
263
288
|
}
|
264
|
-
function
|
265
|
-
return
|
289
|
+
function v() {
|
290
|
+
return u({
|
266
291
|
mutationKey: ["ecency-wallets", "check-wallet-existence"],
|
267
292
|
mutationFn: async ({ address: e, currency: t }) => (await (await fetch(
|
268
|
-
|
293
|
+
d.privateApiHost + "/private-api/wallets-exist",
|
269
294
|
{
|
270
295
|
method: "POST",
|
271
296
|
headers: {
|
@@ -279,11 +304,11 @@ function g() {
|
|
279
304
|
)).json()).length === 0
|
280
305
|
});
|
281
306
|
}
|
282
|
-
const
|
307
|
+
const be = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
283
308
|
__proto__: null,
|
284
|
-
useCheckWalletExistence:
|
285
|
-
useCreateAccountWithWallets:
|
286
|
-
}, Symbol.toStringTag, { value: "Module" })),
|
309
|
+
useCheckWalletExistence: v,
|
310
|
+
useCreateAccountWithWallets: J
|
311
|
+
}, Symbol.toStringTag, { value: "Module" })), Q = {
|
287
312
|
[o.BTC]: ["m/84'/0'/0'/0/0"],
|
288
313
|
[o.ETH]: ["m/84'/60'/0'/0/0"],
|
289
314
|
// its not working for Trust, Exodus, todo: check others below
|
@@ -294,43 +319,43 @@ const ue = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
294
319
|
// Disabled
|
295
320
|
[o.ATOM]: ["m/84'/118'/0'/0'/0"]
|
296
321
|
};
|
297
|
-
async function
|
298
|
-
for (const
|
322
|
+
async function G(e, t, n) {
|
323
|
+
for (const s of Q[n] || [])
|
299
324
|
try {
|
300
|
-
const
|
325
|
+
const a = await t.getDerivedPrivateKey({
|
301
326
|
mnemonic: e,
|
302
|
-
hdPath:
|
327
|
+
hdPath: s
|
303
328
|
}), i = await t.getNewAddress({
|
304
|
-
privateKey:
|
329
|
+
privateKey: a,
|
305
330
|
addressType: n === o.BTC ? "segwit_native" : void 0
|
306
331
|
});
|
307
|
-
return [
|
332
|
+
return [a.toString(), i.address];
|
308
333
|
} catch {
|
309
334
|
return [];
|
310
335
|
}
|
311
336
|
return [];
|
312
337
|
}
|
313
|
-
function
|
314
|
-
const n =
|
315
|
-
return
|
338
|
+
function ve(e, t) {
|
339
|
+
const n = f(), { mutateAsync: s } = v();
|
340
|
+
return u({
|
316
341
|
mutationKey: ["ecency-wallets", "import-wallet", e, t],
|
317
|
-
mutationFn: async ({ privateKeyOrSeed:
|
318
|
-
const i =
|
342
|
+
mutationFn: async ({ privateKeyOrSeed: a }) => {
|
343
|
+
const i = g(t);
|
319
344
|
if (!i)
|
320
345
|
throw new Error("Cannot find token for this currency");
|
321
|
-
const
|
322
|
-
let c, l =
|
323
|
-
if (
|
324
|
-
|
346
|
+
const r = a.split(" ").length === 12;
|
347
|
+
let c, l = a;
|
348
|
+
if (r ? [l, c] = await G(
|
349
|
+
a,
|
325
350
|
i,
|
326
351
|
t
|
327
352
|
) : c = (await i.getNewAddress({
|
328
|
-
privateKey:
|
329
|
-
})).address, !c || !
|
353
|
+
privateKey: a
|
354
|
+
})).address, !c || !a)
|
330
355
|
throw new Error(
|
331
356
|
"Private key/seed phrase isn't matching with public key or token"
|
332
357
|
);
|
333
|
-
if (!await
|
358
|
+
if (!await s({
|
334
359
|
address: c,
|
335
360
|
currency: t
|
336
361
|
}))
|
@@ -343,13 +368,13 @@ function me(e, t) {
|
|
343
368
|
publicKey: ""
|
344
369
|
};
|
345
370
|
},
|
346
|
-
onSuccess: ({ privateKey:
|
371
|
+
onSuccess: ({ privateKey: a, publicKey: i, address: r }) => {
|
347
372
|
n.setQueryData(
|
348
373
|
["ecency-wallets", "wallets", e],
|
349
374
|
(c) => new Map(c ? Array.from(c.entries()) : []).set(t, {
|
350
|
-
privateKey:
|
375
|
+
privateKey: a,
|
351
376
|
publicKey: i,
|
352
|
-
address:
|
377
|
+
address: r,
|
353
378
|
username: e,
|
354
379
|
currency: t,
|
355
380
|
custom: !0
|
@@ -358,16 +383,93 @@ function me(e, t) {
|
|
358
383
|
}
|
359
384
|
});
|
360
385
|
}
|
386
|
+
function I(e) {
|
387
|
+
let t = atob(e);
|
388
|
+
if (t[0] === "{")
|
389
|
+
return JSON.parse(t);
|
390
|
+
}
|
391
|
+
const h = (e) => {
|
392
|
+
try {
|
393
|
+
const t = d.storage.getItem(
|
394
|
+
d.storagePrefix + "_user_" + e
|
395
|
+
);
|
396
|
+
return I(JSON.parse(t));
|
397
|
+
} catch (t) {
|
398
|
+
console.error(t);
|
399
|
+
return;
|
400
|
+
}
|
401
|
+
}, $ = (e) => h(e) && h(e).accessToken, U = (e) => h(e) && h(e).postingKey;
|
402
|
+
function V(e = [], t, n) {
|
403
|
+
return u({
|
404
|
+
mutationKey: [...e, t],
|
405
|
+
mutationFn: async (s) => {
|
406
|
+
const a = U(t);
|
407
|
+
if (a) {
|
408
|
+
const r = m.fromString(a);
|
409
|
+
return d.hiveClient.broadcast.sendOperations(
|
410
|
+
n(s),
|
411
|
+
r
|
412
|
+
);
|
413
|
+
}
|
414
|
+
let i = $(t);
|
415
|
+
if (i)
|
416
|
+
return (await new B.Client({
|
417
|
+
accessToken: i
|
418
|
+
}).broadcast(n(s))).result;
|
419
|
+
throw new Error(
|
420
|
+
"[SDK][Broadcast] – cannot broadcast w/o posting key or token"
|
421
|
+
);
|
422
|
+
}
|
423
|
+
});
|
424
|
+
}
|
425
|
+
function z(e) {
|
426
|
+
return V(
|
427
|
+
["accounts", "update"],
|
428
|
+
e,
|
429
|
+
({ newProfile: t }) => [
|
430
|
+
[
|
431
|
+
"account_update2",
|
432
|
+
{
|
433
|
+
account: e,
|
434
|
+
json_metadata: "",
|
435
|
+
posting_json_metadata: JSON.stringify({
|
436
|
+
profile: { ...t, version: 2 }
|
437
|
+
}),
|
438
|
+
extensions: []
|
439
|
+
}
|
440
|
+
]
|
441
|
+
]
|
442
|
+
);
|
443
|
+
}
|
444
|
+
function Pe(e) {
|
445
|
+
const { data: t } = p({
|
446
|
+
queryKey: ["ecency-wallets", "wallets", e]
|
447
|
+
}), { mutateAsync: n } = z(e);
|
448
|
+
return u({
|
449
|
+
mutationKey: ["ecency-wallets", "save-wallet-to-metadata", e],
|
450
|
+
mutationFn: () => n({
|
451
|
+
...Array.from((t == null ? void 0 : t.entries()) ?? []).reduce(
|
452
|
+
(s, [a, i]) => ({
|
453
|
+
...s,
|
454
|
+
[a]: i.address
|
455
|
+
}),
|
456
|
+
{}
|
457
|
+
)
|
458
|
+
})
|
459
|
+
});
|
460
|
+
}
|
361
461
|
export {
|
362
462
|
o as EcencyWalletCurrency,
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
463
|
+
be as EcencyWalletsPrivateApi,
|
464
|
+
W as delay,
|
465
|
+
g as getWallet,
|
466
|
+
ye as mnemonicToSeedBip39,
|
467
|
+
z as useAccountUpdate,
|
468
|
+
ge as useCoinGeckoPriceQuery,
|
469
|
+
fe as useGetExternalWalletBalanceQuery,
|
470
|
+
q as useHiveKeysQuery,
|
471
|
+
ve as useImportWallet,
|
472
|
+
Pe as useSaveWalletInformationToMetadata,
|
473
|
+
T as useSeedPhrase,
|
474
|
+
Te as useWalletCreate
|
373
475
|
};
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "@ecency/sdk",
|
3
3
|
"private": false,
|
4
|
-
"version": "1.0.
|
4
|
+
"version": "1.0.4",
|
5
5
|
"type": "module",
|
6
6
|
"license": "MIT",
|
7
7
|
"main": "./dist/ecency-sdk.umd.js",
|
@@ -41,6 +41,7 @@
|
|
41
41
|
"@okxweb3/coin-ton": "^1.1.1-beta.1",
|
42
42
|
"@okxweb3/coin-tron": "^1.1.0",
|
43
43
|
"@okxweb3/crypto-lib": "^1.0.10",
|
44
|
-
"bip39": "^3.1.0"
|
44
|
+
"bip39": "^3.1.0",
|
45
|
+
"hivesigner": "3.3.4"
|
45
46
|
}
|
46
47
|
}
|