@hashgraph/hedera-wallet-connect 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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"]}