@subwallet/extension-base 1.3.6-0 → 1.3.7-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.
Files changed (60) hide show
  1. package/background/KoniTypes.d.ts +13 -0
  2. package/cjs/constants/blocked-actions.js +108 -0
  3. package/cjs/constants/index.js +4 -4
  4. package/cjs/core/substrate/xcm-parser.js +4 -3
  5. package/cjs/koni/api/nft/config.js +6 -4
  6. package/cjs/koni/api/nft/index.js +9 -0
  7. package/cjs/koni/api/nft/story_odyssey_nft/index.js +126 -0
  8. package/cjs/koni/background/handlers/Extension.js +22 -1
  9. package/cjs/koni/background/handlers/State.js +12 -0
  10. package/cjs/packageInfo.js +1 -1
  11. package/cjs/services/balance-service/helpers/subscribe/substrate/index.js +2 -1
  12. package/cjs/services/chain-service/constants.js +2 -1
  13. package/cjs/services/earning-service/handlers/native-staking/para-chain.js +20 -17
  14. package/cjs/services/environment-service/stores/Environment.js +19 -0
  15. package/cjs/services/setting-service/SettingService.js +13 -0
  16. package/cjs/services/transaction-service/index.js +12 -6
  17. package/cjs/services/transaction-service/utils.js +3 -0
  18. package/cjs/stores/EnvironmentStore.js +18 -0
  19. package/cjs/stores/index.js +8 -1
  20. package/cjs/utils/environment.js +15 -1
  21. package/cjs/utils/staticData/index.js +7 -2
  22. package/constants/blocked-actions.d.ts +29 -0
  23. package/constants/blocked-actions.js +96 -0
  24. package/constants/index.d.ts +1 -1
  25. package/constants/index.js +1 -1
  26. package/core/substrate/xcm-parser.d.ts +1 -1
  27. package/core/substrate/xcm-parser.js +4 -3
  28. package/koni/api/nft/config.d.ts +1 -1
  29. package/koni/api/nft/config.js +5 -2
  30. package/koni/api/nft/index.js +9 -0
  31. package/koni/api/nft/story_odyssey_nft/index.d.ts +40 -0
  32. package/koni/api/nft/story_odyssey_nft/index.js +119 -0
  33. package/koni/background/handlers/Extension.d.ts +3 -0
  34. package/koni/background/handlers/Extension.js +22 -1
  35. package/koni/background/handlers/State.d.ts +3 -0
  36. package/koni/background/handlers/State.js +12 -0
  37. package/package.json +26 -10
  38. package/packageInfo.js +1 -1
  39. package/services/balance-service/helpers/subscribe/substrate/index.js +2 -1
  40. package/services/chain-service/constants.d.ts +1 -0
  41. package/services/chain-service/constants.js +2 -1
  42. package/services/earning-service/handlers/native-staking/para-chain.js +20 -17
  43. package/services/environment-service/stores/Environment.d.ts +10 -0
  44. package/services/environment-service/stores/Environment.js +12 -0
  45. package/services/setting-service/SettingService.d.ts +5 -0
  46. package/services/setting-service/SettingService.js +13 -0
  47. package/services/transaction-service/index.js +13 -7
  48. package/services/transaction-service/utils.js +3 -0
  49. package/stores/EnvironmentStore.d.ts +5 -0
  50. package/stores/EnvironmentStore.js +10 -0
  51. package/stores/index.d.ts +1 -0
  52. package/stores/index.js +2 -1
  53. package/utils/environment.d.ts +6 -0
  54. package/utils/environment.js +8 -0
  55. package/utils/staticData/blockedActions.json +1 -0
  56. package/utils/staticData/index.d.ts +7 -3
  57. package/utils/staticData/index.js +5 -1
  58. package/cjs/constants/blocked-actions-list.js +0 -14
  59. package/constants/blocked-actions-list.d.ts +0 -7
  60. package/constants/blocked-actions-list.js +0 -7
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.default = void 0;
8
+ var _defaults = require("@subwallet/extension-base/defaults");
9
+ var _SubscribableStore = _interopRequireDefault(require("@subwallet/extension-base/stores/SubscribableStore"));
10
+ // Copyright 2019-2022 @subwallet/extension-base
11
+ // SPDX-License-Identifier: Apache-2.0
12
+
13
+ class EnvironmentStore extends _SubscribableStore.default {
14
+ constructor() {
15
+ super(_defaults.EXTENSION_PREFIX ? `${_defaults.EXTENSION_PREFIX}environment` : null);
16
+ }
17
+ }
18
+ exports.default = EnvironmentStore;
@@ -34,6 +34,12 @@ Object.defineProperty(exports, "CurrentCurrencyStore", {
34
34
  return _CurrentCurrencyStore.default;
35
35
  }
36
36
  });
