@hashgraph/hedera-wallet-connect 0.1.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/.editorconfig ADDED
@@ -0,0 +1,19 @@
1
+ root = true
2
+
3
+ [*]
4
+ charset = utf-8
5
+ end_of_line = lf
6
+ indent_size = 4
7
+ indent_style = space
8
+ insert_final_newline = true
9
+ max_line_length = 120
10
+ tab_width = 4
11
+
12
+ [{*.ts, *js}]
13
+ indent_size = 2
14
+
15
+ [{*.json,jest.config}]
16
+ indent_size = 2
17
+
18
+ [{*.yaml,*.yml}]
19
+ indent_size = 2
@@ -0,0 +1,18 @@
1
+ name: Publish to NPM
2
+ on:
3
+ release:
4
+ types: [published]
5
+ jobs:
6
+ build:
7
+ runs-on: ubuntu-latest
8
+ steps:
9
+ - uses: actions/checkout@v3
10
+ # Setup .npmrc file to publish to npm
11
+ - uses: actions/setup-node@v3
12
+ with:
13
+ node-version: '18.x'
14
+ registry-url: 'https://registry.npmjs.org'
15
+ - run: npm ci
16
+ - run: npm publish --access=public
17
+ env:
18
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 Hashgraph
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,119 @@
1
+ # **Hedera Wallet Connect**
2
+
3
+ This package is a messaging relay between decentralized applications and wallets in Hedera network based on Wallet Connect relays.
4
+
5
+ ## Getting started
6
+ ### Installation
7
+ 1. Install npm package `hedera-wallet-connect`;
8
+ ```bash
9
+ npm install hedera-wallet-connect
10
+ ```
11
+
12
+ ### DApp section
13
+ 1. Import `DAppConnector` from `hedera-wallet-connect` package:
14
+ ```typescript
15
+ import {DAppConnector} from "hedera-wallet-connect";
16
+ ```
17
+ 2. Create an instance of DAppConnector: `this.dAppConnector = new DAppConnector();`.
18
+ You can optionally pass application metadata to the constructor.
19
+ Metadata is a general WalletConnect metadata with provided structure:
20
+ ```typescript
21
+ type Metadata = {
22
+ name: string; // Name of your DApp
23
+ description: string; // Description for your DApp
24
+ url: string; // URL adress of your DApp
25
+ icons: string[]; // Icons for displaying in connector
26
+ }
27
+ ```
28
+ If not specified metadata will be automatically composed using website meta content.
29
+ 3. Execute `init` method on instance of DAppConnector. You can pass array of custom event names you would like to receive from Wallet (They will be sent by wallet only if supported).
30
+ ```typescript
31
+ await this.dAppConnector.init(["someEventName"])
32
+ ```
33
+ 4. In order to request connection to the Wallet run `connect` method. You can pass LedgerId to this method in order to select other than MAINNET Ledger.
34
+ ```typescript
35
+ await this.dAppConnector.connect(LedgerId.TESTNET)
36
+ ```
37
+ If app is reloading calling `connect` method will try to resume existing session instead of opening new pairing window.
38
+ 5. When connection is established you should request signers array by calling `getSigners` method.
39
+ ```typescript
40
+ await this.dAppConnector.getSigners()
41
+ ```
42
+ This will return array of Signer (HIP-338) interfaces for all allowed by Wallet accounts.
43
+ Use them to execute methods on behalf of wallet account.
44
+ You can also subscribe to the events sent by the connected Wallet. Use `events$` subscription provided by DAppConnector.
45
+ ```typescript
46
+ this.dAppConnector.$events.subscribe(
47
+ ({name, data}: {name: string, data: any}) => {
48
+ console.log(`Event ${name}: ${JSON.stringify(data)}`);
49
+ })
50
+ ```
51
+
52
+ ### Wallet section
53
+ 1. Import `WalletConnector` from `hedera-wallet-connect` package:
54
+ ```typescript
55
+ import {WalletConnector} from "hedera-wallet-connect";
56
+ ```
57
+ 2. Create an instance of WalletConnector:
58
+ ```typescript
59
+ this.walletConnector = new WalletConnector();
60
+ ```
61
+ You can optionally pass application metadata to the constructor.
62
+ Metadata is a general WalletConnect metadata with provided structure:
63
+ ```typescript
64
+ type Metadata = {
65
+ name: string; // Name of your DApp
66
+ description: string; // Description for your DApp
67
+ url: string; // URL adress of your DApp
68
+ icons: string[]; // Icons for displaying in connector
69
+ }
70
+ ```
71
+ If not specified metadata will be automatically composed using website meta content.
72
+ It's advisable to specify metadata in case of extension or hybrid app wallet.
73
+ 3. Execute `init` method on instance of DAppConnector. You should pass callback method of your wallet as an argument.
74
+ This callback will be executed as soon as proposal for connection will arrive from the DApp. As an argument for this callback you will get WalletConnect session proposal.
75
+ ```typescript
76
+ type ProposalCallback = (proposal: SignClientTypes.EventArguments["session_proposal"]) => Promise<void>;
77
+ ```
78
+ ```typescript
79
+ await this.walletConnector.init(proposalCallback)
80
+ ```
81
+ 4. In order to connect to DApp just pass URI string to `pair` method of connector
82
+ ```typescript
83
+ this.walletConnector.pair(uri)
84
+ ```
85
+ 5. After reviewing of current proposal you should approve or reject it by calling appropriate methods:
86
+ ```typescript
87
+ rejectSessionProposal(data: RejectParams)
88
+ ```
89
+ or
90
+ ```typescript
91
+ approveSessionProposal<T extends Signer>(data: ApproveParams, signers: T[])
92
+ ```
93
+ When approving session except ApproveParams you should also provide Signer (HIP-338) implementations for all approved accounts.
94
+ 6. Wallet can also send events to the dApp using method `sendEvent`. With name and payload:
95
+ ```typescript
96
+ await this.walletConnector.sendEvent(name, data);
97
+ ```
98
+
99
+ ### Common section
100
+ 1. You can check whether connector is initialized by checking initialized field:
101
+ ```typescript
102
+ this.connector.initialized === true
103
+ ```
104
+ 2. In order to disconnect call `disconnect` method.
105
+ ```typescript
106
+ this.connector.disconnect()
107
+ ```
108
+
109
+
110
+ ## Utils
111
+
112
+ Conversion between WC chainId and Hedera LedgerId is possible using methods:
113
+ ```typescript
114
+ getChainByLedgerId: (ledgerId: LedgerId) => string;
115
+ getLedgerIdByChainId: (chainId: string) => string;
116
+ ```
117
+
118
+ # License
119
+ This repository is distributed under the terms of the MIT License. See [LICENSE](LICENSE) for details.
@@ -0,0 +1,81 @@
1
+ import { catchError, from, timeout } from "rxjs";
2
+ import { getAppMetadata, getSdkError } from "@walletconnect/utils";
3
+ export class Connector {
4
+ dAppMetadata;
5
+ isInitializing = false;
6
+ client = null;
7
+ session = null;
8
+ signers = [];
9
+ constructor(metadata) {
10
+ this.dAppMetadata = metadata || getAppMetadata();
11
+ }
12
+ async checkPersistedState() {
13
+ if (!this.client) {
14
+ throw new Error("WC is not initialized");
15
+ }
16
+ if (this.session) {
17
+ return this.session;
18
+ }
19
+ if (this.client.session.length) {
20
+ const sessionCheckPromises = this.client.session
21
+ .getAll()
22
+ .map((session) => {
23
+ if (session.expiry * 1000 <= Date.now()) {
24
+ try {
25
+ this.client.disconnect({
26
+ topic: session.topic,
27
+ reason: { code: 0, message: "Session expired" }
28
+ });
29
+ }
30
+ catch (e) {
31
+ console.log("Non existing session with topic:", session.topic);
32
+ }
33
+ return Promise.reject("Session expired");
34
+ }
35
+ return new Promise((resolve, reject) => from(this.client.ping({ topic: session.topic }))
36
+ .pipe(timeout(3000), catchError(async (err) => {
37
+ try {
38
+ await this.client.disconnect({
39
+ topic: session.topic,
40
+ reason: { code: 0, message: "Ping was unsuccessful" }
41
+ });
42
+ }
43
+ catch (e) {
44
+ console.log("Non existing session with topic:", session.topic);
45
+ }
46
+ reject("Non existing session");
47
+ })).subscribe(() => {
48
+ resolve(session);
49
+ }));
50
+ });
51
+ this.session = await Promise.any(sessionCheckPromises).catch(() => null);
52
+ return this.session;
53
+ }
54
+ this.session = null;
55
+ return this.session;
56
+ }
57
+ async disconnect() {
58
+ if (!this.client) {
59
+ throw new Error("WC is not initialized");
60
+ }
61
+ try {
62
+ if (this.session) {
63
+ await this.client.disconnect({
64
+ topic: this.session.topic,
65
+ reason: getSdkError("USER_DISCONNECTED")
66
+ });
67
+ }
68
+ }
69
+ finally {
70
+ this.reset();
71
+ }
72
+ }
73
+ reset() {
74
+ this.session = null;
75
+ this.signers = [];
76
+ }
77
+ get initialized() {
78
+ return Boolean(this.client && !this.isInitializing);
79
+ }
80
+ }
81
+ //# sourceMappingURL=Connector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Connector.js","sourceRoot":"","sources":["../../src/Connector.ts"],"names":[],"mappings":"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","sourcesContent":["import SignClient from \"@walletconnect/sign-client\";\nimport {catchError, from, timeout} from \"rxjs\";\nimport {Signer} from \"@hashgraph/sdk\";\nimport {SessionTypes, SignClientTypes} from \"@walletconnect/types\";\nimport {getAppMetadata, getSdkError} from \"@walletconnect/utils\";\n\ndeclare type Client = SignClient.default;\n\nexport class Connector {\n protected readonly dAppMetadata: SignClientTypes.Metadata;\n protected isInitializing: boolean = false;\n protected client: Client | null = null;\n protected session: SessionTypes.Struct | null = null;\n protected signers: Signer[] = [];\n\n protected constructor(metadata?: SignClientTypes.Metadata) {\n this.dAppMetadata = metadata || getAppMetadata();\n }\n\n async checkPersistedState() {\n if (!this.client) {\n throw new Error(\"WC is not initialized\");\n }\n\n if (this.session) {\n return this.session;\n }\n\n if (this.client.session.length) {\n const sessionCheckPromises: Promise<SessionTypes.Struct | null>[] = this.client.session\n .getAll()\n .map((session: SessionTypes.Struct) => {\n if (session.expiry * 1000 <= Date.now()) {\n try {\n this.client!.disconnect({\n topic: session.topic,\n reason: { code: 0, message: \"Session expired\" }\n });\n } catch (e) {\n console.log(\"Non existing session with topic:\", session.topic)\n }\n return Promise.reject(\"Session expired\");\n }\n return new Promise((resolve, reject) =>\n from(this.client!.ping({ topic: session.topic }))\n .pipe(\n timeout(3000),\n catchError(async (err) => {\n try {\n await this.client!.disconnect({\n topic: session.topic,\n reason: { code: 0, message: \"Ping was unsuccessful\" }\n });\n } catch (e) {\n console.log(\"Non existing session with topic:\", session.topic)\n }\n reject(\"Non existing session\");\n })\n ).subscribe(() => {\n resolve(session);\n })\n );\n });\n this.session = await Promise.any(sessionCheckPromises).catch(() => null);\n return this.session;\n }\n\n this.session = null;\n return this.session;\n }\n\n\n async disconnect() {\n if (!this.client) {\n throw new Error(\"WC is not initialized\");\n }\n try {\n if (this.session) {\n await this.client.disconnect({\n topic: this.session.topic,\n reason: getSdkError(\"USER_DISCONNECTED\")\n });\n }\n } finally {\n this.reset();\n }\n }\n\n private reset() {\n this.session = null;\n this.signers = [];\n }\n\n get initialized(): boolean {\n return Boolean(this.client && !this.isInitializing);\n }\n}\n"]}
@@ -0,0 +1,118 @@
1
+ import { AccountId, LedgerId } from "@hashgraph/sdk";
2
+ import QRCodeModal from "@walletconnect/qrcode-modal";
3
+ import { SignClient } from "@walletconnect/sign-client";
4
+ import { Subject } from "rxjs";
5
+ import { Connector } from "./Connector.js";
6
+ import { getAccountLedgerPairsFromSession, getExtensionMethodsFromSession, getLedgerIDsFromSession, getRequiredNamespaces } from "./Utils.js";
7
+ import { WCSigner } from "./WCSigner.js";
8
+ import { HWCError } from "./ErrorHelper.js";
9
+ export class DAppConnector extends Connector {
10
+ allowedEvents = [];
11
+ extensionMethods = [];
12
+ static instance;
13
+ $events = new Subject();
14
+ constructor(metadata) {
15
+ super(metadata);
16
+ DAppConnector.instance = this;
17
+ }
18
+ async init(events = [], methods = []) {
19
+ this.allowedEvents = events;
20
+ this.extensionMethods = methods;
21
+ try {
22
+ this.isInitializing = true;
23
+ this.client = await SignClient.init({
24
+ relayUrl: "wss://relay.walletconnect.com",
25
+ projectId: "ce06497abf4102004138a10edd29c921",
26
+ metadata: this.dAppMetadata
27
+ });
28
+ this.subscribeToEvents();
29
+ const existingSession = await this.checkPersistedState();
30
+ if (existingSession) {
31
+ await this.onSessionConnected(existingSession);
32
+ }
33
+ }
34
+ finally {
35
+ this.isInitializing = false;
36
+ }
37
+ }
38
+ subscribeToEvents() {
39
+ if (!this.client) {
40
+ throw new Error("WC is not initialized");
41
+ }
42
+ this.client.on("session_update", ({ topic, params }) => {
43
+ const { namespaces } = params;
44
+ const session = this.client.session.get(topic);
45
+ const updatedSession = { ...session, namespaces };
46
+ this.onSessionConnected(updatedSession);
47
+ });
48
+ this.client.on("session_event", ({ topic, params }) => {
49
+ if (params.chainId.includes("hedera:")) {
50
+ this.$events.next(params.event);
51
+ }
52
+ });
53
+ }
54
+ async connect(ledgerId = LedgerId.MAINNET, activeTopic) {
55
+ if (!this.client) {
56
+ throw new Error("WC is not initialized");
57
+ }
58
+ if (this.session) {
59
+ const sessionNetworks = getLedgerIDsFromSession(this.session).map(l => l.toString());
60
+ if (sessionNetworks.includes(ledgerId.toString())) {
61
+ return;
62
+ }
63
+ }
64
+ return new Promise(async (resolve, reject) => {
65
+ try {
66
+ const requiredNamespaces = getRequiredNamespaces(ledgerId);
67
+ requiredNamespaces.hedera.events.push(...this.allowedEvents);
68
+ const { uri, approval } = await this.client.connect({
69
+ pairingTopic: activeTopic,
70
+ requiredNamespaces
71
+ });
72
+ if (uri) {
73
+ // @ts-ignore
74
+ QRCodeModal.open(uri, () => {
75
+ reject(new HWCError(402, "User rejected pairing", {}));
76
+ });
77
+ }
78
+ const session = await approval();
79
+ await this.onSessionConnected(session);
80
+ resolve();
81
+ }
82
+ catch (e) {
83
+ reject(e);
84
+ }
85
+ finally {
86
+ // @ts-ignore
87
+ QRCodeModal.close();
88
+ }
89
+ });
90
+ }
91
+ async prepareConnectURI(ledgerId = LedgerId.MAINNET, activeTopic) {
92
+ if (!this.client) {
93
+ throw new Error("WC is not initialized");
94
+ }
95
+ if (this.session) {
96
+ const sessionNetworks = getLedgerIDsFromSession(this.session).map(l => l.toString());
97
+ if (sessionNetworks.includes(ledgerId.toString())) {
98
+ return;
99
+ }
100
+ }
101
+ const requiredNamespaces = getRequiredNamespaces(ledgerId);
102
+ requiredNamespaces.hedera.events.push(...this.allowedEvents);
103
+ requiredNamespaces.hedera.methods.push(...this.extensionMethods);
104
+ return this.client.connect({
105
+ pairingTopic: activeTopic,
106
+ requiredNamespaces
107
+ });
108
+ }
109
+ async onSessionConnected(session) {
110
+ const allNamespaceAccounts = getAccountLedgerPairsFromSession(session);
111
+ this.session = session;
112
+ this.signers = allNamespaceAccounts.map(({ account, network }) => new WCSigner(AccountId.fromString(account), this.client, session.topic, network, getExtensionMethodsFromSession(session)));
113
+ }
114
+ getSigners() {
115
+ return this.signers;
116
+ }
117
+ }
118
+ //# sourceMappingURL=DAppConnector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DAppConnector.js","sourceRoot":"","sources":["../../src/DAppConnector.ts"],"names":[],"mappings":"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","sourcesContent":["import {AccountId, LedgerId} from \"@hashgraph/sdk\";\nimport QRCodeModal from \"@walletconnect/qrcode-modal\";\nimport {SignClient} from \"@walletconnect/sign-client\";\nimport {SessionTypes, SignClientTypes} from \"@walletconnect/types\";\nimport {Subject} from \"rxjs\";\nimport {Connector} from \"./Connector.js\";\nimport {\n getAccountLedgerPairsFromSession, getExtensionMethodsFromSession,\n getLedgerIDsFromSession,\n getRequiredNamespaces\n} from \"./Utils.js\";\nimport {WCSigner} from \"./WCSigner.js\";\nimport {HWCError} from \"./ErrorHelper.js\";\n\ntype WalletEvent = {\n name: string,\n data: any\n}\n\nexport type DAppMetadata = SignClientTypes.Metadata;\n\nexport class DAppConnector extends Connector {\n private allowedEvents: string[] = [];\n private extensionMethods: string[] = [];\n static instance: DAppConnector;\n public $events: Subject<WalletEvent> = new Subject<WalletEvent>();\n\n constructor(metadata?: DAppMetadata) {\n super(metadata);\n DAppConnector.instance = this;\n }\n\n async init(events: string[] = [], methods: string[] = []) {\n this.allowedEvents = events;\n this.extensionMethods = methods;\n try {\n this.isInitializing = true;\n this.client = await SignClient.init({\n relayUrl: \"wss://relay.walletconnect.com\",\n projectId: \"ce06497abf4102004138a10edd29c921\",\n metadata: this.dAppMetadata\n });\n this.subscribeToEvents();\n const existingSession = await this.checkPersistedState();\n if (existingSession) {\n await this.onSessionConnected(existingSession);\n }\n } finally {\n this.isInitializing = false;\n }\n }\n\n private subscribeToEvents() {\n if (!this.client) {\n throw new Error(\"WC is not initialized\");\n }\n\n this.client.on(\"session_update\", ({ topic, params }) => {\n const { namespaces } = params;\n const session = this.client!.session.get(topic);\n const updatedSession = { ...session, namespaces };\n this.onSessionConnected(updatedSession);\n });\n this.client.on(\"session_event\", ({topic, params}) => {\n if (params.chainId.includes(\"hedera:\")) {\n this.$events.next(params.event);\n }\n });\n }\n\n async connect(ledgerId: LedgerId = LedgerId.MAINNET, activeTopic?: string) {\n if (!this.client) {\n throw new Error(\"WC is not initialized\");\n }\n\n if (this.session) {\n const sessionNetworks = getLedgerIDsFromSession(this.session).map(l => l.toString());\n if (sessionNetworks.includes(ledgerId.toString())) {\n return;\n }\n }\n\n return new Promise<void>(async (resolve, reject) => {\n try {\n const requiredNamespaces = getRequiredNamespaces(ledgerId);\n requiredNamespaces.hedera.events.push(...this.allowedEvents)\n const { uri, approval } = await this.client.connect({\n pairingTopic: activeTopic,\n requiredNamespaces\n });\n\n if (uri) {\n // @ts-ignore\n QRCodeModal.open(uri, () => {\n reject(new HWCError(402, \"User rejected pairing\", {}));\n });\n }\n\n const session = await approval();\n await this.onSessionConnected(session);\n resolve();\n } catch (e: any) {\n reject(e);\n } finally {\n // @ts-ignore\n QRCodeModal.close();\n }\n });\n }\n\n async prepareConnectURI(ledgerId: LedgerId = LedgerId.MAINNET, activeTopic?: string): Promise<{\n uri?: string;\n approval: () => Promise<SessionTypes.Struct>;\n }> {\n if (!this.client) {\n throw new Error(\"WC is not initialized\");\n }\n\n if (this.session) {\n const sessionNetworks = getLedgerIDsFromSession(this.session).map(l => l.toString());\n if (sessionNetworks.includes(ledgerId.toString())) {\n return;\n }\n }\n\n const requiredNamespaces = getRequiredNamespaces(ledgerId);\n requiredNamespaces.hedera.events.push(...this.allowedEvents);\n requiredNamespaces.hedera.methods.push(...this.extensionMethods);\n return this.client.connect({\n pairingTopic: activeTopic,\n requiredNamespaces\n });\n }\n\n async onSessionConnected(session: SessionTypes.Struct) {\n const allNamespaceAccounts = getAccountLedgerPairsFromSession(session);\n this.session = session;\n this.signers = allNamespaceAccounts.map(({account, network}) => new WCSigner(\n AccountId.fromString(account),\n this.client,\n session.topic,\n network,\n getExtensionMethodsFromSession(session)\n ))\n }\n\n getSigners() {\n return this.signers;\n }\n}\n"]}
@@ -0,0 +1,97 @@
1
+ export class HWCError extends Error {
2
+ code;
3
+ description;
4
+ error;
5
+ constructor(code, description, error) {
6
+ super(`HWC Error: ${description}`);
7
+ this.code = code;
8
+ this.description = description;
9
+ this.error = error;
10
+ }
11
+ }
12
+ function sleep(delay) {
13
+ return new Promise((resolve) => setTimeout(resolve, delay));
14
+ }
15
+ export const Catch = (errorType, handler, options) => {
16
+ async function handleError(ctx, errorType, handler, error) {
17
+ if (typeof handler === "function" && error instanceof errorType) {
18
+ const result = handler.call(null, error, ctx);
19
+ if (typeof result !== "undefined" && result instanceof Promise) {
20
+ return await result;
21
+ }
22
+ return result;
23
+ }
24
+ else {
25
+ switch (error.code) {
26
+ // @ts-ignore
27
+ case 402: {
28
+ throw new HWCError(402, "Signature rejected by user", error);
29
+ }
30
+ case 403:
31
+ case 423: {
32
+ throw new HWCError(403, "Wallet is closed or locked", error);
33
+ }
34
+ default: {
35
+ throw new HWCError(error.code || 500, "WalletConnect error", error);
36
+ }
37
+ }
38
+ }
39
+ }
40
+ function generateDescriptor(descriptor, errorType, handler) {
41
+ const originalMethod = descriptor.value;
42
+ descriptor.value = function (...args) {
43
+ let isRetry = false;
44
+ try {
45
+ const result = originalMethod.apply(this, args);
46
+ if (result && result instanceof Promise) {
47
+ return result.catch(async (error) => {
48
+ const canRetry = await handleError(this, errorType, handler, error);
49
+ if (options?.retry && canRetry) {
50
+ isRetry = true;
51
+ if (options.retryDelay) {
52
+ await sleep(options.retryDelay);
53
+ }
54
+ return originalMethod.apply(this, args);
55
+ }
56
+ });
57
+ }
58
+ return result;
59
+ }
60
+ catch (error) {
61
+ if (!isRetry) {
62
+ handleError(this, errorType, handler, error).then(async (canRetry) => {
63
+ if (options?.retry && canRetry) {
64
+ if (options.retryDelay) {
65
+ await sleep(options.retryDelay);
66
+ }
67
+ return originalMethod.apply(this, args);
68
+ }
69
+ });
70
+ }
71
+ else {
72
+ throw error;
73
+ }
74
+ }
75
+ };
76
+ return descriptor;
77
+ }
78
+ return (target, propertyKey, descriptor) => {
79
+ if (descriptor) {
80
+ // Method descriptor
81
+ return generateDescriptor(descriptor, errorType, handler);
82
+ }
83
+ else {
84
+ // Iterate over class properties except constructor
85
+ Reflect.ownKeys(target.prototype)
86
+ .filter(prop => prop !== "constructor")
87
+ .forEach((propertyName) => {
88
+ const desc = Object.getOwnPropertyDescriptor(target.prototype, propertyName);
89
+ if (desc.value instanceof Function) {
90
+ Object.defineProperty(target.prototype, propertyName, generateDescriptor(desc, errorType, handler));
91
+ }
92
+ });
93
+ }
94
+ };
95
+ };
96
+ export const CatchAll = (handler, options) => Catch(Error, handler, options);
97
+ //# sourceMappingURL=ErrorHelper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ErrorHelper.js","sourceRoot":"","sources":["../../src/ErrorHelper.ts"],"names":[],"mappings":"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","sourcesContent":["type HandlerFunction = (error: Error, ctx: any) => Promise<boolean> | boolean;\ntype CatchOptions = {\n retry?: boolean,\n retryDelay?: number\n}\n\nexport class HWCError extends Error {\n constructor(\n public readonly code: number,\n public readonly description: string,\n public readonly error: Error | {}\n ) {\n super(`HWC Error: ${description}`);\n }\n}\n\nfunction sleep(delay: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, delay));\n}\n\nexport const Catch = (errorType: any, handler: HandlerFunction, options?: CatchOptions): any => {\n async function handleError(ctx: any, errorType: any, handler: HandlerFunction, error: Error): Promise<boolean> {\n if (typeof handler === \"function\" && error instanceof errorType) {\n const result = handler.call(null, error, ctx);\n if (typeof result !== \"undefined\" && result instanceof Promise) {\n return await result;\n }\n return result;\n } else {\n switch ((error as any).code) {\n // @ts-ignore\n case 402: {\n throw new HWCError(402,\"Signature rejected by user\", error);\n }\n case 403:\n case 423: {\n throw new HWCError(403,\"Wallet is closed or locked\", error);\n }\n default: {\n throw new HWCError((error as any).code || 500,\"WalletConnect error\", error);\n }\n }\n }\n }\n\n function generateDescriptor(\n descriptor: PropertyDescriptor,\n errorType: any,\n handler: HandlerFunction\n ): PropertyDescriptor {\n const originalMethod = descriptor.value;\n\n descriptor.value = function (...args: any[]) {\n let isRetry = false;\n try {\n const result = originalMethod.apply(this, args);\n\n if (result && result instanceof Promise) {\n return result.catch(async (error: any) => {\n const canRetry = await handleError(this, errorType, handler, error);\n if (options?.retry && canRetry) {\n isRetry = true;\n if (options.retryDelay) {\n await sleep(options.retryDelay);\n }\n return originalMethod.apply(this, args);\n }\n });\n }\n\n return result;\n } catch (error: any) {\n if (!isRetry) {\n handleError(this, errorType, handler, error).then(async (canRetry) => {\n if (options?.retry && canRetry) {\n if (options.retryDelay) {\n await sleep(options.retryDelay);\n }\n return originalMethod.apply(this, args);\n }\n });\n } else {\n throw error;\n }\n }\n };\n\n return descriptor;\n }\n\n return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {\n if (descriptor) {\n // Method descriptor\n return generateDescriptor(descriptor, errorType, handler);\n } else {\n // Iterate over class properties except constructor\n Reflect.ownKeys(target.prototype)\n .filter(prop => prop !== \"constructor\")\n .forEach((propertyName) => {\n const desc = Object.getOwnPropertyDescriptor(target.prototype, propertyName)!;\n if (desc.value instanceof Function) {\n Object.defineProperty(\n target.prototype,\n propertyName,\n generateDescriptor(desc, errorType, handler)\n );\n }\n });\n }\n };\n};\n\nexport const CatchAll = (handler: HandlerFunction, options?: CatchOptions): any => Catch(Error, handler, options);"]}
@@ -0,0 +1,99 @@
1
+ import { AccountId, LedgerId, PublicKey, SignerSignature, Transaction } from "@hashgraph/sdk";
2
+ import { Buffer } from "buffer";
3
+ const chainsMap = new Map();
4
+ chainsMap.set(LedgerId.MAINNET.toString(), 295);
5
+ chainsMap.set(LedgerId.TESTNET.toString(), 296);
6
+ chainsMap.set(LedgerId.PREVIEWNET.toString(), 297);
7
+ export var METHODS;
8
+ (function (METHODS) {
9
+ METHODS["SIGN_TRANSACTION"] = "signTransaction";
10
+ METHODS["CALL"] = "call";
11
+ METHODS["GET_ACCOUNT_BALANCE"] = "getAccountBalance";
12
+ METHODS["GET_ACCOUNT_INFO"] = "getAccountInfo";
13
+ METHODS["GET_LEDGER_ID"] = "getLedgerId";
14
+ METHODS["GET_ACCOUNT_ID"] = "getAccountId";
15
+ METHODS["GET_ACCOUNT_KEY"] = "getAccountKey";
16
+ METHODS["GET_NETWORK"] = "getNetwork";
17
+ METHODS["GET_MIRROR_NETWORK"] = "getMirrorNetwork";
18
+ METHODS["SIGN"] = "sign";
19
+ METHODS["GET_ACCOUNT_RECORDS"] = "getAccountRecords";
20
+ METHODS["CHECK_TRANSACTION"] = "checkTransaction";
21
+ METHODS["POPULATE_TRANSACTION"] = "populateTransaction";
22
+ })(METHODS || (METHODS = {}));
23
+ export var EVENTS;
24
+ (function (EVENTS) {
25
+ EVENTS["ACCOUNTS_CHANGED"] = "accountsChanged";
26
+ })(EVENTS || (EVENTS = {}));
27
+ export const getChainByLedgerId = (ledgerId) => {
28
+ return `hedera:${chainsMap.get(ledgerId.toString())}`;
29
+ };
30
+ export const getLedgerIdByChainId = (chainId) => {
31
+ const ledgerIdsMap = Object.fromEntries(Array.from(chainsMap.entries()).map(a => a.reverse()));
32
+ return ledgerIdsMap[parseInt(chainId)];
33
+ };
34
+ export const getRequiredNamespaces = (ledgerId) => {
35
+ return {
36
+ hedera: {
37
+ chains: [getChainByLedgerId(ledgerId)],
38
+ methods: Object.values(METHODS),
39
+ events: Object.values(EVENTS),
40
+ }
41
+ };
42
+ };
43
+ export const getLedgerIDsFromSession = (session) => {
44
+ return Object.values(session?.namespaces || {})
45
+ .flatMap(namespace => namespace.accounts.map(acc => {
46
+ const [network, chainId, account] = acc.split(":");
47
+ return LedgerId.fromString(getLedgerIdByChainId(chainId));
48
+ }));
49
+ };
50
+ export const getAccountLedgerPairsFromSession = (session) => {
51
+ return Object.values(session?.namespaces || {})
52
+ .flatMap(namespace => namespace.accounts.map(acc => {
53
+ const [network, chainId, account] = acc.split(":");
54
+ return { network: LedgerId.fromString(getLedgerIdByChainId(chainId)), account };
55
+ }));
56
+ };
57
+ export const getExtensionMethodsFromSession = (session) => {
58
+ return Object.values(session.namespaces)
59
+ .flatMap(ns => ns.methods)
60
+ .filter(method => !Object.values(METHODS).includes(method));
61
+ };
62
+ export const isEncodable = (obj) => {
63
+ return ("toBytes" in obj) &&
64
+ (typeof obj.toBytes === "function");
65
+ };
66
+ export const isTransaction = (obj) => {
67
+ if (obj instanceof Transaction) {
68
+ return true;
69
+ }
70
+ else if ("transactionId" in obj && "sign" in obj) {
71
+ return true;
72
+ }
73
+ return false;
74
+ };
75
+ export const evmAddressFromObject = (data) => {
76
+ try {
77
+ return Buffer.from(Object.values(data?._bytes || [])).toString("hex");
78
+ }
79
+ catch {
80
+ return null;
81
+ }
82
+ };
83
+ export const publicKeyFromObject = (data) => {
84
+ try {
85
+ return PublicKey.fromBytes(Buffer.from(Object.values(data?._key?._key?._keyData || [])));
86
+ }
87
+ catch {
88
+ return null;
89
+ }
90
+ };
91
+ export const convertToSignerSignature = (data) => {
92
+ const publicKey = publicKeyFromObject(data.publicKey);
93
+ const { shard, realm, num, aliasKey, aliasEvmAddress } = data.accountId;
94
+ const accountAddress = evmAddressFromObject(aliasEvmAddress) || publicKeyFromObject(aliasKey) || num.low;
95
+ const accountId = AccountId.fromString(`${shard.low}.${realm.low}.${accountAddress.toString()}`);
96
+ const signature = Buffer.from(Object.values(data.signature.data || data.signature));
97
+ return new SignerSignature({ accountId, signature, publicKey });
98
+ };
99
+ //# sourceMappingURL=Utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Utils.js","sourceRoot":"","sources":["../../src/Utils.ts"],"names":[],"mappings":"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","sourcesContent":["import {AccountId, LedgerId, PublicKey, SignerSignature, Transaction} from \"@hashgraph/sdk\";\nimport {ProposalTypes, SessionTypes} from \"@walletconnect/types\";\nimport {Buffer} from \"buffer\";\n\nconst chainsMap = new Map();\nchainsMap.set(LedgerId.MAINNET.toString(), 295);\nchainsMap.set(LedgerId.TESTNET.toString(), 296);\nchainsMap.set(LedgerId.PREVIEWNET.toString(), 297);\n\nexport enum METHODS {\n SIGN_TRANSACTION = \"signTransaction\",\n CALL = \"call\",\n GET_ACCOUNT_BALANCE = \"getAccountBalance\",\n GET_ACCOUNT_INFO = \"getAccountInfo\",\n GET_LEDGER_ID = \"getLedgerId\",\n GET_ACCOUNT_ID = \"getAccountId\",\n GET_ACCOUNT_KEY = \"getAccountKey\",\n GET_NETWORK = \"getNetwork\",\n GET_MIRROR_NETWORK = \"getMirrorNetwork\",\n SIGN = \"sign\",\n GET_ACCOUNT_RECORDS = \"getAccountRecords\",\n CHECK_TRANSACTION = \"checkTransaction\",\n POPULATE_TRANSACTION = \"populateTransaction\"\n}\n\nexport enum EVENTS {\n ACCOUNTS_CHANGED = \"accountsChanged\",\n}\n\nexport const getChainByLedgerId = (ledgerId: LedgerId): string => {\n return `hedera:${chainsMap.get(ledgerId.toString())}`;\n}\n\nexport const getLedgerIdByChainId = (chainId: string): string => {\n const ledgerIdsMap = Object.fromEntries(Array.from(chainsMap.entries()).map(a => a.reverse()));\n return ledgerIdsMap[parseInt(chainId)];\n};\n\nexport const getRequiredNamespaces = (ledgerId: LedgerId): ProposalTypes.RequiredNamespaces => {\n return {\n hedera: {\n chains: [getChainByLedgerId(ledgerId)],\n methods: Object.values(METHODS),\n events: Object.values(EVENTS),\n }\n };\n};\n\nexport const getLedgerIDsFromSession = (session: SessionTypes.Struct): LedgerId[] => {\n return Object.values(session?.namespaces || {})\n .flatMap(namespace => namespace.accounts.map(acc => {\n const [network, chainId, account] = acc.split(\":\");\n return LedgerId.fromString(getLedgerIdByChainId(chainId));\n }));\n};\nexport const getAccountLedgerPairsFromSession = (session: SessionTypes.Struct): {network: LedgerId, account: string}[] => {\n return Object.values(session?.namespaces || {})\n .flatMap(namespace => namespace.accounts.map(acc => {\n const [network, chainId, account] = acc.split(\":\");\n return {network: LedgerId.fromString(getLedgerIdByChainId(chainId)), account};\n }));\n};\n\nexport const getExtensionMethodsFromSession = (session: SessionTypes.Struct): string[] => {\n return Object.values(session.namespaces)\n .flatMap(ns => ns.methods)\n .filter(method => !Object.values(METHODS).includes(method as any));\n}\n\ntype Encodable = {\n toBytes(): Uint8Array\n}\n\nexport const isEncodable = (obj: any): obj is Encodable => {\n return (\"toBytes\" in obj) &&\n (typeof (obj as Encodable).toBytes === \"function\");\n};\n\nexport const isTransaction = (obj: any): obj is Transaction => {\n if (obj instanceof Transaction) {\n return true;\n } else if (\"transactionId\" in obj && \"sign\" in obj) {\n return true;\n }\n return false;\n};\n\nexport const evmAddressFromObject = (data): string | null => {\n try {\n return Buffer.from(Object.values(data?._bytes || []) as number[]).toString(\"hex\");\n } catch {\n return null;\n }\n}\n\nexport const publicKeyFromObject = (data): PublicKey | null => {\n try {\n return PublicKey.fromBytes(Buffer.from(Object.values(data?._key?._key?._keyData || []) as number[]));\n } catch {\n return null;\n }\n}\n\nexport const convertToSignerSignature = (data): SignerSignature => {\n const publicKey = publicKeyFromObject(data.publicKey);\n const {shard, realm, num, aliasKey, aliasEvmAddress} = data.accountId;\n const accountAddress = evmAddressFromObject(aliasEvmAddress) || publicKeyFromObject(aliasKey) || num.low;\n const accountId = AccountId.fromString(`${shard.low}.${realm.low}.${accountAddress.toString()}`);\n const signature = Buffer.from(Object.values(data.signature.data || data.signature) as []);\n return new SignerSignature({accountId, signature, publicKey});\n}\n"]}