@otoplo/wallet-common 0.1.15 → 0.2.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.
- package/dist/index.js +555 -579
- package/dist/index.js.map +1 -1
- package/dist/types/persistence/datastore/db.d.ts +5 -3
- package/dist/types/persistence/datastore/db.d.ts.map +1 -1
- package/dist/types/persistence/wallet-db.d.ts +10 -18
- package/dist/types/persistence/wallet-db.d.ts.map +1 -1
- package/dist/types/services/asset.d.ts +5 -9
- package/dist/types/services/asset.d.ts.map +1 -1
- package/dist/types/services/cache.d.ts +4 -2
- package/dist/types/services/cache.d.ts.map +1 -1
- package/dist/types/services/wallet.d.ts +2 -1
- package/dist/types/services/wallet.d.ts.map +1 -1
- package/dist/types/state/hooks.d.ts +2 -1
- package/dist/types/state/hooks.d.ts.map +1 -1
- package/dist/types/state/slices/market.d.ts +54 -0
- package/dist/types/state/slices/market.d.ts.map +1 -0
- package/dist/types/state/slices/status.d.ts +0 -27
- package/dist/types/state/slices/status.d.ts.map +1 -1
- package/dist/types/state/slices/wallet.d.ts +21 -220
- package/dist/types/state/slices/wallet.d.ts.map +1 -1
- package/dist/types/state/store.d.ts +3 -0
- package/dist/types/state/store.d.ts.map +1 -1
- package/dist/types/types/db.types.d.ts +16 -11
- package/dist/types/types/db.types.d.ts.map +1 -1
- package/dist/types/types/wallet.types.d.ts +39 -14
- package/dist/types/types/wallet.types.d.ts.map +1 -1
- package/dist/types/utils/asset.d.ts +3 -6
- package/dist/types/utils/asset.d.ts.map +1 -1
- package/dist/types/utils/common.d.ts +0 -1
- package/dist/types/utils/common.d.ts.map +1 -1
- package/dist/types/utils/enums.d.ts +0 -4
- package/dist/types/utils/enums.d.ts.map +1 -1
- package/dist/types/utils/index.d.ts +1 -1
- package/dist/types/utils/index.d.ts.map +1 -1
- package/dist/types/utils/{price.d.ts → market.d.ts} +19 -13
- package/dist/types/utils/market.d.ts.map +1 -0
- package/package.json +4 -5
- package/src/persistence/datastore/db.ts +5 -3
- package/src/persistence/wallet-db.ts +28 -28
- package/src/services/asset.ts +69 -162
- package/src/services/cache.ts +12 -2
- package/src/services/wallet.ts +23 -21
- package/src/state/hooks.ts +3 -1
- package/src/state/slices/market.ts +47 -0
- package/src/state/slices/status.ts +2 -31
- package/src/state/slices/wallet.ts +8 -13
- package/src/state/store.ts +3 -0
- package/src/types/db.types.ts +17 -12
- package/src/types/wallet.types.ts +40 -16
- package/src/utils/asset.ts +12 -52
- package/src/utils/common.ts +0 -6
- package/src/utils/enums.ts +0 -5
- package/src/utils/index.ts +1 -1
- package/src/utils/market.ts +97 -0
- package/dist/types/utils/price.d.ts.map +0 -1
- package/src/utils/price.ts +0 -46
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare function getNiftyToken(): TokenEntity;
|
|
3
|
-
export declare function fetchNiftyNFT(id: string): Promise<Uint8Array>;
|
|
4
|
-
export declare function isNiftySubgroup(group: string): boolean;
|
|
5
|
-
export declare function fetchAssetDoc(url: string): Promise<any>;
|
|
6
|
-
export declare function fetchAssetBlob(url: string): Promise<Uint8Array>;
|
|
1
|
+
import { AssetInfo } from '../types';
|
|
7
2
|
export declare function transformTokenIconUrl(icon: string, documentUrl: string): string;
|
|
8
3
|
export declare function parseTokenDataUrl(data?: string): string | null;
|
|
4
|
+
export declare function getAssetMetadata(token: string): Promise<AssetInfo>;
|
|
5
|
+
export declare function getAssetFileUrl(token: string, asset: string): string;
|
|
9
6
|
//# sourceMappingURL=asset.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"asset.d.ts","sourceRoot":"","sources":["../../../src/utils/asset.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"asset.d.ts","sourceRoot":"","sources":["../../../src/utils/asset.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE1C,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAY/E;AAED,wBAAgB,iBAAiB,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAK9D;AAYD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAElE;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAC,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAEnE"}
|
|
@@ -23,5 +23,4 @@ export declare function getFileMediaType(filename: string): 'video' | 'audio' |
|
|
|
23
23
|
export declare function getFileMimeType(filename: string): string;
|
|
24
24
|
export declare function sleep(ms: number): Promise<void>;
|
|
25
25
|
export declare function prettifyAmount(amount: string | number): string;
|
|
26
|
-
export declare function calcAmountValue(amount: string | number, price: number, prettify?: boolean): string;
|
|
27
26
|
//# sourceMappingURL=common.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../../src/utils/common.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,WAAW,EAAsC,MAAM,YAAY,CAAC;AACtF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAGrD,eAAO,MAAM,cAAc,KAAK,CAAC;AACjC,eAAO,MAAM,SAAS,uBAAuB,CAAC;AAC9C,eAAO,MAAM,iBAAiB,SAAS,CAAC;AACxC,eAAO,MAAM,mBAAmB,iDAAkD,CAAC;AAEnF,wBAAgB,SAAS,IAAI,OAAO,CAEnC;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAKxD;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,cAAkC,GAAG,OAAO,CAEnG;AAED,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAKjF;AAED,wBAAgB,aAAa,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,GAAG,EAAE,GAAG,IAAI,GAAG,GAAG,IAAI,SAAS,GAAG,EAAE,GAAG,IAAI,GAAG,EAAE,CAE5F;AAED,wBAAgB,oBAAoB,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,SAAS,SAAI,GAAG,MAAM,CAWxE;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAKzD;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,CAK5D;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKlD;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKpD;AAED,wBAAgB,wBAAwB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAQlF;AAED,wBAAgB,UAAU,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,CAOvD;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAc7F;AA4BD,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,CAM1F;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAMxD;AAED,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAM9D
|
|
1
|
+
{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../../src/utils/common.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,WAAW,EAAsC,MAAM,YAAY,CAAC;AACtF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAGrD,eAAO,MAAM,cAAc,KAAK,CAAC;AACjC,eAAO,MAAM,SAAS,uBAAuB,CAAC;AAC9C,eAAO,MAAM,iBAAiB,SAAS,CAAC;AACxC,eAAO,MAAM,mBAAmB,iDAAkD,CAAC;AAEnF,wBAAgB,SAAS,IAAI,OAAO,CAEnC;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAKxD;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,cAAkC,GAAG,OAAO,CAEnG;AAED,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAKjF;AAED,wBAAgB,aAAa,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,GAAG,EAAE,GAAG,IAAI,GAAG,GAAG,IAAI,SAAS,GAAG,EAAE,GAAG,IAAI,GAAG,EAAE,CAE5F;AAED,wBAAgB,oBAAoB,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,SAAS,SAAI,GAAG,MAAM,CAWxE;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAKzD;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,CAK5D;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKlD;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKpD;AAED,wBAAgB,wBAAwB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAQlF;AAED,wBAAgB,UAAU,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,CAOvD;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAc7F;AA4BD,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,CAM1F;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAMxD;AAED,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAM9D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"enums.d.ts","sourceRoot":"","sources":["../../../src/utils/enums.ts"],"names":[],"mappings":"AAAA,oBAAY,WAAW;IACrB,IAAI,IAAI;IACR,KAAK,IAAI;IACT,IAAI,IAAI;CACT;AAED,oBAAY,QAAQ;IAClB,OAAO,IAAI;IACX,MAAM,IAAI;CACX;AAED,oBAAY,kBAAkB;IAC5B,WAAW,gBAAgB;IAC3B,QAAQ,aAAa;IACrB,eAAe,oBAAoB;IACnC,eAAe,oBAAoB;CACpC
|
|
1
|
+
{"version":3,"file":"enums.d.ts","sourceRoot":"","sources":["../../../src/utils/enums.ts"],"names":[],"mappings":"AAAA,oBAAY,WAAW;IACrB,IAAI,IAAI;IACR,KAAK,IAAI;IACT,IAAI,IAAI;CACT;AAED,oBAAY,QAAQ;IAClB,OAAO,IAAI;IACX,MAAM,IAAI;CACX;AAED,oBAAY,kBAAkB;IAC5B,WAAW,gBAAgB;IAC3B,QAAQ,aAAa;IACrB,eAAe,oBAAoB;IACnC,eAAe,oBAAoB;CACpC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { MarketData } from '../types/wallet.types';
|
|
2
2
|
export declare const CURRENCIES: readonly [{
|
|
3
3
|
readonly code: "usd";
|
|
4
4
|
readonly symbol: "$";
|
|
@@ -11,14 +11,6 @@ export declare const CURRENCIES: readonly [{
|
|
|
11
11
|
readonly code: "gbp";
|
|
12
12
|
readonly symbol: "£";
|
|
13
13
|
readonly name: "British Pound";
|
|
14
|
-
}, {
|
|
15
|
-
readonly code: "cny";
|
|
16
|
-
readonly symbol: "¥";
|
|
17
|
-
readonly name: "Chinese Yuan";
|
|
18
|
-
}, {
|
|
19
|
-
readonly code: "jpy";
|
|
20
|
-
readonly symbol: "¥";
|
|
21
|
-
readonly name: "Japanese Yen";
|
|
22
14
|
}, {
|
|
23
15
|
readonly code: "aud";
|
|
24
16
|
readonly symbol: "A$";
|
|
@@ -31,12 +23,26 @@ export declare const CURRENCIES: readonly [{
|
|
|
31
23
|
readonly code: "chf";
|
|
32
24
|
readonly symbol: "Fr";
|
|
33
25
|
readonly name: "Swiss Franc";
|
|
26
|
+
}, {
|
|
27
|
+
readonly code: "inr";
|
|
28
|
+
readonly symbol: "₹";
|
|
29
|
+
readonly name: "Indian Rupee";
|
|
30
|
+
}, {
|
|
31
|
+
readonly code: "cny";
|
|
32
|
+
readonly symbol: "¥";
|
|
33
|
+
readonly name: "Chinese Yuan";
|
|
34
|
+
}, {
|
|
35
|
+
readonly code: "jpy";
|
|
36
|
+
readonly symbol: "¥";
|
|
37
|
+
readonly name: "Japanese Yen";
|
|
34
38
|
}];
|
|
35
39
|
export type CurrencyCode = typeof CURRENCIES[number]['code'];
|
|
36
40
|
export type CurrencySymbol = typeof CURRENCIES[number]['symbol'];
|
|
37
41
|
export declare const currencySymbols: Record<CurrencyCode, CurrencySymbol>;
|
|
38
|
-
export declare const currencyCodes: ("usd" | "eur" | "gbp" | "
|
|
39
|
-
export declare
|
|
42
|
+
export declare const currencyCodes: ("usd" | "eur" | "gbp" | "aud" | "cad" | "chf" | "inr" | "cny" | "jpy")[];
|
|
43
|
+
export declare const SUPPORTED_TOKENS: Record<string, string>;
|
|
44
|
+
export declare function getMarketData(currency: CurrencyCode): Promise<Record<string, MarketData>>;
|
|
40
45
|
export declare function getCurrencySymbol(currency: CurrencyCode): string;
|
|
41
|
-
export declare function
|
|
42
|
-
|
|
46
|
+
export declare function calculateFiatValue(amount: string | number, price: number, currency?: CurrencyCode): string;
|
|
47
|
+
export declare function formatMoney(value: string | number, currency: CurrencyCode, locale?: string): string;
|
|
48
|
+
//# sourceMappingURL=market.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"market.d.ts","sourceRoot":"","sources":["../../../src/utils/market.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAqBxD,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAUb,CAAC;AAEX,MAAM,MAAM,YAAY,GAAG,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7D,MAAM,MAAM,cAAc,GAAG,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC;AAEjE,eAAO,MAAM,eAAe,EAEvB,MAAM,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC;AAE1C,eAAO,MAAM,aAAa,2EAA8B,CAAC;AAEzD,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAEnD,CAAC;AAEF,wBAAsB,aAAa,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CA4B/F;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,CAEhE;AAGD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,YAAY,GAAG,MAAM,CAI1G;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAU,GAAG,MAAM,CAOpG"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@otoplo/wallet-common",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Shared common library for internal use in Otoplo wallet",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "vgrunner",
|
|
@@ -31,14 +31,13 @@
|
|
|
31
31
|
"url": "git+https://gitlab.com/nexa/otoplo/otoplo-wallet-common.git"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@scure/bip39": "^2.0.1"
|
|
35
|
-
"jszip": "^3.10.1"
|
|
34
|
+
"@scure/bip39": "^2.0.1"
|
|
36
35
|
},
|
|
37
36
|
"devDependencies": {
|
|
38
37
|
"del-cli": "^7.0.0",
|
|
39
38
|
"eslint": "^9.39.2",
|
|
40
39
|
"typescript": "^5.9.3",
|
|
41
|
-
"typescript-eslint": "^8.
|
|
40
|
+
"typescript-eslint": "^8.54.0",
|
|
42
41
|
"vite": "^7.3.1",
|
|
43
42
|
"vite-plugin-dts": "^4.5.4"
|
|
44
43
|
},
|
|
@@ -46,7 +45,7 @@
|
|
|
46
45
|
"@otoplo/electrum-client": "^0.2.1",
|
|
47
46
|
"@reduxjs/toolkit": "^2.11.2",
|
|
48
47
|
"js-big-decimal": "^2.2.0",
|
|
49
|
-
"libnexa-ts": "^3.0.
|
|
48
|
+
"libnexa-ts": "^3.0.1",
|
|
50
49
|
"react": ">=19.1.0",
|
|
51
50
|
"react-redux": "^9.2.0",
|
|
52
51
|
"wallet-comms-sdk": "^0.9.1"
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AccountEntity, AssetEntity, AssetTransactionEntity, NftEntity, SessionEntity, TokenEntity, TransactionEntity, AddressEntity, VaultEntity } from "../../types/db.types";
|
|
2
|
+
import type { AssetType } from "../../types/wallet.types";
|
|
2
3
|
|
|
3
4
|
export interface DBStore {
|
|
4
5
|
clearData(): Promise<void>;
|
|
@@ -11,22 +12,23 @@ export interface DBStore {
|
|
|
11
12
|
countTransactions(account: number, tokenId?: string): Promise<number>;
|
|
12
13
|
clearTransactions(account: number): Promise<void>;
|
|
13
14
|
|
|
15
|
+
countTokens(account: number): Promise<number>;
|
|
14
16
|
upsertToken(token: TokenEntity): Promise<void>;
|
|
15
|
-
getTokens(account: number): Promise<
|
|
17
|
+
getTokens(account: number, pageNum: number, pageSize: number): Promise<TokenEntity[]>;
|
|
16
18
|
getToken(id: string): Promise<TokenEntity | undefined>;
|
|
17
19
|
deleteToken(id: string): Promise<void>;
|
|
18
20
|
|
|
19
21
|
countNfts(account: number): Promise<number>;
|
|
20
22
|
upsertNft(nft: NftEntity): Promise<void>;
|
|
21
|
-
getNfts(account: number, pageNum: number, pageSize: number): Promise<
|
|
23
|
+
getNfts(account: number, pageNum: number, pageSize: number): Promise<NftEntity[]>;
|
|
22
24
|
getNft(id: string): Promise<NftEntity | undefined>;
|
|
23
25
|
deleteNft(id: string): Promise<void>;
|
|
24
26
|
isNftExist(id: string): Promise<boolean>;
|
|
25
27
|
|
|
26
28
|
upsertAsset(asset: AssetEntity): Promise<void>;
|
|
29
|
+
getAssets(account: number, type: AssetType): Promise<AssetEntity[]>;
|
|
27
30
|
deleteAsset(account: number, id: string): Promise<void>;
|
|
28
31
|
countAssetsById(id: string): Promise<number>;
|
|
29
|
-
isAssetExistForAccount(account: number, id: string): Promise<boolean>
|
|
30
32
|
|
|
31
33
|
upsertAccount(account: AccountEntity): Promise<void>;
|
|
32
34
|
getAccounts(): Promise<AccountEntity[]>;
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import type { DBStore } from "./datastore/db";
|
|
2
|
-
import { AccountType
|
|
2
|
+
import { AccountType } from "../utils/enums";
|
|
3
3
|
import type { AccountDTO, AccountEntity, AddressDTO, AddressEntity, AssetEntity, AssetTransactionEntity, NftEntity, SessionEntity, TokenEntity, TransactionEntity, VaultDTO, VaultEntity } from "../types/db.types";
|
|
4
|
+
import type { AssetType } from "../types/wallet.types";
|
|
4
5
|
import { currentTimestamp } from "../utils/common";
|
|
5
6
|
|
|
6
7
|
export type DBEvent =
|
|
7
8
|
| { type: 'tx_refresh'; }
|
|
8
9
|
| { type: 'nft_refresh'; }
|
|
9
|
-
| { type: '
|
|
10
|
-
| { type: 'token_removed'; accountId: number; tokenId: string; }
|
|
11
|
-
| { type: 'nft_deleted'; id: string; }
|
|
10
|
+
| { type: 'token_refresh'; }
|
|
12
11
|
|
|
13
12
|
export type DBUpdateCallback = (event: DBEvent) => void;
|
|
14
13
|
|
|
@@ -50,11 +49,11 @@ export class WalletDB {
|
|
|
50
49
|
return this.store.upsertAssetTransaction(assetTx);
|
|
51
50
|
}
|
|
52
51
|
|
|
53
|
-
public async getLocalTransactions(account: number, tokenId?: string): Promise<TransactionEntity[]
|
|
52
|
+
public async getLocalTransactions(account: number, tokenId?: string): Promise<TransactionEntity[]> {
|
|
54
53
|
return this.store.getTransactions(account, tokenId);
|
|
55
54
|
}
|
|
56
55
|
|
|
57
|
-
public async getPageLocalTransactions(account: number, pageNum: number, pageSize: number, tokenId?: string): Promise<TransactionEntity[]
|
|
56
|
+
public async getPageLocalTransactions(account: number, pageNum: number, pageSize: number, tokenId?: string): Promise<TransactionEntity[]> {
|
|
58
57
|
return this.store.getPageTransactions(account, pageNum, pageSize, tokenId);
|
|
59
58
|
}
|
|
60
59
|
|
|
@@ -71,16 +70,16 @@ export class WalletDB {
|
|
|
71
70
|
const asset: AssetEntity = {
|
|
72
71
|
accountId: account,
|
|
73
72
|
tokenIdHex: token.tokenIdHex,
|
|
74
|
-
type:
|
|
73
|
+
type: "token",
|
|
75
74
|
addedTime: currentTimestamp()
|
|
76
75
|
}
|
|
77
|
-
await this.store.upsertAsset(asset);
|
|
78
76
|
await this.store.upsertToken(token);
|
|
79
|
-
this.
|
|
77
|
+
await this.saveAsset(asset);
|
|
78
|
+
this.notify({ type: 'token_refresh' });
|
|
80
79
|
}
|
|
81
80
|
|
|
82
|
-
public async getLocalTokens(account: number): Promise<
|
|
83
|
-
return this.store.getTokens(account);
|
|
81
|
+
public async getLocalTokens(account: number, pageNum: number, pageSize: number): Promise<TokenEntity[]> {
|
|
82
|
+
return this.store.getTokens(account, pageNum, pageSize);
|
|
84
83
|
}
|
|
85
84
|
|
|
86
85
|
public async getToken(id: string): Promise<TokenEntity | undefined> {
|
|
@@ -93,15 +92,22 @@ export class WalletDB {
|
|
|
93
92
|
if (count == 0) {
|
|
94
93
|
await this.store.deleteToken(tokenId);
|
|
95
94
|
}
|
|
96
|
-
this.notify({ type: '
|
|
95
|
+
this.notify({ type: 'token_refresh' });
|
|
97
96
|
}
|
|
98
97
|
|
|
99
|
-
public async saveNft(
|
|
98
|
+
public async saveNft(account: number, nft: NftEntity, time: number): Promise<void> {
|
|
99
|
+
const asset: AssetEntity = {
|
|
100
|
+
accountId: account,
|
|
101
|
+
tokenIdHex: nft.tokenIdHex,
|
|
102
|
+
type: "nft",
|
|
103
|
+
addedTime: time
|
|
104
|
+
}
|
|
100
105
|
await this.store.upsertNft(nft);
|
|
101
|
-
await this.saveAsset(asset
|
|
106
|
+
await this.saveAsset(asset);
|
|
107
|
+
this.notify({ type: 'nft_refresh' });
|
|
102
108
|
}
|
|
103
109
|
|
|
104
|
-
public async getLocalNfts(account: number, pageNum: number, pageSize: number): Promise<
|
|
110
|
+
public async getLocalNfts(account: number, pageNum: number, pageSize: number): Promise<NftEntity[]> {
|
|
105
111
|
return this.store.getNfts(account, pageNum, pageSize);
|
|
106
112
|
}
|
|
107
113
|
|
|
@@ -109,16 +115,13 @@ export class WalletDB {
|
|
|
109
115
|
return this.store.getNft(id);
|
|
110
116
|
}
|
|
111
117
|
|
|
112
|
-
public async deleteNft(account: number, tokenId: string
|
|
118
|
+
public async deleteNft(account: number, tokenId: string): Promise<void> {
|
|
113
119
|
await this.removeAsset(account, tokenId);
|
|
114
120
|
const count = await this.store.countAssetsById(tokenId);
|
|
115
121
|
if (count == 0) {
|
|
116
122
|
await this.store.deleteNft(tokenId);
|
|
117
|
-
this.notify({ type: 'nft_deleted', id: tokenId });
|
|
118
|
-
}
|
|
119
|
-
if (notify) {
|
|
120
|
-
this.notify({ type: 'nft_refresh' });
|
|
121
123
|
}
|
|
124
|
+
this.notify({ type: 'nft_refresh' });
|
|
122
125
|
}
|
|
123
126
|
|
|
124
127
|
public async countLocalNfts(account: number): Promise<number> {
|
|
@@ -129,21 +132,18 @@ export class WalletDB {
|
|
|
129
132
|
return this.store.isNftExist(id);
|
|
130
133
|
}
|
|
131
134
|
|
|
132
|
-
public async
|
|
135
|
+
public async getAssets(account: number, type: AssetType): Promise<AssetEntity[]> {
|
|
136
|
+
return this.store.getAssets(account, type);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
public async saveAsset(asset: AssetEntity): Promise<void> {
|
|
133
140
|
await this.store.upsertAsset(asset);
|
|
134
|
-
if (notifyNft) {
|
|
135
|
-
this.notify({ type: 'nft_refresh' });
|
|
136
|
-
}
|
|
137
141
|
}
|
|
138
142
|
|
|
139
143
|
public async removeAsset(account: number, id: string): Promise<void> {
|
|
140
144
|
return this.store.deleteAsset(account, id);
|
|
141
145
|
}
|
|
142
146
|
|
|
143
|
-
public async isAssetExistForAccount(account: number, id: string): Promise<boolean> {
|
|
144
|
-
return this.store.isAssetExistForAccount(account, id);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
147
|
public async saveAccount(account: AccountDTO): Promise<void> {
|
|
148
148
|
const accountEntity: AccountEntity = {
|
|
149
149
|
id: account.id,
|
package/src/services/asset.ts
CHANGED
|
@@ -1,200 +1,102 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import { currentTimestamp, getAddressBuffer, tokenHexToAddr, tokenIdToHex } from "../utils/common";
|
|
5
|
-
import { AssetType } from "../utils/enums";
|
|
1
|
+
import type { NftEntity, TokenEntity } from "../types/db.types";
|
|
2
|
+
import { getAssetMetadata } from "../utils/asset";
|
|
3
|
+
import { currentTimestamp, tokenIdToHex } from "../utils/common";
|
|
6
4
|
import type { WalletDB } from "../persistence/wallet-db";
|
|
7
|
-
import type { RostrumService } from "./rostrum";
|
|
8
5
|
import type { WalletCache } from "./cache";
|
|
9
|
-
import JSZip from "jszip";
|
|
10
6
|
import type { AssetInfo, Balance } from "../types/wallet.types";
|
|
11
7
|
|
|
12
8
|
export class AssetService {
|
|
13
9
|
|
|
14
10
|
private readonly walletDb: WalletDB;
|
|
15
|
-
private readonly rostrumService: RostrumService;
|
|
16
11
|
private readonly walletCache: WalletCache;
|
|
17
12
|
|
|
18
|
-
constructor(walletDb: WalletDB,
|
|
13
|
+
constructor(walletDb: WalletDB, walletCache: WalletCache) {
|
|
19
14
|
this.walletDb = walletDb;
|
|
20
|
-
this.rostrumService = rostrumService;
|
|
21
15
|
this.walletCache = walletCache;
|
|
22
16
|
}
|
|
23
17
|
|
|
24
|
-
public async
|
|
18
|
+
public async getAssetInfo(assetId: string): Promise<AssetInfo | undefined> {
|
|
25
19
|
try {
|
|
26
|
-
if (
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
20
|
+
if (this.walletCache.hasToken(assetId)) {
|
|
21
|
+
const token = await this.walletCache.getToken(assetId);
|
|
22
|
+
return {
|
|
23
|
+
type: "token",
|
|
24
|
+
parent: token!.parent,
|
|
25
|
+
token: token!.token,
|
|
26
|
+
tokenIdHex: token!.tokenIdHex,
|
|
27
|
+
data: {
|
|
28
|
+
name: token!.name,
|
|
29
|
+
ticker: token!.ticker,
|
|
30
|
+
decimals: token!.decimals,
|
|
31
|
+
iconUrl: token!.iconUrl
|
|
32
|
+
}
|
|
30
33
|
}
|
|
31
34
|
}
|
|
32
35
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
if (genesis.op_return_id == GroupIdType.NRC1) {
|
|
49
|
-
const token_zip = await fetchAssetBlob(genesis.document_url);
|
|
50
|
-
const zip = await JSZip.loadAsync(token_zip);
|
|
51
|
-
const info = zip.file('info.json');
|
|
52
|
-
if (info) {
|
|
53
|
-
const infoData = await info.async('string');
|
|
54
|
-
const infoJson = JSON.parse(infoData);
|
|
55
|
-
iconUrl = transformTokenIconUrl(infoJson[0]?.icon, genesis.document_url);
|
|
56
|
-
}
|
|
57
|
-
} else {
|
|
58
|
-
const infoJson = await fetchAssetDoc(genesis.document_url);
|
|
59
|
-
iconUrl = transformTokenIconUrl(infoJson[0]?.icon, genesis.document_url);
|
|
36
|
+
if (this.walletCache.hasNft(assetId)) {
|
|
37
|
+
const nft = await this.walletCache.getNft(assetId);
|
|
38
|
+
return {
|
|
39
|
+
type: "nft",
|
|
40
|
+
parent: nft!.parent,
|
|
41
|
+
token: nft!.token,
|
|
42
|
+
tokenIdHex: nft!.tokenIdHex,
|
|
43
|
+
data: {
|
|
44
|
+
name: nft!.name,
|
|
45
|
+
series: nft!.series,
|
|
46
|
+
collection: nft!.collection,
|
|
47
|
+
author: nft!.author,
|
|
48
|
+
public: nft!.public,
|
|
49
|
+
front: nft!.front,
|
|
50
|
+
back: nft!.back
|
|
60
51
|
}
|
|
61
|
-
} catch (e) {
|
|
62
|
-
console.error("Failed to load metadata", e)
|
|
63
52
|
}
|
|
64
53
|
}
|
|
65
|
-
|
|
66
|
-
const tokenEntity: TokenEntity = {
|
|
67
|
-
token: genesis.group,
|
|
68
|
-
tokenIdHex: genesis.token_id_hex,
|
|
69
|
-
decimals: genesis.decimal_places ?? 0,
|
|
70
|
-
parentGroup: parent,
|
|
71
|
-
name: genesis.name ?? "",
|
|
72
|
-
ticker: genesis.ticker ?? "",
|
|
73
|
-
iconUrl: iconUrl
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
return tokenEntity;
|
|
77
|
-
} catch (e) {
|
|
78
|
-
console.error(e)
|
|
79
|
-
return undefined;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
public async isNftToken(token: string): Promise<boolean> {
|
|
84
|
-
try {
|
|
85
|
-
if (isNiftySubgroup(token)) {
|
|
86
|
-
return true;
|
|
87
|
-
}
|
|
88
54
|
|
|
89
|
-
|
|
90
|
-
if (cachedToken) {
|
|
91
|
-
return true;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
const genesis = await this.rostrumService.getTokenGenesis(token);
|
|
95
|
-
if (genesis.op_return_id == GroupIdType.NRC3) {
|
|
96
|
-
return true;
|
|
97
|
-
}
|
|
55
|
+
return await getAssetMetadata(assetId);
|
|
98
56
|
} catch (e) {
|
|
99
|
-
console.error(e)
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
return false;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
public async getAssetInfo(token: string): Promise<AssetInfo | undefined> {
|
|
106
|
-
let asset: AssetInfo | undefined = await this.getTokenInfo(token);
|
|
107
|
-
if (!asset) {
|
|
108
|
-
const isNft = await this.isNftToken(token);
|
|
109
|
-
if (isNft) {
|
|
110
|
-
asset = {
|
|
111
|
-
token: tokenHexToAddr(token),
|
|
112
|
-
tokenIdHex: tokenIdToHex(token),
|
|
113
|
-
decimals: 0,
|
|
114
|
-
};
|
|
115
|
-
}
|
|
57
|
+
console.error(e);
|
|
58
|
+
return undefined;
|
|
116
59
|
}
|
|
117
|
-
return asset;
|
|
118
60
|
}
|
|
119
61
|
|
|
120
62
|
public async handleNftReceive(accountId: number, tokenIdHex: string, time: number): Promise<void> {
|
|
121
|
-
const
|
|
122
|
-
if (
|
|
123
|
-
const asset: AssetEntity = {
|
|
124
|
-
accountId: accountId,
|
|
125
|
-
tokenIdHex: tokenIdHex,
|
|
126
|
-
type: AssetType.NFT,
|
|
127
|
-
addedTime: time
|
|
128
|
-
}
|
|
129
|
-
await this.walletDb.saveAsset(asset, true);
|
|
130
|
-
return;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
const genesis = await this.rostrumService.getTokenGenesis(tokenIdHex);
|
|
134
|
-
if (genesis.op_return_id == GroupIdType.NRC3) {
|
|
135
|
-
const groupId = getAddressBuffer(tokenIdHex);
|
|
136
|
-
if (GroupToken.isSubgroup(groupId)) {
|
|
137
|
-
const parentGroupId = new Address(groupId.subarray(0, 32), Networks.defaultNetwork, AddressType.GroupIdAddress).toString();
|
|
138
|
-
const parentGenesis = await this.rostrumService.getTokenGenesis(parentGroupId);
|
|
139
|
-
if (parentGenesis?.op_return_id == GroupIdType.NRC2) {
|
|
140
|
-
// parent is an NRC-2 collection, this is an NRC-3 NFT. The name of the collection and NRC-3 NFT belongs
|
|
141
|
-
// to is the name of the NRC-2 collection.
|
|
142
|
-
await this.saveNft(accountId, tokenIdHex, genesis.document_url ?? '', parentGroupId, time, parentGenesis?.name ?? "");
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
} else if (isNiftySubgroup(tokenIdHex)) {
|
|
146
|
-
// NiftyArt does not have collections, pass "" for the collection
|
|
147
|
-
await this.saveNft(accountId, tokenIdHex, 'nifty', getNiftyToken().token, time, "");
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
private async saveNft(account: number, hexId: string, source: string, parent: string, time: number, collection: string): Promise<void> {
|
|
152
|
-
if (!source) {
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
try {
|
|
157
|
-
const asset: AssetEntity = {
|
|
158
|
-
accountId: account,
|
|
159
|
-
tokenIdHex: hexId,
|
|
160
|
-
type: AssetType.NFT,
|
|
161
|
-
addedTime: time
|
|
162
|
-
}
|
|
63
|
+
const nft = await this.getAssetInfo(tokenIdHex);
|
|
64
|
+
if (nft && nft.type == 'nft') {
|
|
163
65
|
const nftEntity: NftEntity = {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
collection: collection
|
|
66
|
+
token: nft.token,
|
|
67
|
+
tokenIdHex: nft.tokenIdHex,
|
|
68
|
+
parent: nft.parent,
|
|
69
|
+
...nft.data
|
|
169
70
|
}
|
|
170
|
-
|
|
171
|
-
await this.walletDb.saveNft(asset, nftEntity);
|
|
172
|
-
} catch (e) {
|
|
173
|
-
console.error('failed to save NFT', e);
|
|
71
|
+
await this.walletDb.saveNft(accountId, nftEntity, time);
|
|
174
72
|
}
|
|
175
73
|
}
|
|
176
74
|
|
|
177
|
-
public async
|
|
75
|
+
public async syncTokens(accountId: number, tokenBalances: Record<string, Balance>): Promise<void> {
|
|
178
76
|
for (const tokenId in tokenBalances) {
|
|
179
|
-
const
|
|
180
|
-
if (
|
|
181
|
-
await this.
|
|
77
|
+
const balance = tokenBalances[tokenId];
|
|
78
|
+
if (balance && BigInt(balance.confirmed) + BigInt(balance.unconfirmed) > 0n) {
|
|
79
|
+
const token = await this.getAssetInfo(tokenId);
|
|
80
|
+
if (token && token.type == 'token') {
|
|
81
|
+
const tokenEntity: TokenEntity = {
|
|
82
|
+
token: token.token,
|
|
83
|
+
tokenIdHex: token.tokenIdHex,
|
|
84
|
+
parent: token.parent,
|
|
85
|
+
...token.data
|
|
86
|
+
};
|
|
87
|
+
await this.walletDb.saveToken(accountId, tokenEntity);
|
|
88
|
+
}
|
|
182
89
|
}
|
|
183
90
|
}
|
|
184
91
|
}
|
|
185
92
|
|
|
186
93
|
public async syncNfts(accountId: number, tokensBalance: Record<string, Balance>): Promise<void> {
|
|
187
94
|
const currentAssets = Object.keys(tokensBalance);
|
|
188
|
-
const internalAssets = await this.walletDb.
|
|
189
|
-
|
|
190
|
-
const handleNftDelete = async (tokenId: string): Promise<void> => {
|
|
191
|
-
await this.walletDb.deleteNft(accountId, tokenId, true);
|
|
192
|
-
this.walletCache.removeNft(tokenId);
|
|
193
|
-
}
|
|
95
|
+
const internalAssets = await this.walletDb.getAssets(accountId, "nft");
|
|
194
96
|
|
|
195
97
|
const staleAssets = internalAssets?.filter(a => !currentAssets.includes(a.tokenIdHex)) ?? [];
|
|
196
98
|
for (const asset of staleAssets) {
|
|
197
|
-
await
|
|
99
|
+
await this.deleteNft(accountId, asset.tokenIdHex);
|
|
198
100
|
}
|
|
199
101
|
|
|
200
102
|
for (const [token, balance] of Object.entries(tokensBalance)) {
|
|
@@ -204,17 +106,22 @@ export class AssetService {
|
|
|
204
106
|
if ((!hasBalance && !isAssetExist) || (hasBalance && isAssetExist)) {
|
|
205
107
|
continue;
|
|
206
108
|
}
|
|
207
|
-
|
|
208
|
-
const isNft = await this.isNftToken(tokenId);
|
|
209
|
-
if (!isNft) {
|
|
210
|
-
continue;
|
|
211
|
-
}
|
|
212
109
|
|
|
213
110
|
if (!hasBalance && isAssetExist) {
|
|
214
|
-
await
|
|
111
|
+
await this.deleteNft(accountId, tokenId);
|
|
215
112
|
} else {
|
|
216
113
|
await this.handleNftReceive(accountId, tokenId, currentTimestamp());
|
|
217
114
|
}
|
|
218
115
|
}
|
|
219
116
|
}
|
|
117
|
+
|
|
118
|
+
public async deleteToken(accountId: number, tokenId: string): Promise<void> {
|
|
119
|
+
await this.walletDb.deleteToken(accountId, tokenId);
|
|
120
|
+
this.walletCache.removeToken(tokenId);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
public async deleteNft(accountId: number, tokenId: string): Promise<void> {
|
|
124
|
+
await this.walletDb.deleteNft(accountId, tokenId);
|
|
125
|
+
this.walletCache.removeNft(tokenId);
|
|
126
|
+
}
|
|
220
127
|
}
|
package/src/services/cache.ts
CHANGED
|
@@ -18,7 +18,17 @@ export class WalletCache {
|
|
|
18
18
|
this.nfts.clear();
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
public
|
|
21
|
+
public hasToken(id: string): boolean {
|
|
22
|
+
id = tokenIdToHex(id);
|
|
23
|
+
return this.tokens.has(id);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public hasNft(id: string): boolean {
|
|
27
|
+
id = tokenIdToHex(id);
|
|
28
|
+
return this.nfts.has(id);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public async getToken(id: string): Promise<TokenEntity | undefined> {
|
|
22
32
|
id = tokenIdToHex(id);
|
|
23
33
|
if (this.tokens.has(id)) {
|
|
24
34
|
return this.tokens.get(id)!;
|
|
@@ -31,7 +41,7 @@ export class WalletCache {
|
|
|
31
41
|
return token;
|
|
32
42
|
}
|
|
33
43
|
|
|
34
|
-
public async
|
|
44
|
+
public async getNft(id: string): Promise<NftEntity | undefined> {
|
|
35
45
|
id = tokenIdToHex(id);
|
|
36
46
|
if (this.nfts.has(id)) {
|
|
37
47
|
return this.nfts.get(id)!;
|