37
+ Object.defineProperty(exports, "EnvironmentStore", {
38
+ enumerable: true,
39
+ get: function () {
40
+ return _EnvironmentStore.default;
41
+ }
42
+ });
37
43
  Object.defineProperty(exports, "MetadataStore", {
38
44
  enumerable: true,
39
45
  get: function () {
@@ -52,4 +58,5 @@ var _Accounts = _interopRequireDefault(require("./Accounts"));
52
58
  var _CurrentAccountStore = _interopRequireDefault(require("./CurrentAccountStore"));
53
59
  var _CurrentCurrencyStore = _interopRequireDefault(require("./CurrentCurrencyStore"));
54
60
  var _Metadata = _interopRequireDefault(require("./Metadata"));
55
- var _ModifyPairStore = _interopRequireDefault(require("./ModifyPairStore"));
61
+ var _ModifyPairStore = _interopRequireDefault(require("./ModifyPairStore"));
62
+ var _EnvironmentStore = _interopRequireDefault(require("./EnvironmentStore"));
@@ -4,7 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.targetIsWeb = exports.targetIsMobile = exports.targetIsExtension = exports.osName = exports.isMobile = exports.isFirefox = exports.TARGET_ENV = exports.RuntimeInfo = exports.MODULE_SUPPORT = exports.BowserParser = void 0;
7
+ exports.targetIsWeb = exports.targetIsMobile = exports.targetIsExtension = exports.platformType = exports.platformModel = exports.osVersion = exports.osName = exports.isMobile = exports.isFirefox = exports.isBrave = exports.browserVersion = exports.browserName = exports.TARGET_ENV = exports.RuntimeInfo = exports.MODULE_SUPPORT = exports.BowserParser = void 0;
8
8
  var _mv = require("@subwallet/extension-base/utils/mv3");
9
9
  var _bowser = _interopRequireDefault(require("bowser"));
10
10
  var _KoniTypes = require("../background/KoniTypes");
@@ -72,13 +72,27 @@ const RuntimeInfo = detectRuntimeEnvironment();
72
72
  // Todo: Support more in backend case
73
73
  exports.RuntimeInfo = RuntimeInfo;
74
74
  const BowserParser = _bowser.default.getParser(typeof navigator !== 'undefined' ? ((_navigator3 = navigator) === null || _navigator3 === void 0 ? void 0 : _navigator3.userAgent) + '' : '');
75
+ // @ts-ignore
76
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
75
77
  exports.BowserParser = BowserParser;
78
+ const isBrave = navigator.brave !== undefined && navigator.brave.isBrave.name === 'isBrave';
79
+ exports.isBrave = isBrave;
76
80
  const isFirefox = BowserParser.getBrowserName(true) === 'firefox';
77
81
  exports.isFirefox = isFirefox;
82
+ const browserName = isBrave ? 'brave' : BowserParser.getBrowserName(true);
83
+ exports.browserName = browserName;
84
+ const browserVersion = BowserParser.getBrowserVersion();
85
+ exports.browserVersion = browserVersion;
78
86
  const osName = BowserParser.getOSName();
79
87
  exports.osName = osName;
88
+ const osVersion = BowserParser.getOSVersion();
89
+ exports.osVersion = osVersion;
80
90
  const isMobile = BowserParser.getPlatform().type === 'mobile';
81
91
  exports.isMobile = isMobile;
92
+ const platformType = BowserParser.getPlatform().type;
93
+ exports.platformType = platformType;
94
+ const platformModel = BowserParser.getPlatform().model;
95
+ exports.platformModel = platformModel;
82
96
  const TARGET_ENV = process.env.TARGET_ENV || 'extension';
83
97
  exports.TARGET_ENV = TARGET_ENV;
84
98
  const targetIsExtension = TARGET_ENV === 'extension';
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.termAndCondition = exports.staticData = exports.remindNotificationTime = exports.marketingCampaigns = exports.currencySymbol = exports.crowdloanFunds = exports.buyTokenConfigs = exports.buyServiceInfos = exports.blockedActionsFeatures = exports.StaticKey = void 0;
6
+ exports.termAndCondition = exports.staticData = exports.remindNotificationTime = exports.marketingCampaigns = exports.currencySymbol = exports.crowdloanFunds = exports.buyTokenConfigs = exports.buyServiceInfos = exports.blockedActionsFeatures = exports.blockedActions = exports.StaticKey = void 0;
7
7
  var _chainList = require("@subwallet/chain-list");
8
8
  // Copyright 2019-2022 @subwallet/extension-base authors & contributors
9
9
  // SPDX-License-Identifier: Apache-2.0
@@ -33,7 +33,10 @@ const blockedActionsFeatures = require('./blockedActionsFeatures.json');
33
33
  // eslint-disable-next-line @typescript-eslint/no-var-requires,@typescript-eslint/no-unsafe-assignment
34
34
  exports.blockedActionsFeatures = blockedActionsFeatures;
35
35
  const remindNotificationTime = require('./remindNotificationTime.json');
36
+ // eslint-disable-next-line @typescript-eslint/no-var-requires,@typescript-eslint/no-unsafe-assignment
36
37
  exports.remindNotificationTime = remindNotificationTime;
38
+ const blockedActions = require('./blockedActions.json');
39
+ exports.blockedActions = blockedActions;
37
40
  let StaticKey;
38
41
  exports.StaticKey = StaticKey;
39
42
  (function (StaticKey) {
@@ -46,6 +49,7 @@ exports.StaticKey = StaticKey;
46
49
  StaticKey["BUY_TOKEN_CONFIGS"] = "buy-token-configs";
47
50
  StaticKey["BLOCKED_ACTIONS_FEATURES"] = "blocked-actions-features";
48
51
  StaticKey["REMIND_NOTIFICATION_TIME"] = "remind-notification-time";
52
+ StaticKey["BLOCKED_ACTIONS"] = "blocked-actions";
49
53
  })(StaticKey || (exports.StaticKey = StaticKey = {}));
50
54
  const staticData = {
51
55
  [StaticKey.CHAINS]: Object.values(_chainList.ChainInfoMap),
@@ -56,6 +60,7 @@ const staticData = {
56
60
  [StaticKey.TERM_AND_CONDITION]: termAndCondition.default,
57
61
  [StaticKey.BUY_TOKEN_CONFIGS]: buyTokenConfigs,
58
62
  [StaticKey.BLOCKED_ACTIONS_FEATURES]: blockedActionsFeatures,
59
- [StaticKey.REMIND_NOTIFICATION_TIME]: remindNotificationTime
63
+ [StaticKey.REMIND_NOTIFICATION_TIME]: remindNotificationTime,
64
+ [StaticKey.BLOCKED_ACTIONS]: blockedActions
60
65
  };
61
66
  exports.staticData = staticData;
@@ -0,0 +1,29 @@
1
+ import { ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
2
+ export interface BlockedActionsFeaturesMap {
3
+ blockedActionsMap: Record<ExtrinsicType, string[]>;
4
+ blockedFeaturesList: string[];
5
+ }
6
+ export declare const APP_ENV: string;
7
+ export declare const APP_VER: string;
8
+ export interface EnvConfig {
9
+ appConfig?: AppConfig;
10
+ browserConfig?: BrowserConfig;
11
+ osConfig?: OSConfig;
12
+ }
13
+ export interface AppConfig {
14
+ environment: string;
15
+ version?: string;
16
+ }
17
+ export interface BrowserConfig {
18
+ type: string;
19
+ version?: string;
20
+ }
21
+ export interface OSConfig {
22
+ type: string;
23
+ version?: string;
24
+ }
25
+ declare type BlockedConfigObjects = Record<string, EnvConfig>;
26
+ export declare function fetchBlockedConfigObjects(): Promise<BlockedConfigObjects>;
27
+ export declare function getPassConfigId(currentConfig: EnvConfig, blockedConfigObjects: BlockedConfigObjects): string[];
28
+ export declare function fetchLastestBlockedActionsAndFeatures(ids: string[]): Promise<BlockedActionsFeaturesMap[]>;
29
+ export {};
@@ -0,0 +1,96 @@
1
+ // Copyright 2019-2022 @subwallet/extension-base authors & contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { packageInfo } from '@subwallet/extension-base';
5
+ import { fetchStaticData } from '@subwallet/extension-base/utils';
6
+ import { staticData, StaticKey } from '@subwallet/extension-base/utils/staticData';
7
+ export const APP_ENV = process.env.TARGET_ENV;
8
+ export const APP_VER = packageInfo.version;
9
+ const PRODUCTION_BRANCHES = ['master', 'webapp', 'webapp-dev'];
10
+ const branchName = process.env.BRANCH_NAME || 'koni-dev';
11
+ const targetFolder = PRODUCTION_BRANCHES.indexOf(branchName) > -1 ? 'list' : 'preview';
12
+ export async function fetchBlockedConfigObjects() {
13
+ const targetFile = `${targetFolder}/envConfig.json`;
14
+ return await fetchStaticData('blocked-actions', targetFile);
15
+ }
16
+ export function getPassConfigId(currentConfig, blockedConfigObjects) {
17
+ const passList = [];
18
+ Object.entries(blockedConfigObjects).forEach(([key, appliedConfig]) => {
19
+ let passAppConfig = false;
20
+ let passBrowserConfig = false;
21
+ let passOSConfig = false;
22
+ if (!appliedConfig.appConfig || !currentConfig.appConfig) {
23
+ passAppConfig = true;
24
+ } else {
25
+ const isPassEnv = currentConfig.appConfig.environment === appliedConfig.appConfig.environment;
26
+ const isPassVer = isPassVersion(currentConfig.appConfig.version, appliedConfig.appConfig.version);
27
+ passAppConfig = isPassEnv && isPassVer;
28
+ }
29
+ if (!appliedConfig.browserConfig || !currentConfig.browserConfig) {
30
+ passBrowserConfig = true;
31
+ } else {
32
+ const isPassType = currentConfig.browserConfig.type === appliedConfig.browserConfig.type;
33
+ const isPassVer = isPassVersion(currentConfig.browserConfig.version, appliedConfig.browserConfig.version);
34
+ passBrowserConfig = isPassType && isPassVer;
35
+ }
36
+ if (!appliedConfig.osConfig || !currentConfig.osConfig) {
37
+ passOSConfig = true;
38
+ } else {
39
+ const isPassType = currentConfig.osConfig.type === appliedConfig.osConfig.type;
40
+ const isPassVer = isPassVersion(currentConfig.osConfig.version, appliedConfig.osConfig.version);
41
+ passOSConfig = isPassType && isPassVer;
42
+ }
43
+ if (passAppConfig && passBrowserConfig && passOSConfig) {
44
+ passList.push(key);
45
+ }
46
+ });
47
+ return passList;
48
+ }
49
+ function isPassVersion(versionStr, versionCondition) {
50
+ // todo: check if has case versionStr = undefined?
51
+ const versionArr = versionStr.split('.');
52
+ if (!versionCondition) {
53
+ return true;
54
+ }
55
+ if (versionCondition.includes('>=')) {
56
+ const versionConditionStr = versionCondition.replace('>=', '').trim();
57
+ const versionConditionArr = versionConditionStr.split('.'); // todo: map(Number) instead of parseInt later
58
+
59
+ if (versionConditionStr === versionStr) {
60
+ return true;
61
+ }
62
+ for (let i = 0; i < versionArr.length; i++) {
63
+ if (parseInt(versionArr[i]) < parseInt(versionConditionArr[i])) {
64
+ return false;
65
+ }
66
+ if (parseInt(versionArr[i]) > parseInt(versionConditionArr[i])) {
67
+ return true;
68
+ }
69
+ }
70
+ return true;
71
+ }
72
+ if (versionCondition.includes('>')) {
73
+ const versionConditionArr = versionCondition.replace('>', '').trim().split('.');
74
+ for (let i = 0; i < versionArr.length; i++) {
75
+ if (parseInt(versionArr[i]) < parseInt(versionConditionArr[i])) {
76
+ return false;
77
+ }
78
+ if (parseInt(versionArr[i]) > parseInt(versionConditionArr[i])) {
79
+ return true;
80
+ }
81
+ }
82
+ return false;
83
+ }
84
+
85
+ // todo: also handle less use cases: <, <=
86
+
87
+ const versionConditionStr = versionCondition.trim();
88
+ return versionStr === versionConditionStr;
89
+ }
90
+ export async function fetchLastestBlockedActionsAndFeatures(ids) {
91
+ if (ids.length === 0) {
92
+ return [staticData[StaticKey.BLOCKED_ACTIONS_FEATURES]];
93
+ }
94
+ const targetFiles = ids.map(id => `${targetFolder}/${id}.json`);
95
+ return await Promise.all(targetFiles.map(targetFile => fetchStaticData('blocked-actions', targetFile)));
96
+ }
@@ -35,7 +35,7 @@ export declare const NETWORK_MULTI_GAS_FEE: string[];
35
35
  export declare const ORDINAL_COLLECTION = "__Ordinal__";
36
36
  export declare const ORDINAL_METHODS: string[];
37
37
  export declare const PERMISSIONS_TO_REVOKE: string[];
38
- export * from './blocked-actions-list';
38
+ export * from './blocked-actions';
39
39
  export * from './environment';
40
40
  export * from './signing';
41
41
  export * from './staking';
@@ -37,7 +37,7 @@ export const NETWORK_MULTI_GAS_FEE = ['*'];
37
37
  export const ORDINAL_COLLECTION = '__Ordinal__';
38
38
  export const ORDINAL_METHODS = ['drc-20', 'pol-20'];
39
39
  export const PERMISSIONS_TO_REVOKE = ['eth_accounts'];
40
- export * from "./blocked-actions-list.js";
40
+ export * from "./blocked-actions.js";
41
41
  export * from "./environment.js";
42
42
  export * from "./signing.js";
43
43
  export * from "./staking.js";
@@ -53,4 +53,4 @@ export declare function _isXcmWithinSameConsensus(originChainInfo: _ChainInfo, d
53
53
  export declare function _isSnowBridgeXcm(originChainInfo: _ChainInfo, destChainInfo: _ChainInfo): boolean;
54
54
  export declare function _isAvailBridgeXcm(originChainInfo: _ChainInfo, destChainInfo: _ChainInfo): boolean;
55
55
  export declare function _isMythosFromHydrationToMythos(originChainInfo: _ChainInfo, destChainInfo: _ChainInfo, assetSlug: string): boolean;
56
- export declare function _adaptX1Interior(assetIdentifier: Record<string, any>, version: number): Record<string, any>;
56
+ export declare function _adaptX1Interior(_assetIdentifier: Record<string, any>, version: number): Record<string, any>;
@@ -215,17 +215,18 @@ function _getAssetIdentifier(tokenInfo, version) {
215
215
  throw new Error('Asset must have multilocation');
216
216
  }
217
217
  const assetIdentifier = ['statemint-LOCAL-KSM', 'statemine-LOCAL-DOT'].includes(tokenInfo.slug) // todo: hotfix for ksm statemint recheck all chain
218
- ? _assetIdentifier : _adaptX1Interior(structuredClone(_assetIdentifier), version);
218
+ ? _assetIdentifier : _adaptX1Interior(_assetIdentifier, version);
219
219
  return version >= 4 // from V4, Concrete is removed
220
220
  ? assetIdentifier : {
221
221
  Concrete: assetIdentifier
222
222
  };
223
223
  }
224
- export function _adaptX1Interior(assetIdentifier, version) {
224
+ export function _adaptX1Interior(_assetIdentifier, version) {
225
+ const assetIdentifier = structuredClone(_assetIdentifier);
225
226
  const interior = assetIdentifier.interior;
226
227
  const isInteriorObj = typeof interior === 'object' && interior !== null;
227
228
  const isX1 = isInteriorObj && 'X1' in interior;
228
- const needModifyX1 = version <= 4 && Array.isArray(interior.X1);
229
+ const needModifyX1 = version < 4 && Array.isArray(interior.X1);
229
230
  if (isInteriorObj && isX1 && needModifyX1) {
230
231
  // X1 is an object for version < 4. From V4, it's an array
231
232
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access
@@ -11,7 +11,7 @@ export declare const BIT_AVATAR_API = "https://api.bitavatar.io/v1";
11
11
  export declare const BIT_COUNTRY_LAND_ESTATE_METADATA_API = "https://pioneer-api.bit.country/metadata/landTokenUriPioneer";
12
12
  export declare const BIT_COUNTRY_THUMBNAIL_RESOLVER = "https://res.cloudinary.com/ddftctzph/image/upload/c_scale,q_100,w_250/production-ipfs/asset/";
13
13
  export declare const CF_IPFS_GATEWAY = "https://cf-ipfs.com/ipfs/";
14
- export declare const PINATA_IPFS_GATEWAY = "https://gateway.pinata.cloud/ipfs/";
14
+ export declare const ODYSSEY_ENDPOINT = "https://indexer-v2.dev.aurascan.io/api/v2/graphql";
15
15
  export declare const VARA_SCAN_ENDPOINT = "https://nft-explorer.vara-network.io/graphql";
16
16
  export declare const AVAIL_LIGHT_CLIENT_NFT = "https://indexer.availspace.app/graphql";
17
17
  export declare const UNIQUE_SCAN_ENDPOINT = "https://api-unique.uniquescan.io/v1/graphql";
@@ -20,7 +20,7 @@ export const BIT_COUNTRY_THUMBNAIL_RESOLVER = 'https://res.cloudinary.com/ddftct
20
20
  export const CF_IPFS_GATEWAY = 'https://cf-ipfs.com/ipfs/';
21
21
 
22
22
  // XOrigin
23
- export const PINATA_IPFS_GATEWAY = 'https://gateway.pinata.cloud/ipfs/';
23
+ export const ODYSSEY_ENDPOINT = 'https://indexer-v2.dev.aurascan.io/api/v2/graphql';
24
24
 
25
25
  // deprecated
26
26
  // export const UNIQUE_SCAN_ENDPOINT = 'https://explorer-api.unique.network/v1/graphql';
@@ -54,6 +54,9 @@ export const TERNOA_MAINNET_CLIENT_NFT = 'https://indexer-mainnet.ternoa.dev';
54
54
  export const TERNOA_ALPHANET_CLIENT_NFT = 'https://indexer-alphanet.ternoa.dev';
55
55
  export const TERNOA_MAINNET_GATEWAY = 'https://ipfs-mainnet.trnnfr.com/ipfs/';
56
56
  export const TERNOA_ALPHANET_GATEWAY = 'https://ipfs-dev.trnnfr.com/ipfs/';
57
+
58
+ // XOrigin
59
+
57
60
  export const IPFS_GATEWAY_4EVERLAND = 'https://4everland.io/ipfs/';
58
61
  export const IPFS_FLEEK = 'https://ipfs.fleek.co/ipfs/';
59
62
  export const W3S_IPFS = 'https://w3s.link/ipfs/'; // 400
@@ -82,7 +85,7 @@ export let SUPPORTED_TRANSFER_EVM_CHAIN_NAME;
82
85
  SUPPORTED_TRANSFER_EVM_CHAIN_NAME["shibuya"] = "shibuya";
83
86
  })(SUPPORTED_TRANSFER_EVM_CHAIN_NAME || (SUPPORTED_TRANSFER_EVM_CHAIN_NAME = {}));
84
87
  export const SUPPORTED_TRANSFER_EVM_CHAIN = [SUPPORTED_TRANSFER_EVM_CHAIN_NAME.moonbase, SUPPORTED_TRANSFER_EVM_CHAIN_NAME.moonbeam, SUPPORTED_TRANSFER_EVM_CHAIN_NAME.moonriver, SUPPORTED_TRANSFER_EVM_CHAIN_NAME.astarEvm, SUPPORTED_TRANSFER_EVM_CHAIN_NAME.shiden, SUPPORTED_TRANSFER_EVM_CHAIN_NAME.shibuya];
85
- export const UNSUPPORTED_TRANSFER_EVM_CHAIN_NAME = ['unique_evm', 'rari'];
88
+ export const UNSUPPORTED_TRANSFER_EVM_CHAIN_NAME = ['unique_evm', 'rari', 'storyOdyssey_testnet'];
86
89
  export const TRANSFER_CHAIN_ID = {
87
90
  [SUPPORTED_TRANSFER_EVM_CHAIN_NAME.moonbase]: 1287,
88
91
  [SUPPORTED_TRANSFER_EVM_CHAIN_NAME.moonbeam]: 1284,
@@ -18,6 +18,7 @@ import { _isChainSupportEvmNft, _isChainSupportNativeNft, _isChainSupportWasmNft
18
18
  import { categoryAddresses, targetIsWeb } from '@subwallet/extension-base/utils';
19
19
  import AssetHubNftsPalletApi from "./assethub_nft/index.js";
20
20
  import { RariNftApi } from "./rari/index.js";
21
+ import { OdysseyNftApi } from "./story_odyssey_nft/index.js";
21
22
  import { TernoaNftApi } from "./ternoa_nft/index.js";
22
23
  function createSubstrateNftApi(chain, substrateApi, addresses) {
23
24
  const {
@@ -48,6 +49,8 @@ function createSubstrateNftApi(chain, substrateApi, addresses) {
48
49
  return [new TernoaNftApi(substrateApi, substrateAddresses, chain)];
49
50
  } else if (_NFT_CHAIN_GROUP.rari.includes(chain)) {
50
51
  return [new RariNftApi(chain, evmAddresses)];
52
+ } else if (_NFT_CHAIN_GROUP.story_odyssey.includes(chain)) {
53
+ return [new OdysseyNftApi(chain, evmAddresses)];
51
54
  }
52
55
  return null;
53
56
  }
@@ -157,6 +160,12 @@ export class NftHandler {
157
160
  this.handlers.push(...handlers);
158
161
  }
159
162
  }
163
+ if (chain === 'storyOdyssey_testnet') {
164
+ const handlers = createSubstrateNftApi(chain, null, evmAddresses);
165
+ if (handlers && !!handlers.length) {
166
+ this.handlers.push(...handlers);
167
+ }
168
+ }
160
169
  if (_isChainSupportWasmNft(chainInfo)) {
161
170
  if (this.substrateApiMap[chain]) {
162
171
  const handler = createWasmNftApi(chain, this.substrateApiMap[chain], substrateAddresses);
@@ -0,0 +1,40 @@
1
+ import { BaseNftApi, HandleNftParams } from '../nft';
2
+ interface OdysseyTokenMetadata {
3
+ name: string;
4
+ image: string;
5
+ description: string;
6
+ }
7
+ interface OdysseyNftInfo {
8
+ onchain: {
9
+ metadata: OdysseyTokenMetadata;
10
+ token_uri: string;
11
+ };
12
+ offchain: {
13
+ image: {
14
+ url: string;
15
+ content_type: string;
16
+ };
17
+ animation?: object;
18
+ };
19
+ }
20
+ interface OdysseyToken {
21
+ owner: string;
22
+ token_id: string;
23
+ media_info: OdysseyNftInfo;
24
+ erc721_contract_address: string;
25
+ }
26
+ export declare class OdysseyNftApi extends BaseNftApi {
27
+ constructor(chain: string, addresses: string[]);
28
+ endpoint: string;
29
+ private static parseNftRequest;
30
+ private fetchNftData;
31
+ private fetchUrlMetadata;
32
+ private parseUrlIfIpfs;
33
+ private parseNftItem;
34
+ private parseNftCollection;
35
+ private processNftItem;
36
+ handleNfts(params: HandleNftParams): Promise<void>;
37
+ fetchNftsWithDetail(address: string): Promise<OdysseyToken[] | null>;
38
+ fetchNfts(params: HandleNftParams): Promise<0 | 1>;
39
+ }
40
+ export {};
@@ -0,0 +1,119 @@
1
+ // Copyright 2019-2022 @subwallet/extension-koni authors & contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { ODYSSEY_ENDPOINT } from "../config.js";
5
+ import { BaseNftApi } from "../nft.js";
6
+ export class OdysseyNftApi extends BaseNftApi {
7
+ constructor(chain, addresses) {
8
+ super(chain, undefined, addresses);
9
+ }
10
+ endpoint = ODYSSEY_ENDPOINT;
11
+ static parseNftRequest(address) {
12
+ const lowerCaseAddress = address.toLowerCase();
13
+ return `
14
+ query MyQuery {
15
+ odyssey {
16
+ erc721_token(
17
+ where: {owner: {_eq: "${lowerCaseAddress}"}}
18
+ ) {
19
+ media_info
20
+ owner
21
+ token_id
22
+ erc721_contract_address
23
+ }
24
+ }
25
+ }
26
+ `;
27
+ }
28
+ async fetchNftData(query) {
29
+ try {
30
+ const response = await fetch(this.endpoint, {
31
+ method: 'POST',
32
+ headers: {
33
+ 'Content-Type': 'application/json'
34
+ },
35
+ body: JSON.stringify({
36
+ operationName: 'MyQuery',
37
+ variables: {},
38
+ query
39
+ })
40
+ });
41
+ const result = await response.json();
42
+ return result.data.odyssey.erc721_token;
43
+ } catch (err) {
44
+ console.error('Error:', err);
45
+ return null;
46
+ }
47
+ }
48
+ async fetchUrlMetadata(url) {
49
+ try {
50
+ const response = await fetch(url);
51
+ return await response.json();
52
+ } catch (err) {
53
+ console.error('Error:', err);
54
+ return null;
55
+ }
56
+ }
57
+ parseUrlIfIpfs(url) {
58
+ if (url.startsWith('ipfs://')) {
59
+ return this.parseUrl(url);
60
+ }
61
+ if (url.includes('github.com')) {
62
+ return `${url}?raw=true`;
63
+ }
64
+ return url;
65
+ }
66
+ parseNftItem(nft, metadata, address) {
67
+ var _metadata$media, _metadata$media$;
68
+ const urlMetadataImage = this.parseUrlIfIpfs((metadata === null || metadata === void 0 ? void 0 : metadata.image) || '');
69
+ return {
70
+ id: nft.token_id,
71
+ name: (metadata === null || metadata === void 0 ? void 0 : metadata.name) || (metadata === null || metadata === void 0 ? void 0 : metadata.title),
72
+ description: metadata === null || metadata === void 0 ? void 0 : metadata.description,
73
+ image: urlMetadataImage || (metadata === null || metadata === void 0 ? void 0 : (_metadata$media = metadata.media) === null || _metadata$media === void 0 ? void 0 : (_metadata$media$ = _metadata$media[0]) === null || _metadata$media$ === void 0 ? void 0 : _metadata$media$.url),
74
+ collectionId: nft.erc721_contract_address,
75
+ chain: this.chain,
76
+ owner: address
77
+ };
78
+ }
79
+ parseNftCollection(nft) {
80
+ const image = this.parseUrlIfIpfs(nft.media_info.onchain.metadata.image || '');
81
+ return {
82
+ collectionId: nft.erc721_contract_address,
83
+ chain: this.chain,
84
+ collectionName: nft.media_info.onchain.metadata.name,
85
+ image: image || undefined
86
+ };
87
+ }
88
+ async processNftItem(nft, address, params) {
89
+ const tokenUri = this.parseUrlIfIpfs(nft.media_info.onchain.token_uri) || '';
90
+ const urlMetadata = await this.fetchUrlMetadata(tokenUri);
91
+ const parsedNft = this.parseNftItem(nft, urlMetadata, address);
92
+ params.updateItem(this.chain, parsedNft, address);
93
+ const parsedCollection = this.parseNftCollection(nft);
94
+ params.updateCollection(this.chain, parsedCollection);
95
+ }
96
+ async handleNfts(params) {
97
+ await Promise.all(this.addresses.map(async address => {
98
+ const nftDetails = await this.fetchNftsWithDetail(address);
99
+ if (!nftDetails || nftDetails.length === 0) {
100
+ return;
101
+ }
102
+ await Promise.all(nftDetails.map(async nft => {
103
+ await this.processNftItem(nft, address, params);
104
+ }));
105
+ }));
106
+ }
107
+ async fetchNftsWithDetail(address) {
108
+ const query = OdysseyNftApi.parseNftRequest(address);
109
+ return await this.fetchNftData(query);
110
+ }
111
+ async fetchNfts(params) {
112
+ try {
113
+ await this.handleNfts(params);
114
+ } catch (e) {
115
+ return 0;
116
+ }
117
+ return 1;
118
+ }
119
+ }
@@ -196,6 +196,9 @@ export default class KoniExtension {
196
196
  private subscribeAssetLogoMap;
197
197
  private subscribeChainLogoMap;
198
198
  private passPhishingPage;
199
+ private saveAppConfig;
200
+ private saveBrowserConfig;
201
+ private saveOSConfig;
199
202
  private connectWalletConnect;
200
203
  private connectWCSubscribe;
201
204
  private approveWalletConnectSession;
@@ -2519,13 +2519,26 @@ export default class KoniExtension {
2519
2519
  }
2520
2520
 
2521
2521
  // Phishing detect
2522
-
2523
2522
  async passPhishingPage({
2524
2523
  url
2525
2524
  }) {
2526
2525
  return await this.#koniState.approvePassPhishingPage(url);
2527
2526
  }
2528
2527
 
2528
+ // Set environment config
2529
+ saveAppConfig(request) {
2530
+ this.#koniState.saveEnvConfig('appConfig', request.appConfig);
2531
+ return true;
2532
+ }
2533
+ saveBrowserConfig(request) {
2534
+ this.#koniState.saveEnvConfig('browserConfig', request.browserConfig);
2535
+ return true;
2536
+ }
2537
+ saveOSConfig(request) {
2538
+ this.#koniState.saveEnvConfig('osConfig', request.osConfig);
2539
+ return true;
2540
+ }
2541
+
2529
2542
  /// Wallet connect
2530
2543
 
2531
2544
  // Connect
@@ -3798,6 +3811,14 @@ export default class KoniExtension {
3798
3811
  case 'pri(phishing.pass)':
3799
3812
  return await this.passPhishingPage(request);
3800
3813
 
3814
+ // Set Environment config
3815
+ case 'pri(settings.saveAppConfig)':
3816
+ return this.saveAppConfig(request);
3817
+ case 'pri(settings.saveBrowserConfig)':
3818
+ return this.saveBrowserConfig(request);
3819
+ case 'pri(settings.saveOSConfig)':
3820
+ return this.saveOSConfig(request);
3821
+
3801
3822
  /// Keyring state
3802
3823
  case 'pri(keyring.subscribe)':
3803
3824
  return this.keyringStateSubscribe(id, port);
@@ -2,6 +2,7 @@
2
2
  import { _AssetRef, _AssetType, _ChainAsset, _ChainInfo, _MultiChainAsset } from '@subwallet/chain-list/types';
3
3
  import { AddTokenRequestExternal, AmountData, ApiMap, AuthRequestV2, ChainStakingMetadata, ConfirmationsQueue, ConfirmationsQueueTon, CrowdloanItem, CrowdloanJson, EvmSendTransactionParams, ExternalRequestPromise, MantaPayConfig, MantaPaySyncState, NftCollection, NftItem, NftJson, NominatorMetadata, RequestAccountExportPrivateKey, RequestConfirmationComplete, RequestConfirmationCompleteTon, RequestCrowdloanContributions, RequestSettingsType, ResponseAccountExportPrivateKey, ServiceInfo, SingleModeJson, StakingItem, StakingJson, StakingRewardItem, StakingRewardJson, StakingType, UiSettings } from '@subwallet/extension-base/background/KoniTypes';
4
4
  import { RequestAuthorizeTab, RequestRpcSend, RequestRpcSubscribe, RequestRpcUnsubscribe, RequestSign, ResponseRpcListProviders, ResponseSigning } from '@subwallet/extension-base/background/types';
5
+ import { EnvConfig } from '@subwallet/extension-base/constants';
5
6
  import { BalanceService } from '@subwallet/extension-base/services/balance-service';
6
7
  import BuyService from '@subwallet/extension-base/services/buy-service';
7
8
  import CampaignService from '@subwallet/extension-base/services/campaign-service';
@@ -239,6 +240,8 @@ export default class KoniState {
239
240
  reloadBalance(): Promise<boolean>;
240
241
  reloadCrowdloan(): Promise<boolean>;
241
242
  approvePassPhishingPage(_url: string): Promise<boolean>;
243
+ saveEnvConfig<T extends keyof EnvConfig>(key: T, value: EnvConfig[T]): void;
244
+ initEnvConfig(envConfig: EnvConfig): void;
242
245
  resetWallet(resetAll: boolean): Promise<void>;
243
246
  enableMantaPay(updateStore: boolean, address: string, password: string, seedPhrase?: string): Promise<string | undefined>;
244
247
  disableMantaPay(address: string): Promise<boolean>;
@@ -1302,6 +1302,18 @@ export default class KoniState {
1302
1302
  });
1303
1303
  });
1304
1304
  }
1305
+ saveEnvConfig(key, value) {
1306
+ this.settingService.getEnvironmentList(config => {
1307
+ const newSettings = {
1308
+ ...config,
1309
+ [key]: value
1310
+ };
1311
+ this.settingService.setEnvironment(newSettings);
1312
+ });
1313
+ }
1314
+ initEnvConfig(envConfig) {
1315
+ this.settingService.setEnvironment(envConfig);
1316
+ }
1305
1317
  async resetWallet(resetAll) {
1306
1318
  await this.keyringService.resetWallet(resetAll);
1307
1319
  await this.earningService.resetYieldPosition();