genlayer-js 0.6.3 → 0.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 (41) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +6 -6
  3. package/dist/chains/index.cjs +4 -2
  4. package/dist/chains/index.d.cts +1 -1
  5. package/dist/chains/index.d.ts +1 -1
  6. package/dist/chains/index.js +3 -1
  7. package/dist/{chunk-XAQMWSP4.cjs → chunk-I6HC44KD.cjs} +34 -4
  8. package/dist/{chunk-O3T2C57T.js → chunk-WEXFFND6.js} +33 -3
  9. package/dist/index-B8E0qiOq.d.cts +13 -0
  10. package/dist/{index-vnyqXaRU.d.ts → index-CpcNUbXb.d.ts} +13 -1
  11. package/dist/{index-FMf4Unm0.d.cts → index-DJTO3-o3.d.cts} +13 -1
  12. package/dist/index-ZoW0HQ_m.d.ts +13 -0
  13. package/dist/index.cjs +124 -16
  14. package/dist/index.d.cts +2 -2
  15. package/dist/index.d.ts +2 -2
  16. package/dist/index.js +118 -10
  17. package/dist/types/index.cjs +2 -2
  18. package/dist/types/index.d.cts +1 -1
  19. package/dist/types/index.d.ts +1 -1
  20. package/dist/types/index.js +1 -1
  21. package/package.json +1 -1
  22. package/src/accounts/actions.ts +3 -3
  23. package/src/chains/index.ts +1 -0
  24. package/src/chains/localnet.ts +30 -0
  25. package/src/client/client.ts +10 -6
  26. package/src/config/snapID.ts +4 -0
  27. package/src/global.d.ts +1 -1
  28. package/src/types/clients.ts +5 -0
  29. package/src/types/index.ts +2 -0
  30. package/src/types/metamaskClientResult.ts +5 -0
  31. package/src/types/network.ts +1 -0
  32. package/src/types/snapSource.ts +1 -0
  33. package/src/wallet/actions.ts +10 -0
  34. package/src/wallet/connect.ts +65 -0
  35. package/src/wallet/metamaskClient.ts +50 -0
  36. package/tests/client.test-d.ts +2 -2
  37. package/tests/client.test.ts +7 -7
  38. package/dist/index-CHQn8ZME.d.cts +0 -10
  39. package/dist/index-CioK5j0r.d.ts +0 -10
  40. /package/dist/{chunk-2EJVFGKU.js → chunk-K72OSU5N.js} +0 -0
  41. /package/dist/{chunk-52HYC24L.cjs → chunk-YDFRDDP5.cjs} +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
 
2
2
 
3
+ ## 0.7.0 (2025-03-05)
4
+
5
+
6
+ ### Features
7
+
8
+ * connect ([#58](https://github.com/yeagerai/genlayer-js/issues/58)) ([7e396c7](https://github.com/yeagerai/genlayer-js/commit/7e396c765536ef0ec1a81c259c113587dc6de8ee))
9
+
10
+ ## 0.6.4 (2025-02-04)
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * override chain endpoint if extra config provided ([#68](https://github.com/yeagerai/genlayer-js/issues/68)) ([215185a](https://github.com/yeagerai/genlayer-js/commit/215185a4f96d44a60ea1ad4b55c71bd0bdc489f6))
16
+
3
17
  ## 0.6.3 (2025-01-28)
4
18
 
5
19
  ## 0.6.2 (2025-01-20)
package/README.md CHANGED
@@ -26,11 +26,11 @@ Here’s how to initialize the client and connect to the GenLayer Simulator:
26
26
 
27
27
  ### Reading a Transaction
28
28
  ```typescript
29
- import { simulator } from 'genlayer-js/chains';
29
+ import { localnet } from 'genlayer-js/chains';
30
30
  import { createClient } from "genlayer-js";
31
31
 
32
32
  const client = createClient({
33
- chain: simulator,
33
+ chain: localnet,
34
34
  });
35
35
 
36
36
  const transactionHash = "0x...";
@@ -40,11 +40,11 @@ const transaction = await client.getTransaction({ hash: transactionHash })
40
40
 
41
41
  ### Reading a contract
42
42
  ```typescript
43
- import { simulator } from 'genlayer-js/chains';
43
+ import { localnet } from 'genlayer-js/chains';
44
44
  import { createClient } from "genlayer-js";
45
45
 
46
46
  const client = createClient({
47
- chain: simulator,
47
+ chain: localnet,
48
48
  });
49
49
 
50
50
  const result = await client.readContract({
@@ -58,11 +58,11 @@ const result = await client.readContract({
58
58
 
59
59
  ### Writing a transaction
60
60
  ```typescript
61
- import { simulator } from 'genlayer-js/chains';
61
+ import { localnet } from 'genlayer-js/chains';
62
62
  import { createClient, createAccount } from "genlayer-js";
63
63
 
64
64
  const client = createClient({
65
- network: simulator,
65
+ network: localnet,
66
66
  });
67
67
 
68
68
  const account = createAccount();
@@ -1,7 +1,9 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
2
 
3
- var _chunkXAQMWSP4cjs = require('../chunk-XAQMWSP4.cjs');
3
+
4
+ var _chunkI6HC44KDcjs = require('../chunk-I6HC44KD.cjs');
4
5
  require('../chunk-75ZPJI57.cjs');
5
6
 
6
7
 
7
- exports.simulator = _chunkXAQMWSP4cjs.simulator;
8
+
9
+ exports.localnet = _chunkI6HC44KDcjs.localnet; exports.simulator = _chunkI6HC44KDcjs.simulator;
@@ -1,3 +1,3 @@
1
- export { s as simulator } from '../index-CHQn8ZME.cjs';
1
+ export { l as localnet, s as simulator } from '../index-B8E0qiOq.cjs';
2
2
  import '../chains-C5PI_Nr_.cjs';
3
3
  import 'viem';
@@ -1,3 +1,3 @@
1
- export { s as simulator } from '../index-CioK5j0r.js';
1
+ export { l as localnet, s as simulator } from '../index-ZoW0HQ_m.js';
2
2
  import '../chains-C5PI_Nr_.js';
3
3
  import 'viem';
@@ -1,7 +1,9 @@
1
1
  import {
2
+ localnet,
2
3
  simulator
3
- } from "../chunk-O3T2C57T.js";
4
+ } from "../chunk-WEXFFND6.js";
4
5
  import "../chunk-MLKGABMK.js";
5
6
  export {
7
+ localnet,
6
8
  simulator
7
9
  };
@@ -5,15 +5,16 @@ var _chunk75ZPJI57cjs = require('./chunk-75ZPJI57.cjs');
5
5
  // src/chains/index.ts
6
6
  var chains_exports = {};
7
7
  _chunk75ZPJI57cjs.__export.call(void 0, chains_exports, {
8
+ localnet: () => localnet,
8
9
  simulator: () => simulator
9
10
  });
10
11
 
11
- // src/chains/simulator.ts
12
+ // src/chains/localnet.ts
12
13
  var _viem = require('viem');
13
14
  var SIMULATOR_JSON_RPC_URL = "http://127.0.0.1:4000/api";
14
- var simulator = _viem.defineChain.call(void 0, {
15
+ var localnet = _viem.defineChain.call(void 0, {
15
16
  id: 61999,
16
- name: "GenLayer Simulator",
17
+ name: "Genlayer Localnet",
17
18
  rpcUrls: {
18
19
  default: {
19
20
  http: [SIMULATOR_JSON_RPC_URL]
@@ -36,7 +37,36 @@ var simulator = _viem.defineChain.call(void 0, {
36
37
  defaultConsensusMaxRotations: 3
37
38
  });
38
39
 
40
+ // src/chains/simulator.ts
41
+
42
+ var SIMULATOR_JSON_RPC_URL2 = "http://127.0.0.1:4000/api";
43
+ var simulator = _viem.defineChain.call(void 0, {
44
+ id: 61999,
45
+ name: "GenLayer Simulator",
46
+ rpcUrls: {
47
+ default: {
48
+ http: [SIMULATOR_JSON_RPC_URL2]
49
+ }
50
+ },
51
+ nativeCurrency: {
52
+ name: "GEN Token",
53
+ symbol: "GEN",
54
+ decimals: 18
55
+ },
56
+ blockExplorers: {
57
+ default: {
58
+ name: "GenLayer Explorer",
59
+ url: SIMULATOR_JSON_RPC_URL2
60
+ }
61
+ },
62
+ testnet: true,
63
+ consensusMainContract: null,
64
+ defaultNumberOfInitialValidators: 5,
65
+ defaultConsensusMaxRotations: 3
66
+ });
67
+
68
+
39
69
 
40
70
 
41
71
 
42
- exports.simulator = simulator; exports.chains_exports = chains_exports;
72
+ exports.localnet = localnet; exports.simulator = simulator; exports.chains_exports = chains_exports;
@@ -5,15 +5,16 @@ import {
5
5
  // src/chains/index.ts
6
6
  var chains_exports = {};
7
7
  __export(chains_exports, {
8
+ localnet: () => localnet,
8
9
  simulator: () => simulator
9
10
  });
10
11
 
11
- // src/chains/simulator.ts
12
+ // src/chains/localnet.ts
12
13
  import { defineChain } from "viem";
13
14
  var SIMULATOR_JSON_RPC_URL = "http://127.0.0.1:4000/api";
14
- var simulator = defineChain({
15
+ var localnet = defineChain({
15
16
  id: 61999,
16
- name: "GenLayer Simulator",
17
+ name: "Genlayer Localnet",
17
18
  rpcUrls: {
18
19
  default: {
19
20
  http: [SIMULATOR_JSON_RPC_URL]
@@ -36,7 +37,36 @@ var simulator = defineChain({
36
37
  defaultConsensusMaxRotations: 3
37
38
  });
38
39
 
40
+ // src/chains/simulator.ts
41
+ import { defineChain as defineChain2 } from "viem";
42
+ var SIMULATOR_JSON_RPC_URL2 = "http://127.0.0.1:4000/api";
43
+ var simulator = defineChain2({
44
+ id: 61999,
45
+ name: "GenLayer Simulator",
46
+ rpcUrls: {
47
+ default: {
48
+ http: [SIMULATOR_JSON_RPC_URL2]
49
+ }
50
+ },
51
+ nativeCurrency: {
52
+ name: "GEN Token",
53
+ symbol: "GEN",
54
+ decimals: 18
55
+ },
56
+ blockExplorers: {
57
+ default: {
58
+ name: "GenLayer Explorer",
59
+ url: SIMULATOR_JSON_RPC_URL2
60
+ }
61
+ },
62
+ testnet: true,
63
+ consensusMainContract: null,
64
+ defaultNumberOfInitialValidators: 5,
65
+ defaultConsensusMaxRotations: 3
66
+ });
67
+
39
68
  export {
69
+ localnet,
40
70
  simulator,
41
71
  chains_exports
42
72
  };
@@ -0,0 +1,13 @@
1
+ import { S as SimulatorChain } from './chains-C5PI_Nr_.cjs';
2
+
3
+ declare const localnet: SimulatorChain;
4
+
5
+ declare const simulator: SimulatorChain;
6
+
7
+ declare const index_localnet: typeof localnet;
8
+ declare const index_simulator: typeof simulator;
9
+ declare namespace index {
10
+ export { index_localnet as localnet, index_simulator as simulator };
11
+ }
12
+
13
+ export { index as i, localnet as l, simulator as s };
@@ -91,6 +91,16 @@ type ContractSchema = {
91
91
  methods: ContractMethod[];
92
92
  };
93
93
 
94
+ type Network = 'localnet' | 'testnet' | 'mainnet';
95
+
96
+ type SnapSource = 'npm' | 'local';
97
+
98
+ type MetaMaskClientResult = {
99
+ isFlask: boolean;
100
+ installedSnaps: Record<string, any>;
101
+ isGenLayerSnapInstalled: boolean;
102
+ };
103
+
94
104
  type GenLayerMethod = {
95
105
  method: "sim_fundAccount";
96
106
  params: [address: string, amount: number];
@@ -168,6 +178,8 @@ type GenLayerClient<TSimulatorChain extends SimulatorChain> = Omit<Client<Transp
168
178
  getContractSchema: (address: string) => Promise<ContractSchema>;
169
179
  getContractSchemaForCode: (contractCode: string | Uint8Array) => Promise<ContractSchema>;
170
180
  initializeConsensusSmartContract: (forceReset?: boolean) => Promise<void>;
181
+ connect: (network?: Network, snapSource?: SnapSource) => Promise<void>;
182
+ metamaskClient: (snapSource?: SnapSource) => Promise<MetaMaskClientResult>;
171
183
  };
172
184
 
173
- export { type Address as A, type CalldataEncodable as C, type GenLayerClient as G, type MethodDescription as M, type TransactionDataElement$1 as T, CalldataAddress as a, type GenLayerMethod as b, type ContractParamsArraySchemaElement as c, type ContractParamsSchema as d, type ContractMethodBase as e, type ContractMethod as f, type ContractSchema as g, type TransactionHash as h, TransactionStatus as i, type GenLayerTransaction as j, type TransactionDataElement as k };
185
+ export { type Address as A, type CalldataEncodable as C, type GenLayerClient as G, type MethodDescription as M, type Network as N, type SnapSource as S, type TransactionDataElement$1 as T, CalldataAddress as a, type GenLayerMethod as b, type ContractParamsArraySchemaElement as c, type ContractParamsSchema as d, type ContractMethodBase as e, type ContractMethod as f, type ContractSchema as g, type TransactionHash as h, TransactionStatus as i, type GenLayerTransaction as j, type TransactionDataElement as k };
@@ -91,6 +91,16 @@ type ContractSchema = {
91
91
  methods: ContractMethod[];
92
92
  };
93
93
 
94
+ type Network = 'localnet' | 'testnet' | 'mainnet';
95
+
96
+ type SnapSource = 'npm' | 'local';
97
+
98
+ type MetaMaskClientResult = {
99
+ isFlask: boolean;
100
+ installedSnaps: Record<string, any>;
101
+ isGenLayerSnapInstalled: boolean;
102
+ };
103
+
94
104
  type GenLayerMethod = {
95
105
  method: "sim_fundAccount";
96
106
  params: [address: string, amount: number];
@@ -168,6 +178,8 @@ type GenLayerClient<TSimulatorChain extends SimulatorChain> = Omit<Client<Transp
168
178
  getContractSchema: (address: string) => Promise<ContractSchema>;
169
179
  getContractSchemaForCode: (contractCode: string | Uint8Array) => Promise<ContractSchema>;
170
180
  initializeConsensusSmartContract: (forceReset?: boolean) => Promise<void>;
181
+ connect: (network?: Network, snapSource?: SnapSource) => Promise<void>;
182
+ metamaskClient: (snapSource?: SnapSource) => Promise<MetaMaskClientResult>;
171
183
  };
172
184
 
173
- export { type Address as A, type CalldataEncodable as C, type GenLayerClient as G, type MethodDescription as M, type TransactionDataElement$1 as T, CalldataAddress as a, type GenLayerMethod as b, type ContractParamsArraySchemaElement as c, type ContractParamsSchema as d, type ContractMethodBase as e, type ContractMethod as f, type ContractSchema as g, type TransactionHash as h, TransactionStatus as i, type GenLayerTransaction as j, type TransactionDataElement as k };
185
+ export { type Address as A, type CalldataEncodable as C, type GenLayerClient as G, type MethodDescription as M, type Network as N, type SnapSource as S, type TransactionDataElement$1 as T, CalldataAddress as a, type GenLayerMethod as b, type ContractParamsArraySchemaElement as c, type ContractParamsSchema as d, type ContractMethodBase as e, type ContractMethod as f, type ContractSchema as g, type TransactionHash as h, TransactionStatus as i, type GenLayerTransaction as j, type TransactionDataElement as k };
@@ -0,0 +1,13 @@
1
+ import { S as SimulatorChain } from './chains-C5PI_Nr_.js';
2
+
3
+ declare const localnet: SimulatorChain;
4
+
5
+ declare const simulator: SimulatorChain;
6
+
7
+ declare const index_localnet: typeof localnet;
8
+ declare const index_simulator: typeof simulator;
9
+ declare namespace index {
10
+ export { index_localnet as localnet, index_simulator as simulator };
11
+ }
12
+
13
+ export { index as i, localnet as l, simulator as s };
package/dist/index.cjs CHANGED
@@ -1,10 +1,11 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
2
 
3
3
 
4
- var _chunkXAQMWSP4cjs = require('./chunk-XAQMWSP4.cjs');
5
4
 
5
+ var _chunkI6HC44KDcjs = require('./chunk-I6HC44KD.cjs');
6
6
 
7
- var _chunk52HYC24Lcjs = require('./chunk-52HYC24L.cjs');
7
+
8
+ var _chunkYDFRDDP5cjs = require('./chunk-YDFRDDP5.cjs');
8
9
 
9
10
 
10
11
  var _chunk75ZPJI57cjs = require('./chunk-75ZPJI57.cjs');
@@ -16,8 +17,8 @@ var _viem = require('viem');
16
17
  function accountActions(client) {
17
18
  return {
18
19
  fundAccount: async ({ address, amount }) => {
19
- if (_optionalChain([client, 'access', _ => _.chain, 'optionalAccess', _2 => _2.id]) !== _chunkXAQMWSP4cjs.simulator.id) {
20
- throw new Error("Client is not connected to the simulator");
20
+ if (_optionalChain([client, 'access', _ => _.chain, 'optionalAccess', _2 => _2.id]) !== _chunkI6HC44KDcjs.localnet.id) {
21
+ throw new Error("Client is not connected to the localnet");
21
22
  }
22
23
  return client.request({
23
24
  method: "sim_fundAccount",
@@ -167,7 +168,7 @@ function encodeImpl(to, data) {
167
168
  }
168
169
  } else if (data instanceof Map) {
169
170
  encodeMap(to, data);
170
- } else if (data instanceof _chunk52HYC24Lcjs.CalldataAddress) {
171
+ } else if (data instanceof _chunkYDFRDDP5cjs.CalldataAddress) {
171
172
  to.push(SPECIAL_ADDR);
172
173
  for (const c of data.bytes) {
173
174
  to.push(c);
@@ -216,7 +217,7 @@ function decodeImpl(data, index) {
216
217
  case BigInt(SPECIAL_ADDR): {
217
218
  const res = data.slice(index.i, index.i + 20);
218
219
  index.i += 20;
219
- return new (0, _chunk52HYC24Lcjs.CalldataAddress)(res);
220
+ return new (0, _chunkYDFRDDP5cjs.CalldataAddress)(res);
220
221
  }
221
222
  }
222
223
  const type = Number(cur & 0xffn) & (1 << BITS_IN_TYPE) - 1;
@@ -328,7 +329,7 @@ function toStringImpl(data, to) {
328
329
  to.push("]");
329
330
  } else if (data instanceof Map) {
330
331
  toStringImplMap(data.entries(), to);
331
- } else if (data instanceof _chunk52HYC24Lcjs.CalldataAddress) {
332
+ } else if (data instanceof _chunkYDFRDDP5cjs.CalldataAddress) {
332
333
  to.push("addr#");
333
334
  for (const c of data.bytes) {
334
335
  to.push(c.toString(16));
@@ -541,14 +542,119 @@ var transactionActions = (client) => ({
541
542
  }
542
543
  });
543
544
 
545
+ // src/config/snapID.ts
546
+ var snapID = {
547
+ local: "local:http://localhost:8081",
548
+ npm: "npm:genlayer-wallet-plugin"
549
+ };
550
+
551
+ // src/wallet/connect.ts
552
+ var networks = {
553
+ localnet: _chunkI6HC44KDcjs.localnet
554
+ };
555
+ var connect = async (client, network = "localnet", snapSource = "npm") => {
556
+ if (!window.ethereum) {
557
+ throw new Error("MetaMask is not installed.");
558
+ }
559
+ if (network === "testnet" || network === "mainnet") {
560
+ throw new Error(`${network} is not available yet. Please use localnet.`);
561
+ }
562
+ const selectedNetwork = networks[network];
563
+ if (!selectedNetwork) {
564
+ throw new Error(`Network configuration for '${network}' is not available.`);
565
+ }
566
+ const chainIdHex = `0x${selectedNetwork.id.toString(16)}`;
567
+ const chainParams = {
568
+ chainId: chainIdHex,
569
+ chainName: selectedNetwork.name,
570
+ rpcUrls: selectedNetwork.rpcUrls.default.http,
571
+ nativeCurrency: selectedNetwork.nativeCurrency,
572
+ blockExplorerUrls: [_optionalChain([selectedNetwork, 'access', _19 => _19.blockExplorers, 'optionalAccess', _20 => _20.default, 'access', _21 => _21.url])]
573
+ };
574
+ const currentChainId = await window.ethereum.request({ method: "eth_chainId" });
575
+ if (currentChainId !== chainIdHex) {
576
+ await window.ethereum.request({
577
+ method: "wallet_addEthereumChain",
578
+ params: [chainParams]
579
+ });
580
+ await window.ethereum.request({
581
+ method: "wallet_switchEthereumChain",
582
+ params: [{ chainId: chainIdHex }]
583
+ });
584
+ }
585
+ const id = snapSource === "local" ? snapID.local : snapID.npm;
586
+ const installedSnaps = await window.ethereum.request({ method: "wallet_getSnaps" });
587
+ const isGenLayerSnapInstalled = Object.values(installedSnaps).some(
588
+ (snap) => snap.id === id
589
+ );
590
+ if (!isGenLayerSnapInstalled) {
591
+ await window.ethereum.request({
592
+ method: "wallet_requestSnaps",
593
+ params: {
594
+ [id]: {}
595
+ }
596
+ });
597
+ }
598
+ client.chain = selectedNetwork;
599
+ };
600
+
601
+ // src/wallet/metamaskClient.ts
602
+ var metamaskClient = async (snapSource = "npm") => {
603
+ if (typeof window === "undefined" || !window.ethereum) {
604
+ throw new Error("MetaMask is not installed.");
605
+ }
606
+ const isFlask = async () => {
607
+ try {
608
+ const clientVersion = await _optionalChain([window, 'access', _22 => _22.ethereum, 'optionalAccess', _23 => _23.request, 'call', _24 => _24({
609
+ method: "web3_clientVersion"
610
+ })]);
611
+ return _optionalChain([clientVersion, 'optionalAccess', _25 => _25.includes, 'call', _26 => _26("flask")]);
612
+ } catch (error) {
613
+ console.error("Error detecting Flask:", error);
614
+ return false;
615
+ }
616
+ };
617
+ const installedSnaps = async () => {
618
+ try {
619
+ return await _optionalChain([window, 'access', _27 => _27.ethereum, 'optionalAccess', _28 => _28.request, 'call', _29 => _29({
620
+ method: "wallet_getSnaps"
621
+ })]);
622
+ } catch (error) {
623
+ console.error("Error getting installed snaps:", error);
624
+ return {};
625
+ }
626
+ };
627
+ const isGenLayerSnapInstalled = async () => {
628
+ const id = snapSource === "local" ? snapID.local : snapID.npm;
629
+ const snaps = await installedSnaps();
630
+ return Object.values(snaps).some((snap) => snap.id === id);
631
+ };
632
+ const flaskDetected = await isFlask();
633
+ const snapsList = await installedSnaps();
634
+ const genLayerSnapInstalled = await isGenLayerSnapInstalled();
635
+ return {
636
+ isFlask: flaskDetected,
637
+ installedSnaps: snapsList,
638
+ isGenLayerSnapInstalled: genLayerSnapInstalled
639
+ };
640
+ };
641
+
642
+ // src/wallet/actions.ts
643
+ function walletActions(client) {
644
+ return {
645
+ connect: (network, snapSource) => connect(client, network, snapSource),
646
+ metamaskClient: (snapSource = "npm") => metamaskClient(snapSource)
647
+ };
648
+ }
649
+
544
650
  // src/chains/actions.ts
545
651
  function chainActions(client) {
546
652
  return {
547
653
  initializeConsensusSmartContract: async (forceReset = false) => {
548
- if (_optionalChain([client, 'access', _19 => _19.chain, 'optionalAccess', _20 => _20.id]) !== _chunkXAQMWSP4cjs.simulator.id) {
654
+ if (_optionalChain([client, 'access', _30 => _30.chain, 'optionalAccess', _31 => _31.id]) !== _chunkI6HC44KDcjs.simulator.id) {
549
655
  throw new Error("Client is not connected to the simulator");
550
656
  }
551
- if (!forceReset && _optionalChain([client, 'access', _21 => _21.chain, 'access', _22 => _22.consensusMainContract, 'optionalAccess', _23 => _23.address]) && _optionalChain([client, 'access', _24 => _24.chain, 'access', _25 => _25.consensusMainContract, 'optionalAccess', _26 => _26.abi])) {
657
+ if (!forceReset && _optionalChain([client, 'access', _32 => _32.chain, 'access', _33 => _33.consensusMainContract, 'optionalAccess', _34 => _34.address]) && _optionalChain([client, 'access', _35 => _35.chain, 'access', _36 => _36.consensusMainContract, 'optionalAccess', _37 => _37.abi])) {
552
658
  return;
553
659
  }
554
660
  const contractsResponse = await fetch(client.chain.rpcUrls.default.http[0], {
@@ -573,22 +679,24 @@ function chainActions(client) {
573
679
  }
574
680
 
575
681
  // src/client/client.ts
576
- var createClient = (config = { chain: _chunkXAQMWSP4cjs.simulator }) => {
577
- const chainConfig = config.chain || _chunkXAQMWSP4cjs.simulator;
578
- const rpcUrl = config.endpoint || chainConfig.rpcUrls.default.http[0];
682
+ var createClient = (config = { chain: _chunkI6HC44KDcjs.localnet }) => {
683
+ const chainConfig = config.chain || _chunkI6HC44KDcjs.localnet;
684
+ if (config.endpoint) {
685
+ chainConfig.rpcUrls.default.http = [config.endpoint];
686
+ }
579
687
  const isAddress = typeof config.account !== "object";
580
688
  const customTransport = {
581
689
  async request({ method, params }) {
582
690
  if (method.startsWith("eth_") && isAddress) {
583
691
  try {
584
- return await _optionalChain([window, 'access', _27 => _27.ethereum, 'optionalAccess', _28 => _28.request, 'call', _29 => _29({ method, params })]);
692
+ return await _optionalChain([window, 'access', _38 => _38.ethereum, 'optionalAccess', _39 => _39.request, 'call', _40 => _40({ method, params })]);
585
693
  } catch (err) {
586
694
  console.warn(`Error using window.ethereum for method ${method}:`, err);
587
695
  throw err;
588
696
  }
589
697
  } else {
590
698
  try {
591
- const response = await fetch(rpcUrl, {
699
+ const response = await fetch(chainConfig.rpcUrls.default.http[0], {
592
700
  method: "POST",
593
701
  headers: {
594
702
  "Content-Type": "application/json"
@@ -616,7 +724,7 @@ var createClient = (config = { chain: _chunkXAQMWSP4cjs.simulator }) => {
616
724
  chain: chainConfig,
617
725
  transport: _viem.custom.call(void 0, customTransport),
618
726
  ...config.account ? { account: config.account } : {}
619
- }).extend(_viem.publicActions).extend(_viem.walletActions).extend((client) => accountActions(client)).extend((client) => transactionActions(client)).extend((client) => contractActions(client)).extend((client) => chainActions(client));
727
+ }).extend(_viem.publicActions).extend(_viem.walletActions).extend((client) => accountActions(client)).extend((client) => transactionActions(client)).extend((client) => contractActions(client)).extend((client) => chainActions(client)).extend((client) => walletActions(client));
620
728
  baseClient.initializeConsensusSmartContract().catch((error) => {
621
729
  console.error("Failed to initialize consensus smart contract:", error);
622
730
  });
@@ -646,4 +754,4 @@ var transactions = transactions_exports;
646
754
 
647
755
 
648
756
 
649
- exports.abi = abi_exports; exports.chains = _chunkXAQMWSP4cjs.chains_exports; exports.createAccount = createAccount; exports.createClient = createClient; exports.generatePrivateKey = generatePrivateKey;
757
+ exports.abi = abi_exports; exports.chains = _chunkI6HC44KDcjs.chains_exports; exports.createAccount = createAccount; exports.createClient = createClient; exports.generatePrivateKey = generatePrivateKey;
package/dist/index.d.cts CHANGED
@@ -1,11 +1,11 @@
1
1
  import * as viem from 'viem';
2
2
  import { Account, Address } from 'viem';
3
3
  import { S as SimulatorChain } from './chains-C5PI_Nr_.cjs';
4
- import { G as GenLayerClient, C as CalldataEncodable, T as TransactionDataElement } from './index-FMf4Unm0.cjs';
4
+ import { G as GenLayerClient, C as CalldataEncodable, T as TransactionDataElement } from './index-DJTO3-o3.cjs';
5
5
  import * as abitype from 'abitype';
6
6
  import * as viem__types_experimental_eip7702_types_authorization from 'viem/_types/experimental/eip7702/types/authorization';
7
7
  import * as viem_accounts from 'viem/accounts';
8
- export { i as chains } from './index-CHQn8ZME.cjs';
8
+ export { i as chains } from './index-B8E0qiOq.cjs';
9
9
 
10
10
  interface ClientConfig {
11
11
  chain?: {
package/dist/index.d.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  import * as viem from 'viem';
2
2
  import { Account, Address } from 'viem';
3
3
  import { S as SimulatorChain } from './chains-C5PI_Nr_.js';
4
- import { G as GenLayerClient, C as CalldataEncodable, T as TransactionDataElement } from './index-vnyqXaRU.js';
4
+ import { G as GenLayerClient, C as CalldataEncodable, T as TransactionDataElement } from './index-CpcNUbXb.js';
5
5
  import * as abitype from 'abitype';
6
6
  import * as viem__types_experimental_eip7702_types_authorization from 'viem/_types/experimental/eip7702/types/authorization';
7
7
  import * as viem_accounts from 'viem/accounts';
8
- export { i as chains } from './index-CioK5j0r.js';
8
+ export { i as chains } from './index-ZoW0HQ_m.js';
9
9
 
10
10
  interface ClientConfig {
11
11
  chain?: {
package/dist/index.js CHANGED
@@ -1,23 +1,24 @@
1
1
  import {
2
2
  chains_exports,
3
+ localnet,
3
4
  simulator
4
- } from "./chunk-O3T2C57T.js";
5
+ } from "./chunk-WEXFFND6.js";
5
6
  import {
6
7
  CalldataAddress
7
- } from "./chunk-2EJVFGKU.js";
8
+ } from "./chunk-K72OSU5N.js";
8
9
  import {
9
10
  __export
10
11
  } from "./chunk-MLKGABMK.js";
11
12
 
12
13
  // src/client/client.ts
13
- import { createClient as createViemClient, publicActions, custom, walletActions } from "viem";
14
+ import { createClient as createViemClient, publicActions, custom, walletActions as walletActions2 } from "viem";
14
15
 
15
16
  // src/accounts/actions.ts
16
17
  function accountActions(client) {
17
18
  return {
18
19
  fundAccount: async ({ address, amount }) => {
19
- if (client.chain?.id !== simulator.id) {
20
- throw new Error("Client is not connected to the simulator");
20
+ if (client.chain?.id !== localnet.id) {
21
+ throw new Error("Client is not connected to the localnet");
21
22
  }
22
23
  return client.request({
23
24
  method: "sim_fundAccount",
@@ -541,6 +542,111 @@ var transactionActions = (client) => ({
541
542
  }
542
543
  });
543
544
 
545
+ // src/config/snapID.ts
546
+ var snapID = {
547
+ local: "local:http://localhost:8081",
548
+ npm: "npm:genlayer-wallet-plugin"
549
+ };
550
+
551
+ // src/wallet/connect.ts
552
+ var networks = {
553
+ localnet
554
+ };
555
+ var connect = async (client, network = "localnet", snapSource = "npm") => {
556
+ if (!window.ethereum) {
557
+ throw new Error("MetaMask is not installed.");
558
+ }
559
+ if (network === "testnet" || network === "mainnet") {
560
+ throw new Error(`${network} is not available yet. Please use localnet.`);
561
+ }
562
+ const selectedNetwork = networks[network];
563
+ if (!selectedNetwork) {
564
+ throw new Error(`Network configuration for '${network}' is not available.`);
565
+ }
566
+ const chainIdHex = `0x${selectedNetwork.id.toString(16)}`;
567
+ const chainParams = {
568
+ chainId: chainIdHex,
569
+ chainName: selectedNetwork.name,
570
+ rpcUrls: selectedNetwork.rpcUrls.default.http,
571
+ nativeCurrency: selectedNetwork.nativeCurrency,
572
+ blockExplorerUrls: [selectedNetwork.blockExplorers?.default.url]
573
+ };
574
+ const currentChainId = await window.ethereum.request({ method: "eth_chainId" });
575
+ if (currentChainId !== chainIdHex) {
576
+ await window.ethereum.request({
577
+ method: "wallet_addEthereumChain",
578
+ params: [chainParams]
579
+ });
580
+ await window.ethereum.request({
581
+ method: "wallet_switchEthereumChain",
582
+ params: [{ chainId: chainIdHex }]
583
+ });
584
+ }
585
+ const id = snapSource === "local" ? snapID.local : snapID.npm;
586
+ const installedSnaps = await window.ethereum.request({ method: "wallet_getSnaps" });
587
+ const isGenLayerSnapInstalled = Object.values(installedSnaps).some(
588
+ (snap) => snap.id === id
589
+ );
590
+ if (!isGenLayerSnapInstalled) {
591
+ await window.ethereum.request({
592
+ method: "wallet_requestSnaps",
593
+ params: {
594
+ [id]: {}
595
+ }
596
+ });
597
+ }
598
+ client.chain = selectedNetwork;
599
+ };
600
+
601
+ // src/wallet/metamaskClient.ts
602
+ var metamaskClient = async (snapSource = "npm") => {
603
+ if (typeof window === "undefined" || !window.ethereum) {
604
+ throw new Error("MetaMask is not installed.");
605
+ }
606
+ const isFlask = async () => {
607
+ try {
608
+ const clientVersion = await window.ethereum?.request({
609
+ method: "web3_clientVersion"
610
+ });
611
+ return clientVersion?.includes("flask");
612
+ } catch (error) {
613
+ console.error("Error detecting Flask:", error);
614
+ return false;
615
+ }
616
+ };
617
+ const installedSnaps = async () => {
618
+ try {
619
+ return await window.ethereum?.request({
620
+ method: "wallet_getSnaps"
621
+ });
622
+ } catch (error) {
623
+ console.error("Error getting installed snaps:", error);
624
+ return {};
625
+ }
626
+ };
627
+ const isGenLayerSnapInstalled = async () => {
628
+ const id = snapSource === "local" ? snapID.local : snapID.npm;
629
+ const snaps = await installedSnaps();
630
+ return Object.values(snaps).some((snap) => snap.id === id);
631
+ };
632
+ const flaskDetected = await isFlask();
633
+ const snapsList = await installedSnaps();
634
+ const genLayerSnapInstalled = await isGenLayerSnapInstalled();
635
+ return {
636
+ isFlask: flaskDetected,
637
+ installedSnaps: snapsList,
638
+ isGenLayerSnapInstalled: genLayerSnapInstalled
639
+ };
640
+ };
641
+
642
+ // src/wallet/actions.ts
643
+ function walletActions(client) {
644
+ return {
645
+ connect: (network, snapSource) => connect(client, network, snapSource),
646
+ metamaskClient: (snapSource = "npm") => metamaskClient(snapSource)
647
+ };
648
+ }
649
+
544
650
  // src/chains/actions.ts
545
651
  function chainActions(client) {
546
652
  return {
@@ -573,9 +679,11 @@ function chainActions(client) {
573
679
  }
574
680
 
575
681
  // src/client/client.ts
576
- var createClient = (config = { chain: simulator }) => {
577
- const chainConfig = config.chain || simulator;
578
- const rpcUrl = config.endpoint || chainConfig.rpcUrls.default.http[0];
682
+ var createClient = (config = { chain: localnet }) => {
683
+ const chainConfig = config.chain || localnet;
684
+ if (config.endpoint) {
685
+ chainConfig.rpcUrls.default.http = [config.endpoint];
686
+ }
579
687
  const isAddress = typeof config.account !== "object";
580
688
  const customTransport = {
581
689
  async request({ method, params }) {
@@ -588,7 +696,7 @@ var createClient = (config = { chain: simulator }) => {
588
696
  }
589
697
  } else {
590
698
  try {
591
- const response = await fetch(rpcUrl, {
699
+ const response = await fetch(chainConfig.rpcUrls.default.http[0], {
592
700
  method: "POST",
593
701
  headers: {
594
702
  "Content-Type": "application/json"
@@ -616,7 +724,7 @@ var createClient = (config = { chain: simulator }) => {
616
724
  chain: chainConfig,
617
725
  transport: custom(customTransport),
618
726
  ...config.account ? { account: config.account } : {}
619
- }).extend(publicActions).extend(walletActions).extend((client) => accountActions(client)).extend((client) => transactionActions(client)).extend((client) => contractActions(client)).extend((client) => chainActions(client));
727
+ }).extend(publicActions).extend(walletActions2).extend((client) => accountActions(client)).extend((client) => transactionActions(client)).extend((client) => contractActions(client)).extend((client) => chainActions(client)).extend((client) => walletActions(client));
620
728
  baseClient.initializeConsensusSmartContract().catch((error) => {
621
729
  console.error("Failed to initialize consensus smart contract:", error);
622
730
  });
@@ -1,9 +1,9 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
2
 
3
3
 
4
- var _chunk52HYC24Lcjs = require('../chunk-52HYC24L.cjs');
4
+ var _chunkYDFRDDP5cjs = require('../chunk-YDFRDDP5.cjs');
5
5
  require('../chunk-75ZPJI57.cjs');
6
6
 
7
7
 
8
8
 
9
- exports.CalldataAddress = _chunk52HYC24Lcjs.CalldataAddress; exports.TransactionStatus = _chunk52HYC24Lcjs.TransactionStatus;
9
+ exports.CalldataAddress = _chunkYDFRDDP5cjs.CalldataAddress; exports.TransactionStatus = _chunkYDFRDDP5cjs.TransactionStatus;
@@ -1,3 +1,3 @@
1
- export { A as Address, a as CalldataAddress, C as CalldataEncodable, f as ContractMethod, e as ContractMethodBase, c as ContractParamsArraySchemaElement, d as ContractParamsSchema, g as ContractSchema, G as GenLayerClient, b as GenLayerMethod, j as GenLayerTransaction, M as MethodDescription, k as TransactionDataElement, h as TransactionHash, i as TransactionStatus } from '../index-FMf4Unm0.cjs';
1
+ export { A as Address, a as CalldataAddress, C as CalldataEncodable, f as ContractMethod, e as ContractMethodBase, c as ContractParamsArraySchemaElement, d as ContractParamsSchema, g as ContractSchema, G as GenLayerClient, b as GenLayerMethod, j as GenLayerTransaction, M as MethodDescription, N as Network, S as SnapSource, k as TransactionDataElement, h as TransactionHash, i as TransactionStatus } from '../index-DJTO3-o3.cjs';
2
2
  export { S as SimulatorChain } from '../chains-C5PI_Nr_.cjs';
3
3
  export { Account } from 'viem';
@@ -1,3 +1,3 @@
1
- export { A as Address, a as CalldataAddress, C as CalldataEncodable, f as ContractMethod, e as ContractMethodBase, c as ContractParamsArraySchemaElement, d as ContractParamsSchema, g as ContractSchema, G as GenLayerClient, b as GenLayerMethod, j as GenLayerTransaction, M as MethodDescription, k as TransactionDataElement, h as TransactionHash, i as TransactionStatus } from '../index-vnyqXaRU.js';
1
+ export { A as Address, a as CalldataAddress, C as CalldataEncodable, f as ContractMethod, e as ContractMethodBase, c as ContractParamsArraySchemaElement, d as ContractParamsSchema, g as ContractSchema, G as GenLayerClient, b as GenLayerMethod, j as GenLayerTransaction, M as MethodDescription, N as Network, S as SnapSource, k as TransactionDataElement, h as TransactionHash, i as TransactionStatus } from '../index-CpcNUbXb.js';
2
2
  export { S as SimulatorChain } from '../chains-C5PI_Nr_.js';
3
3
  export { Account } from 'viem';
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  CalldataAddress,
3
3
  TransactionStatus
4
- } from "../chunk-2EJVFGKU.js";
4
+ } from "../chunk-K72OSU5N.js";
5
5
  import "../chunk-MLKGABMK.js";
6
6
  export {
7
7
  CalldataAddress,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "genlayer-js",
3
3
  "type": "module",
4
- "version": "0.6.3",
4
+ "version": "0.7.0",
5
5
  "description": "GenLayer JavaScript SDK",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -1,11 +1,11 @@
1
1
  import {GenLayerClient, TransactionHash, SimulatorChain} from "../types";
2
- import {simulator} from "../chains";
2
+ import {localnet} from "../chains";
3
3
 
4
4
  export function accountActions(client: GenLayerClient<SimulatorChain>) {
5
5
  return {
6
6
  fundAccount: async ({address, amount}: {address: string; amount: number}): Promise<TransactionHash> => {
7
- if (client.chain?.id !== simulator.id) {
8
- throw new Error("Client is not connected to the simulator");
7
+ if (client.chain?.id !== localnet.id) {
8
+ throw new Error("Client is not connected to the localnet");
9
9
  }
10
10
 
11
11
  return client.request({
@@ -1,2 +1,3 @@
1
1
  // src/chains/index.ts
2
+ export {localnet} from "./localnet";
2
3
  export {simulator} from "./simulator";
@@ -0,0 +1,30 @@
1
+ import {defineChain} from "viem";
2
+ import {SimulatorChain} from "@/types";
3
+
4
+ // chains/localnet.ts
5
+ const SIMULATOR_JSON_RPC_URL = "http://127.0.0.1:4000/api";
6
+
7
+ export const localnet: SimulatorChain = defineChain({
8
+ id: 61_999,
9
+ name: "Genlayer Localnet",
10
+ rpcUrls: {
11
+ default: {
12
+ http: [SIMULATOR_JSON_RPC_URL],
13
+ },
14
+ },
15
+ nativeCurrency: {
16
+ name: "GEN Token",
17
+ symbol: "GEN",
18
+ decimals: 18,
19
+ },
20
+ blockExplorers: {
21
+ default: {
22
+ name: "GenLayer Explorer",
23
+ url: SIMULATOR_JSON_RPC_URL,
24
+ },
25
+ },
26
+ testnet: true,
27
+ consensusMainContract: null,
28
+ defaultNumberOfInitialValidators: 5,
29
+ defaultConsensusMaxRotations: 3,
30
+ });
@@ -1,10 +1,11 @@
1
1
  import {Account, createClient as createViemClient, publicActions, custom, Address, walletActions} from "viem";
2
- import {simulator} from "../chains/simulator";
3
2
  import {accountActions} from "../accounts/actions";
4
3
  import {contractActions, overrideContractActions} from "../contracts/actions";
5
4
  import {transactionActions} from "../transactions/actions";
5
+ import {walletActions as genlayerWalletActions} from "../wallet/actions";
6
6
  import {GenLayerClient, SimulatorChain} from "@/types";
7
7
  import {chainActions} from "@/chains/actions";
8
+ import {localnet} from "@/chains";
8
9
 
9
10
  // Define the configuration interface for the client
10
11
  interface ClientConfig {
@@ -19,9 +20,11 @@ interface ClientConfig {
19
20
  account?: Account | Address;
20
21
  }
21
22
 
22
- export const createClient = (config: ClientConfig = {chain: simulator}) => {
23
- const chainConfig = config.chain || simulator;
24
- const rpcUrl = config.endpoint || chainConfig.rpcUrls.default.http[0];
23
+ export const createClient = (config: ClientConfig = {chain: localnet}) => {
24
+ const chainConfig = config.chain || localnet;
25
+ if (config.endpoint) {
26
+ chainConfig.rpcUrls.default.http = [config.endpoint];
27
+ }
25
28
  const isAddress = typeof config.account !== "object";
26
29
 
27
30
  const customTransport = {
@@ -35,7 +38,7 @@ export const createClient = (config: ClientConfig = {chain: simulator}) => {
35
38
  }
36
39
  } else {
37
40
  try {
38
- const response = await fetch(rpcUrl, {
41
+ const response = await fetch(chainConfig.rpcUrls.default.http[0], {
39
42
  method: "POST",
40
43
  headers: {
41
44
  "Content-Type": "application/json",
@@ -73,7 +76,8 @@ export const createClient = (config: ClientConfig = {chain: simulator}) => {
73
76
  .extend(client => accountActions(client as unknown as GenLayerClient<SimulatorChain>))
74
77
  .extend(client => transactionActions(client as unknown as GenLayerClient<SimulatorChain>))
75
78
  .extend(client => contractActions(client as unknown as GenLayerClient<SimulatorChain>))
76
- .extend(client => chainActions(client as unknown as GenLayerClient<SimulatorChain>));
79
+ .extend(client => chainActions(client as unknown as GenLayerClient<SimulatorChain>))
80
+ .extend((client) => genlayerWalletActions(client as unknown as GenLayerClient<SimulatorChain>));
77
81
 
78
82
  // Initialize in the background
79
83
  baseClient.initializeConsensusSmartContract().catch(error => {
@@ -0,0 +1,4 @@
1
+ export const snapID = {
2
+ local: 'local:http://localhost:8081',
3
+ npm: 'npm:genlayer-wallet-plugin'
4
+ }
package/src/global.d.ts CHANGED
@@ -2,6 +2,6 @@
2
2
  interface Window {
3
3
  ethereum?: {
4
4
  isMetaMask?: boolean;
5
- request: (args: { method: string; params?: unknown[] }) => Promise<unknown>;
5
+ request: any
6
6
  };
7
7
  }
@@ -4,6 +4,9 @@ import {SimulatorChain} from "./chains";
4
4
  import {Address, Account} from "./accounts";
5
5
  import {CalldataEncodable} from "./calldata";
6
6
  import {ContractSchema} from "./contracts";
7
+ import {Network} from "./network";
8
+ import {SnapSource} from "@/types/snapSource";
9
+ import {MetaMaskClientResult} from "@/types/metamaskClientResult";
7
10
 
8
11
  export type GenLayerMethod =
9
12
  | {method: "sim_fundAccount"; params: [address: string, amount: number]}
@@ -71,4 +74,6 @@ export type GenLayerClient<TSimulatorChain extends SimulatorChain> = Omit<
71
74
  getContractSchema: (address: string) => Promise<ContractSchema>;
72
75
  getContractSchemaForCode: (contractCode: string | Uint8Array) => Promise<ContractSchema>;
73
76
  initializeConsensusSmartContract: (forceReset?: boolean) => Promise<void>;
77
+ connect: (network?: Network, snapSource?: SnapSource) => Promise<void>;
78
+ metamaskClient: (snapSource?: SnapSource) => Promise<MetaMaskClientResult>;
74
79
  };
@@ -4,3 +4,5 @@ export * from "./chains";
4
4
  export * from "./clients";
5
5
  export * from "./contracts";
6
6
  export * from "./transactions";
7
+ export * from "./network";
8
+ export * from "./snapSource";
@@ -0,0 +1,5 @@
1
+ export type MetaMaskClientResult = {
2
+ isFlask: boolean;
3
+ installedSnaps: Record<string, any>;
4
+ isGenLayerSnapInstalled: boolean;
5
+ };
@@ -0,0 +1 @@
1
+ export type Network = 'localnet' | 'testnet' | 'mainnet';
@@ -0,0 +1 @@
1
+ export type SnapSource = 'npm' | 'local';
@@ -0,0 +1,10 @@
1
+ import { connect } from "./connect";
2
+ import {GenLayerClient, SimulatorChain, Network, SnapSource} from "@/types";
3
+ import { metamaskClient } from "@/wallet/metamaskClient";
4
+
5
+ export function walletActions(client: GenLayerClient<SimulatorChain>) {
6
+ return {
7
+ connect: (network: Network, snapSource: SnapSource) => connect(client, network, snapSource),
8
+ metamaskClient: (snapSource: SnapSource = "npm") => metamaskClient(snapSource),
9
+ };
10
+ }
@@ -0,0 +1,65 @@
1
+ import { localnet } from "@/chains/localnet";
2
+ import { GenLayerClient, SimulatorChain } from "@/types";
3
+ import { Network } from "@/types/network";
4
+ import { SnapSource } from "@/types/snapSource";
5
+ import { snapID } from "@/config/snapID";
6
+
7
+ const networks = {
8
+ localnet,
9
+ };
10
+
11
+ export const connect = async (
12
+ client: GenLayerClient<SimulatorChain>,
13
+ network: Network = "localnet",
14
+ snapSource: SnapSource = 'npm'
15
+ ): Promise<void> => {
16
+ if (!window.ethereum) {
17
+ throw new Error("MetaMask is not installed.");
18
+ }
19
+ if (network === "testnet" || network === "mainnet") {
20
+ throw new Error(`${network} is not available yet. Please use localnet.`);
21
+ }
22
+
23
+ const selectedNetwork = networks[network];
24
+ if (!selectedNetwork) {
25
+ throw new Error(`Network configuration for '${network}' is not available.`);
26
+ }
27
+
28
+ const chainIdHex = `0x${selectedNetwork.id.toString(16)}`;
29
+ const chainParams = {
30
+ chainId: chainIdHex,
31
+ chainName: selectedNetwork.name,
32
+ rpcUrls: selectedNetwork.rpcUrls.default.http,
33
+ nativeCurrency: selectedNetwork.nativeCurrency,
34
+ blockExplorerUrls: [selectedNetwork.blockExplorers?.default.url],
35
+ };
36
+
37
+ const currentChainId = await window.ethereum.request({ method: "eth_chainId" });
38
+ if (currentChainId !== chainIdHex) {
39
+ await window.ethereum.request({
40
+ method: "wallet_addEthereumChain",
41
+ params: [chainParams],
42
+ });
43
+ await window.ethereum.request({
44
+ method: "wallet_switchEthereumChain",
45
+ params: [{ chainId: chainIdHex }],
46
+ });
47
+ }
48
+
49
+ const id = snapSource === 'local' ? snapID.local : snapID.npm;
50
+ const installedSnaps: any = await window.ethereum.request({ method: "wallet_getSnaps" });
51
+ const isGenLayerSnapInstalled = Object.values(installedSnaps).some(
52
+ (snap: any) => snap.id === id
53
+ );
54
+
55
+ if (!isGenLayerSnapInstalled) {
56
+ await window.ethereum.request({
57
+ method: "wallet_requestSnaps",
58
+ params: {
59
+ [id]: {},
60
+ },
61
+ });
62
+ }
63
+
64
+ client.chain = selectedNetwork;
65
+ };
@@ -0,0 +1,50 @@
1
+ import { snapID } from "@/config/snapID";
2
+ import { SnapSource } from "@/types/snapSource";
3
+ import { MetaMaskClientResult } from "@/types/metamaskClientResult";
4
+
5
+ export const metamaskClient = async (snapSource: SnapSource = "npm") => {
6
+ if (typeof window === "undefined" || !window.ethereum) {
7
+ throw new Error("MetaMask is not installed.");
8
+ }
9
+
10
+ const isFlask = async (): Promise<boolean> => {
11
+ try {
12
+ const clientVersion = await window.ethereum?.request({
13
+ method: "web3_clientVersion",
14
+ });
15
+
16
+ return (clientVersion as string)?.includes("flask");
17
+ } catch (error) {
18
+ console.error("Error detecting Flask:", error);
19
+ return false;
20
+ }
21
+ };
22
+
23
+ const installedSnaps = async (): Promise<Record<string, any>> => {
24
+ try {
25
+ return (await window.ethereum?.request({
26
+ method: "wallet_getSnaps",
27
+ })) as Record<string, any>;
28
+ } catch (error) {
29
+ console.error("Error getting installed snaps:", error);
30
+ return {};
31
+ }
32
+ };
33
+
34
+ const isGenLayerSnapInstalled = async (): Promise<boolean> => {
35
+ const id = snapSource === "local" ? snapID.local : snapID.npm;
36
+ const snaps = await installedSnaps();
37
+
38
+ return Object.values(snaps).some((snap: any) => snap.id === id);
39
+ };
40
+
41
+ const flaskDetected = await isFlask();
42
+ const snapsList = await installedSnaps();
43
+ const genLayerSnapInstalled = await isGenLayerSnapInstalled();
44
+
45
+ return {
46
+ isFlask: flaskDetected,
47
+ installedSnaps: snapsList,
48
+ isGenLayerSnapInstalled: genLayerSnapInstalled,
49
+ } as MetaMaskClientResult;
50
+ };
@@ -1,11 +1,11 @@
1
1
  import {createClient} from "../src/client/client";
2
- import {simulator} from "../src/chains/simulator";
2
+ import {localnet} from "@/chains/localnet";
3
3
  import {createAccount, generatePrivateKey} from "../src/accounts/account";
4
4
  import {TransactionHash, TransactionStatus} from "../src/types/transactions";
5
5
 
6
6
  test("type checks", () => {
7
7
  const client = createClient({
8
- chain: simulator,
8
+ chain: localnet,
9
9
  account: createAccount(generatePrivateKey()),
10
10
  });
11
11
 
@@ -1,16 +1,16 @@
1
1
  // tests/client.test.ts
2
2
  import {createClient} from "../src/client/client";
3
- import {simulator} from "../src/chains/simulator";
3
+ import {localnet} from "@/chains/localnet";
4
4
  import {Address} from "../src/types/accounts";
5
5
  import {createAccount, generatePrivateKey} from "../src/accounts/account";
6
6
  import {vi} from "vitest";
7
7
  import {TransactionStatus} from "../src/types/transactions";
8
8
 
9
9
  describe("Client Creation", () => {
10
- it("should create a client for the simulator", () => {
11
- const client = createClient({chain: simulator});
10
+ it("should create a client for the localnet", () => {
11
+ const client = createClient({chain: localnet});
12
12
  expect(client).toBeDefined();
13
- expect(client.chain).toBe(simulator);
13
+ expect(client.chain).toBe(localnet);
14
14
  });
15
15
  });
16
16
 
@@ -18,7 +18,7 @@ describe("Client Overrides", () => {
18
18
  it("should default to client account if no account is provided", async () => {
19
19
  const account = createAccount(generatePrivateKey());
20
20
  const client = createClient({
21
- chain: simulator,
21
+ chain: localnet,
22
22
  account: account,
23
23
  });
24
24
 
@@ -49,7 +49,7 @@ describe("Client Overrides", () => {
49
49
  it("should override client account if account is provided", async () => {
50
50
  const account = createAccount(generatePrivateKey());
51
51
  const client = createClient({
52
- chain: simulator,
52
+ chain: localnet,
53
53
  account,
54
54
  });
55
55
 
@@ -82,7 +82,7 @@ describe("Client Overrides", () => {
82
82
  it("should override client account if address is provided", async () => {
83
83
  const account = "0x65e03a3e916CF1dC92d3C8E8186a89CfAB0D2bc2";
84
84
  const client = createClient({
85
- chain: simulator,
85
+ chain: localnet,
86
86
  account,
87
87
  });
88
88
 
@@ -1,10 +0,0 @@
1
- import { S as SimulatorChain } from './chains-C5PI_Nr_.cjs';
2
-
3
- declare const simulator: SimulatorChain;
4
-
5
- declare const index_simulator: typeof simulator;
6
- declare namespace index {
7
- export { index_simulator as simulator };
8
- }
9
-
10
- export { index as i, simulator as s };
@@ -1,10 +0,0 @@
1
- import { S as SimulatorChain } from './chains-C5PI_Nr_.js';
2
-
3
- declare const simulator: SimulatorChain;
4
-
5
- declare const index_simulator: typeof simulator;
6
- declare namespace index {
7
- export { index_simulator as simulator };
8
- }
9
-
10
- export { index as i, simulator as s };
File without changes
File without changes