genlayer-js 0.0.1

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/.eslintignore ADDED
@@ -0,0 +1,2 @@
1
+ node_modules
2
+ dist
package/.eslintrc.js ADDED
@@ -0,0 +1,58 @@
1
+ module.exports = {
2
+ root: true,
3
+ env: {
4
+ es6: true,
5
+ node: true,
6
+ jest: true,
7
+ },
8
+ extends: ["eslint:recommended", "prettier", "plugin:import/typescript"],
9
+ parser: "@typescript-eslint/parser",
10
+ plugins: ["@typescript-eslint", "import"],
11
+ overrides: [
12
+ {
13
+ files: "**/*.ts",
14
+ parserOptions: {
15
+ project: ["./tsconfig.json"],
16
+ sourceType: "module",
17
+ },
18
+ extends: [
19
+ "plugin:import/errors",
20
+ "plugin:import/warnings",
21
+ "plugin:import/typescript",
22
+ "plugin:@typescript-eslint/recommended",
23
+ ],
24
+ rules: {
25
+ "import/namespace": "off",
26
+ "@typescript-eslint/no-empty-function": "off",
27
+ "@typescript-eslint/no-empty-interface": "off",
28
+ "no-constant-condition": "off",
29
+ "@typescript-eslint/no-explicit-any": "off",
30
+ "prefer-const": "off",
31
+ "@typescript-eslint/no-non-null-assertion": "off",
32
+ "@typescript-eslint/ban-ts-ignore": "off",
33
+ "@typescript-eslint/no-loss-of-precision": "off",
34
+ "@typescript-eslint/ban-types": "off",
35
+ "@typescript-eslint/ban-ts-comment": "off",
36
+ "@typescript-eslint/no-non-null-asserted-optional-chain": "off",
37
+ "@typescript-eslint/no-var-requires": "off",
38
+ "import/export": "off",
39
+ "no-fallthrough": "off",
40
+ "@typescript-eslint/explicit-module-boundary-types": "off",
41
+ "@typescript-eslint/no-floating-promises": ["error"],
42
+ "@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }],
43
+ },
44
+ },
45
+ ],
46
+ ignorePatterns: [
47
+ "**/dist/**/*", // Ignore built files.
48
+ "esbuild.config.js",
49
+ "jest.config.js",
50
+ "Config.js",
51
+ "commitLint.config.ts",
52
+ ],
53
+ settings: {
54
+ "import/resolver": {
55
+ typescript: {},
56
+ },
57
+ },
58
+ };
@@ -0,0 +1,43 @@
1
+ <!-- This is a TEMPLATE, modify it to fit your needs. -->
2
+
3
+ Fixes #issue-number-here
4
+
5
+ # What
6
+
7
+ <!-- Describe the changes you made. -->
8
+
9
+ - changed thing a for b
10
+ - also did this other unrelated thing in my path
11
+
12
+ # Why
13
+
14
+ <!-- Why are you making these changes? This should be related to the issue created, and the value we are adding with this PR -->
15
+
16
+ - to fix a bug
17
+ - to add more value to the user
18
+
19
+ # Testing done
20
+
21
+ <!-- Describe the tests you ran to verify your changes. -->
22
+
23
+ - tested the new feature
24
+ - tested the bug fix
25
+
26
+ # Decisions made
27
+
28
+ <!-- Describe any decisions made during the implementation of this PR. This should in general be in the code, but sometimes they are more related to the issue. For example: decisions on PR workflow -->
29
+
30
+ # Checks
31
+
32
+ - [ ] I have tested this code
33
+ - [ ] I have reviewed my own PR
34
+ - [ ] I have created an issue for this PR
35
+ - [ ] I have set a descriptive PR title compliant with [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/)
36
+
37
+ # Reviewing tips
38
+
39
+ <!-- What can you tell the reviewer to make the review easier? -->
40
+
41
+ # User facing release notes
42
+
43
+ <!-- What should the user know about this change? Think of it going into public forums for end users to read -->
@@ -0,0 +1,41 @@
1
+ name: Release & Publish Package to NPM
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ push:
6
+ branches:
7
+ - main
8
+
9
+ jobs:
10
+ release:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - name: Get CI Bot Token
14
+ uses: tibdex/github-app-token@v1
15
+ id: ci_bot_token
16
+ with:
17
+ app_id: ${{ secrets.CI_BOT_APP_ID }}
18
+ private_key: ${{ secrets.CI_BOT_SECRET }}
19
+
20
+ - name: Checkout source code
21
+ uses: actions/checkout@v4
22
+ with:
23
+ token: ${{ steps.ci_bot_token.outputs.token }}
24
+ - name: Setup Node.js
25
+ uses: actions/setup-node@v2
26
+ with:
27
+ node-version: "18"
28
+ - name: Install the dependencies
29
+ run: npm ci
30
+ - name: Initialize Git User
31
+ run: |
32
+ git config --global user.email "github-actions[bot]@genlayer.com"
33
+ git config --global user.name "github-actions[bot]"
34
+ - name: Initialize the NPM configuration
35
+ run: npm config set //registry.npmjs.org/:_authToken=$NPM_AUTH_TOKEN
36
+ env:
37
+ NPM_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
38
+ - run: npm run release
39
+ env:
40
+ GITHUB_TOKEN: ${{ steps.ci_bot_token.outputs.token }}
41
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
@@ -0,0 +1,19 @@
1
+ # Node artifact files
2
+ node_modules/
3
+ dist/
4
+ package-lock.json
5
+ yarn.lock
6
+ pnpm-lock.yaml
7
+
8
+ # Log files
9
+ *.log
10
+
11
+ # Generated by MacOS
12
+ .DS_Store
13
+
14
+ # Generated by Windows
15
+ Thumbs.db
16
+
17
+ # aws
18
+ .aws-sam
19
+ .sam
package/.prettierrc ADDED
@@ -0,0 +1,12 @@
1
+ {
2
+ "tabWidth": 2,
3
+ "useTabs": false,
4
+ "semi": true,
5
+ "singleQuote": false,
6
+ "jsxSingleQuote": false,
7
+ "trailingComma": "all",
8
+ "bracketSpacing": false,
9
+ "bracketSameLine": false,
10
+ "arrowParens": "avoid",
11
+ "printWidth": 110
12
+ }
@@ -0,0 +1,64 @@
1
+ {
2
+ "git": {
3
+ "commitMessage": "Release v${version} [skip ci]",
4
+ "tagName": "v${version}",
5
+ "requireCleanWorkingDir": false,
6
+ "requireUpstream": false,
7
+ "requireCommits": false,
8
+ "push": true
9
+ },
10
+ "github": {
11
+ "release": true,
12
+ "tokenRef": "GITHUB_TOKEN"
13
+ },
14
+ "npm": {
15
+ "publish": true
16
+ },
17
+ "plugins": {
18
+ "@release-it/conventional-changelog": {
19
+ "preset": "conventionalcommits",
20
+ "infile": "CHANGELOG.md",
21
+ "types": [
22
+ {
23
+ "type": "feat",
24
+ "section": "Features"
25
+ },
26
+ {
27
+ "type": "fix",
28
+ "section": "Bug Fixes"
29
+ },
30
+ {
31
+ "type": "chore",
32
+ "section": "Improvement Tasks"
33
+ },
34
+ {
35
+ "type": "ci",
36
+ "section": "Continuous Integration"
37
+ },
38
+ {
39
+ "type": "docs",
40
+ "section": "Documentation"
41
+ },
42
+ {
43
+ "type": "style",
44
+ "section": "Styles"
45
+ },
46
+ {
47
+ "type": "refactor",
48
+ "section": "Refactor Tasks"
49
+ },
50
+ {
51
+ "type": "perf",
52
+ "section": "Performance Improvements"
53
+ },
54
+ {
55
+ "type": "test",
56
+ "section": "Testing"
57
+ }
58
+ ]
59
+ }
60
+ },
61
+ "hooks": {
62
+ "after:bump": "npm run build"
63
+ }
64
+ }
@@ -0,0 +1,87 @@
1
+ # Contributing to GenLayerJS SDK
2
+
3
+ We're thrilled that you're interested in contributing to the GenLayerJS SDK! This document will guide you through the contribution process.
4
+
5
+ ## What is the GenLayerJS SDK?
6
+
7
+ The GenLayerJS SDK is a TypeScript library designed for developers building decentralized applications (Dapps) on the GenLayer protocol. It provides a comprehensive set of tools to interact with the GenLayer network, including client creation, transaction handling, event subscriptions, and more, all while leveraging the power of Viem as the underlying blockchain client.
8
+
9
+ ## How You Can Contribute?
10
+
11
+ Contributions to the GenLayerJS SDK are welcome in several forms:
12
+
13
+ ### Testing the SDK and Providing Feedback
14
+
15
+ Help us make the SDK better by testing and giving feedback:
16
+
17
+ - Start by installing the SDK in your Dapp using the command:
18
+ ```sh
19
+ $ npm install genlayer-js
20
+ ```
21
+ - Try out the SDK features and tell us what you think through our [feedback form](https://docs.google.com/forms/d/1IVNsZwm936kSNCiXmlAP8bgJnbik7Bqaoc3I6UYhr-o/viewform) or on our [Discord Channel](https://discord.gg/8Jm4v89VAu).
22
+ - If you find any issues, please report them on our [GitHub issues page](https://github.com/yeagerai/genlayer-js/issues).
23
+
24
+ ### Sharing New Ideas and Use Cases
25
+
26
+ Have ideas for new features or use cases? We're eager to hear them! But first:
27
+
28
+ - Ensure you have the SDK installed to explore existing use cases.
29
+ - After familiarizing yourself with the SDK, contribute your unique use case and share your ideas in our [Discord channel](https://discord.gg/8Jm4v89VAu).
30
+
31
+ ### Bug fixing and Feature development
32
+
33
+ #### 1. Set yourself up to start coding
34
+
35
+ - **1.1. Pick an issue**: Select one from the project GitHub repository [issue list](https://github.com/yeagerai/genlayer-js/issues) and assign it to yourself.
36
+
37
+ - **1.2. Create a branch**: create the branch that you will work on by using the link provided in the issue details page (right panel at the bottom - section "Development")
38
+
39
+ - **1.3. Setup the SDK locally**: clone the repository and install dependencies
40
+
41
+ ```sh
42
+ $ git clone https://github.com/yeagerai/genlayer-js.git
43
+ $ cd genlayer-js
44
+ $ npm install
45
+ ```
46
+
47
+ - **1.4. Run the SDK in dev mode**: to run the SDK in development mode with hot reload enabled:
48
+
49
+ ```sh
50
+ $ npm run build:watch
51
+ ```
52
+ - **1.5. Link the package locally**: to link the package locally, use the command:
53
+
54
+ ```sh
55
+ $ npm link
56
+ ```
57
+
58
+ This will allow you to use the package in your project without publishing it.
59
+
60
+ - **1.6. Add the package to your project**: to add the package to your project, use the command:
61
+
62
+ ```sh
63
+ $ npm link genlayer-js
64
+ ```
65
+
66
+ #### 2. Submit your solution
67
+
68
+ - **2.1. Prettier Formatter on Save File**: Configure IDE extensions to format your code with [Prettier](https://prettier.io/) before submitting it.
69
+ - **2.2. Code solution**: implement the solution in the code.
70
+ - **2.3. Pull Request**: Submit your changes through a pull request (PR). Fill the entire PR template and set the PR title as a valid conventional commit.
71
+ - **2.4. Check PR and issue linking**: if the issue and the PR are not linked, you can do it manually in the right panel of the Pull Request details page.
72
+ - **2.5. Peer Review**: One or more core contributors will review your PR. They may suggest changes or improvements.
73
+ - **2.6. Approval and Merge**: After approval from the reviewers, you can merge your PR with a squash and merge type of action.
74
+
75
+
76
+ ### Improving Documentation
77
+
78
+ To contribute to our docs, visit our [Documentation Repository](https://github.com/yeagerai/genlayer-docs) to create new issues or contribute to existing issues.
79
+
80
+ ## Community
81
+
82
+ Connect with the GenLayer community to discuss, collaborate, and share insights:
83
+
84
+ - **[Discord Channel](https://discord.gg/8Jm4v89VAu)**: Our primary hub for discussions, support, and announcements.
85
+ - **[Telegram Group](https://t.me/genlayer)**: For more informal chats and quick updates.
86
+
87
+ Your continuous feedback drives better product development. Please engage with us regularly to test, discuss, and improve the GenLayerJS SDK.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024-present YeagerAI LLC
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,99 @@
1
+ # [Your Project Name]
2
+
3
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/license/mit/)
4
+ [![Discord](https://dcbadge.vercel.app/api/server/8Jm4v89VAu?compact=true&style=flat)](https://discord.gg/VpfmXEMN66)
5
+ [![Twitter](https://img.shields.io/twitter/url/https/twitter.com/yeagerai.svg?style=social&label=Follow%20%40GenLayer)](https://x.com/GenLayer)
6
+ [![GitHub star chart](https://img.shields.io/github/stars/yeagerai/genlayer-js?style=social)](https://star-history.com/#yeagerai/genlayer-js)
7
+
8
+ ## 👀 About
9
+
10
+ GenLayerJS SDK is a TypeScript library designed for developers building decentralized applications (Dapps) on the GenLayer protocol. This SDK provides a comprehensive set of tools to interact with the GenLayer network, including client creation, transaction handling, event subscriptions, and more, all while leveraging the power of Viem as the underlying blockchain client.
11
+
12
+ ## Prerequisites
13
+
14
+ Before installing GenLayerJS SDK, ensure you have the following prerequisites installed:
15
+
16
+ - Node.js (>= 16.x)
17
+ - npm (>= 7.x)
18
+
19
+ ## 🛠️ Installation and Usage
20
+
21
+ To install the GenLayerJS SDK, use the following command:
22
+ ```bash
23
+ $ npm install genlayer-js
24
+ ```
25
+ Here’s how to initialize the client and connect to the GenLayer Simulator:
26
+
27
+ ### Reading a Transaction
28
+ ```typescript
29
+ import { simulator } from 'genlayer-js/chains';
30
+ import { createClient } from "genlayer-js";
31
+
32
+ const client = createClient({
33
+ network: simulator,
34
+ });
35
+
36
+ const transaction = await client.getTransaction({ hash: transactionHash })
37
+ ```
38
+
39
+ ### Readding a contract
40
+ ```typescript
41
+ import { simulator } from 'genlayer-js/chains';
42
+ import { createClient, createAccount } from "genlayer-js";
43
+
44
+ const account = createAccount();
45
+ const client = createClient({
46
+ network: simulator,
47
+ account: account, // hoist the account to use it on next calls
48
+ });
49
+
50
+ const result = await client.readContract({
51
+ address: contractAddress,
52
+ functionName: 'get_complete_storage',
53
+ args: []
54
+ })
55
+ ```
56
+
57
+ ### Writing a transaction
58
+ ```typescript
59
+ import { simulator } from 'genlayer-js/chains';
60
+ import { createClient, createAccount } from "genlayer-js";
61
+
62
+ const client = createClient({
63
+ network: simulator,
64
+ });
65
+
66
+ const account = createAccount();
67
+ const transactionHash = await client.writeContract({
68
+ account: account, // using this account for this transaction
69
+ address: contractAddress,
70
+ functionName: 'account',
71
+ args: ['new_storage'],
72
+ value: 0, // value is optional, if you want to send some native token to the contract
73
+ });
74
+
75
+ const receipt = await client.waitForTransactionReceipt({ hash: txHash, status: TransactionStatus.FINALIZED}) //or ACCEPTED
76
+
77
+ ```
78
+ ## 🚀 Key Features
79
+
80
+ * **Client Creation**: Easily create and configure a client to connect to GenLayer’s network.
81
+ * **Transaction Handling**: Send and manage transactions on the GenLayer network.
82
+ * **Wallet Integration***: Seamless integration with MetaMask for managing user accounts.
83
+ * **Gas Estimation***: Estimate gas fees for executing transactions on GenLayer.
84
+
85
+ _* under development_
86
+
87
+ ## 📖 Documentation
88
+
89
+ For detailed information on how to use GenLayerJS SDK, please refer to our [documentation](https://docs.genlayer.io/).
90
+
91
+
92
+
93
+ ## Contributing
94
+
95
+ We welcome contributions to GenLayerJS SDK! Whether it's new features, improved infrastructure, or better documentation, your input is valuable. Please read our [CONTRIBUTING](https://github.com/yeagerai/genlayer-js/blob/main/CONTRIBUTING.md) guide for guidelines on how to submit your contributions.
96
+
97
+ ## License
98
+
99
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "genlayer-js",
3
+ "type": "module",
4
+ "version": "0.0.1",
5
+ "description": "GenLayer JavaScript SDK",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "scripts": {
9
+ "build": "tsup src/index.ts src/chains/index.ts src/types/index.ts --format cjs,esm --dts --splitting --out-dir dist --no-treeshake",
10
+ "build:watch": "tsup src/index.ts src/chains/index.ts src/types/index.ts --format cjs,esm --dts --splitting --out-dir dist --no-treeshake --watch",
11
+ "test": "vitest",
12
+ "test:watch": "vitest --watch",
13
+ "lint": "eslint . --ext .ts",
14
+ "release": "release-it --ci"
15
+ },
16
+ "exports": {
17
+ ".": {
18
+ "import": "./dist/index.js",
19
+ "require": "./dist/index.js"
20
+ },
21
+ "./chains": {
22
+ "import": "./dist/chains/index.js",
23
+ "require": "./dist/chains/index.js"
24
+ },
25
+ "./types": {
26
+ "import": "./dist/types/index.js",
27
+ "require": "./dist/types/index.js"
28
+ }
29
+ },
30
+ "keywords": [],
31
+ "author": "GenLayer",
32
+ "license": "MIT",
33
+ "devDependencies": {
34
+ "@release-it/conventional-changelog": "^8.0.2",
35
+ "@types/jest": "^29.5.13",
36
+ "@types/node": "^22.5.5",
37
+ "@typescript-eslint/eslint-plugin": "^8.5.0",
38
+ "@typescript-eslint/parser": "^8.5.0",
39
+ "cross-env": "^7.0.3",
40
+ "eslint": "^8.57.0",
41
+ "eslint-config-prettier": "^9.1.0",
42
+ "eslint-import-resolver-typescript": "^3.6.3",
43
+ "prettier": "^3.3.3",
44
+ "release-it": "^17.6.0",
45
+ "ts-node": "^10.9.2",
46
+ "tsup": "^8.2.4",
47
+ "typescript": "^5.6.2",
48
+ "vitest": "^2.1.1"
49
+ },
50
+ "dependencies": {
51
+ "eslint-plugin-import": "^2.30.0",
52
+ "viem": "^2.21.7"
53
+ }
54
+ }
@@ -0,0 +1,10 @@
1
+ import {TransactionHash} from "@/types";
2
+ import {Account, Chain, Transport} from "viem";
3
+
4
+ export type IAccountActions<
5
+ transport extends Transport = Transport,
6
+ chain extends Chain | undefined = Chain | undefined,
7
+ account extends Account | undefined = Account | undefined,
8
+ > = {
9
+ fundAccount: ({address, amount}: {address: string; amount: number}) => Promise<TransactionHash>;
10
+ };
@@ -0,0 +1,7 @@
1
+ import {generatePrivateKey, privateKeyToAccount} from "viem/accounts";
2
+
3
+ export const createAccount = () => {
4
+ const privateKey = generatePrivateKey();
5
+ const account = privateKeyToAccount(privateKey);
6
+ return account;
7
+ };
@@ -0,0 +1,22 @@
1
+ import {GenLayerClient, TransactionHash, SimulatorChain} from "@/types";
2
+ import {simulator} from "@/chains";
3
+ import {Account, Transport} from "viem";
4
+
5
+ export function accountActions<
6
+ transport extends Transport = Transport,
7
+ chain extends SimulatorChain | undefined = SimulatorChain | undefined,
8
+ account extends Account | undefined = Account | undefined,
9
+ >(client: GenLayerClient<Transport, SimulatorChain, Account>) {
10
+ return {
11
+ fundAccount: async ({address, amount}: {address: string; amount: number}): Promise<TransactionHash> => {
12
+ if (client.chain?.id !== simulator.id) {
13
+ throw new Error("Client is not connected to the simulator");
14
+ }
15
+
16
+ return client.request({
17
+ method: "sim_fundAccount",
18
+ params: [address, amount],
19
+ }) as Promise<TransactionHash>;
20
+ },
21
+ };
22
+ }
@@ -0,0 +1,2 @@
1
+ // src/chains/index.ts
2
+ export {simulator} from "./simulator";
@@ -0,0 +1,27 @@
1
+ import {defineChain} from "viem";
2
+ import {SimulatorChain} from "@/types";
3
+
4
+ // chains/simulator.ts
5
+ const SIMULATOR_JSON_RPC_URL = "http://127.0.0.1:4000/api";
6
+
7
+ export const simulator: SimulatorChain = defineChain({
8
+ id: 61_999,
9
+ name: "GenLayer Simulator",
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: "http://127.0.0.1:4000/api",
24
+ },
25
+ },
26
+ testnet: true,
27
+ });
@@ -0,0 +1,48 @@
1
+ import {Account, createClient as createViemClient, http, publicActions, Transport} from "viem";
2
+ import {simulator} from "../chains/simulator";
3
+ import {accountActions} from "../accounts/actions";
4
+ import {contractActions, overrideContractActions} from "../contracts/actions";
5
+ import {transactionActions} from "../transactions/actions";
6
+ import {GenLayerClient, SimulatorChain} from "@/types";
7
+ import {createAccount} from "@/accounts/account";
8
+
9
+ // Define the configuration interface for the client
10
+ interface ClientConfig {
11
+ chain?: {
12
+ id: number;
13
+ name: string;
14
+ rpcUrls: {default: {http: readonly string[]}};
15
+ nativeCurrency: {name: string; symbol: string; decimals: number};
16
+ blockExplorers?: {default: {name: string; url: string}};
17
+ };
18
+ endpoint?: string; // Optional: Custom RPC endpoint override
19
+ account?: Account;
20
+ }
21
+
22
+ // Extend Viem client to work with GenLayer-specific chains (simulator, testnet, etc.)
23
+ export const createClient = (config: ClientConfig = {chain: simulator}) => {
24
+ // Determine the RPC URL based on the provided configuration or default to the simulator's RPC UR
25
+ const chainConfig = config.chain || simulator;
26
+ const rpcUrl = config.endpoint || chainConfig.rpcUrls.default.http[0];
27
+
28
+ // Create a Viem client connected to the GenLayer Simulator (or custom chain)
29
+ const baseClient = createViemClient({
30
+ chain: chainConfig,
31
+ transport: http(rpcUrl),
32
+ ...(config.account ? {account: config.account} : {}),
33
+ })
34
+ .extend(publicActions)
35
+ .extend(client => accountActions(client as unknown as GenLayerClient<Transport, SimulatorChain, Account>))
36
+ .extend(client =>
37
+ transactionActions(client as unknown as GenLayerClient<Transport, SimulatorChain, Account>),
38
+ )
39
+ .extend(client =>
40
+ contractActions(client as unknown as GenLayerClient<Transport, SimulatorChain, Account>),
41
+ );
42
+
43
+ const genLayerClient = overrideContractActions(
44
+ baseClient as unknown as GenLayerClient<Transport, SimulatorChain, Account>,
45
+ );
46
+
47
+ return genLayerClient;
48
+ };
@@ -0,0 +1,9 @@
1
+ type TransactionsConfig = {
2
+ waitInterval: number;
3
+ retries: number;
4
+ };
5
+
6
+ export const transactionsConfig: TransactionsConfig = {
7
+ waitInterval: 3000,
8
+ retries: 10,
9
+ };
@@ -0,0 +1,8 @@
1
+ import {ContractSchema} from "@/types";
2
+ import {Address} from "viem";
3
+
4
+ export type IContractActions = {
5
+ getContractSchema: (code: string) => Promise<ContractSchema>;
6
+ getContractSchemaForCode: (address: string) => Promise<ContractSchema>;
7
+ readContract: (args: {address: Address; functionName: string; args: any[]}) => Promise<unknown>;
8
+ };
@@ -0,0 +1,86 @@
1
+ import {toRlp, toHex, Transport, Account, Address} from "viem";
2
+
3
+ import {ContractSchema, SimulatorChain, GenLayerClient} from "@/types";
4
+ import {createAccount} from "@/accounts/account";
5
+
6
+ export const contractActions = (client: GenLayerClient<Transport, SimulatorChain, Account>) => {
7
+ return {
8
+ getContractSchema: async (address: string): Promise<ContractSchema> => {
9
+ const schema = (await client.request({
10
+ method: "gen_getContractSchema",
11
+ params: [address],
12
+ })) as string;
13
+ return schema as unknown as ContractSchema;
14
+ },
15
+ getContractSchemaForCode: async (contractCode: string): Promise<ContractSchema> => {
16
+ const schema = (await client.request({
17
+ method: "gen_getContractSchemaForCode",
18
+ params: [contractCode],
19
+ })) as string;
20
+ return schema as unknown as ContractSchema;
21
+ },
22
+ };
23
+ };
24
+
25
+ export const overrideContractActions = (client: GenLayerClient<Transport, SimulatorChain, Account>) => {
26
+ client.readContract = async (args: {
27
+ account: Account;
28
+ address: Address;
29
+ functionName: string;
30
+ args: any[];
31
+ }): Promise<any> => {
32
+ const {account, address, functionName, args: params} = args;
33
+ const methodParamsAsString = JSON.stringify(params);
34
+ const data = [functionName, methodParamsAsString];
35
+ const encodedData = toRlp(data.map(param => toHex(param)));
36
+
37
+ const requestParams = {
38
+ to: address,
39
+ from: account?.address || client.account?.address,
40
+ data: encodedData,
41
+ };
42
+ const result = await client.request({
43
+ method: "eth_call",
44
+ params: [requestParams, "latest"],
45
+ });
46
+ return result;
47
+ };
48
+
49
+ client.writeContract = async (args: {
50
+ account: Account;
51
+ address: Address;
52
+ functionName: string;
53
+ args: any[];
54
+ value: bigint;
55
+ }): Promise<any> => {
56
+ const {account, address, functionName, args: params, value = 0n} = args;
57
+ const methodParamsAsString = JSON.stringify(params);
58
+ const data = [functionName, methodParamsAsString];
59
+ const encodedData = toRlp(data.map(param => toHex(param)));
60
+
61
+ const senderAccount = account || client.account;
62
+ if (!senderAccount) {
63
+ throw new Error(
64
+ "No account set. Configure the client with an account or pass an account to this function.",
65
+ );
66
+ }
67
+
68
+ if (!senderAccount?.signTransaction) {
69
+ throw new Error("Account does not support signTransaction");
70
+ }
71
+
72
+ const signedTransaction = await senderAccount.signTransaction({
73
+ data: encodedData,
74
+ to: address,
75
+ value,
76
+ type: "legacy",
77
+ });
78
+ const result = await client.request({
79
+ method: "eth_sendRawTransaction",
80
+ params: [signedTransaction],
81
+ });
82
+ return result;
83
+ };
84
+
85
+ return client;
86
+ };
package/src/index.ts ADDED
@@ -0,0 +1,4 @@
1
+ // src/index.ts
2
+ export {createClient} from "./client/client";
3
+ export {createAccount} from "./accounts/account";
4
+ export * as chains from "./chains";
@@ -0,0 +1,20 @@
1
+ import {Account, Chain, Transport} from "viem";
2
+ import {TransactionHash, TransactionStatus, GenLayerTransaction} from "@/types";
3
+
4
+ export type ITransactionActions<
5
+ transport extends Transport = Transport,
6
+ chain extends Chain | undefined = Chain | undefined,
7
+ account extends Account | undefined = Account | undefined,
8
+ > = {
9
+ waitForTransactionReceipt: ({
10
+ hash,
11
+ status,
12
+ interval,
13
+ retries,
14
+ }: {
15
+ hash: TransactionHash;
16
+ status: TransactionStatus;
17
+ interval?: number;
18
+ retries?: number;
19
+ }) => Promise<GenLayerTransaction>;
20
+ };
@@ -0,0 +1,48 @@
1
+ import {GenLayerClient} from "../types/clients";
2
+ import {TransactionHash, TransactionStatus, GenLayerTransaction} from "../types/transactions";
3
+ import {transactionsConfig} from "../config/transactions";
4
+ import {sleep} from "../utils/async";
5
+ import {ITransactionActions} from "./ITransactionActions";
6
+ import {Account, Transport} from "viem";
7
+ import {SimulatorChain} from "@/types";
8
+
9
+ export const transactionActions = (
10
+ client: GenLayerClient<Transport, SimulatorChain, Account>,
11
+ ): ITransactionActions => ({
12
+ waitForTransactionReceipt: async ({
13
+ hash,
14
+ status = TransactionStatus.FINALIZED,
15
+ interval = transactionsConfig.waitInterval,
16
+ retries = transactionsConfig.retries,
17
+ }: {
18
+ hash: TransactionHash;
19
+ status: TransactionStatus;
20
+ interval?: number;
21
+ retries?: number;
22
+ }): Promise<GenLayerTransaction> => {
23
+ const transaction = (await client.getTransaction({hash})) as GenLayerTransaction;
24
+
25
+ if (!transaction) {
26
+ throw new Error("Transaction not found");
27
+ }
28
+
29
+ if (
30
+ transaction.status === status ||
31
+ (status === TransactionStatus.ACCEPTED && transaction.status === TransactionStatus.FINALIZED)
32
+ ) {
33
+ return transaction;
34
+ }
35
+
36
+ if (retries === 0) {
37
+ throw new Error("Transaction status is not " + status);
38
+ }
39
+
40
+ await sleep(interval);
41
+ return transactionActions(client).waitForTransactionReceipt({
42
+ hash,
43
+ status,
44
+ interval,
45
+ retries: retries - 1,
46
+ });
47
+ },
48
+ });
@@ -0,0 +1 @@
1
+ export type Address = `0x${string}` & {length: 42};
@@ -0,0 +1,3 @@
1
+ import {Chain} from "viem";
2
+
3
+ export interface SimulatorChain extends Chain {}
@@ -0,0 +1,38 @@
1
+ import {Account, Transport, Client} from "viem";
2
+ import {GenLayerTransaction, TransactionHash} from "./transactions";
3
+ import {SimulatorChain} from "./chains";
4
+ import {Address} from "./accounts";
5
+
6
+ export type GenLayerMethod =
7
+ | {method: "sim_fundAccount"; params: [address: string, amount: number]}
8
+ | {method: "eth_getTransactionByHash"; params: [hash: TransactionHash]}
9
+ | {method: "eth_call"; params: [requestParams: any, blockNumberOrHash: string]}
10
+ | {method: "eth_sedRawTransaction"; params: [signedTransaction: string]}
11
+ | {method: "gen_getContractSchema"; params: [address: string]}
12
+ | {method: "gen_getContractSchemaForCode"; params: [contractCode: string]};
13
+
14
+ export type GenLayerClient<
15
+ TTransport extends Transport,
16
+ TSimulatorChain extends SimulatorChain,
17
+ TAccount extends Account,
18
+ > = Client<TTransport, TSimulatorChain, TAccount> & {
19
+ request: Client<TTransport, TSimulatorChain, TAccount>["request"] & {
20
+ <TMethod extends GenLayerMethod>(
21
+ args: Extract<GenLayerMethod, {method: TMethod["method"]}>,
22
+ ): Promise<unknown>;
23
+ };
24
+ readContract: (args: {
25
+ account: Account;
26
+ address: Address;
27
+ functionName: string;
28
+ args: any[];
29
+ }) => Promise<any>;
30
+ writeContract: (args: {
31
+ account: Account;
32
+ address: Address;
33
+ functionName: string;
34
+ args: any[];
35
+ value: bigint;
36
+ }) => Promise<any>;
37
+ getTransaction: (args: {hash: TransactionHash}) => Promise<GenLayerTransaction>;
38
+ };
@@ -0,0 +1,15 @@
1
+ export type ContractSchema = {
2
+ abi: Array<{
3
+ inputs?: Array<{
4
+ name: string;
5
+ type: string;
6
+ }>;
7
+ name?: string;
8
+ outputs?: Array<{
9
+ name: string;
10
+ type: string;
11
+ }>;
12
+ type: "constructor" | "function";
13
+ }>;
14
+ class: string;
15
+ };
@@ -0,0 +1,5 @@
1
+ export * from "./accounts";
2
+ export * from "./chains";
3
+ export * from "./clients";
4
+ export * from "./contracts";
5
+ export * from "./transactions";
@@ -0,0 +1,29 @@
1
+ export type TransactionHash = `0x${string}` & {length: 66};
2
+
3
+ export enum TransactionStatus {
4
+ PENDING = "PENDING",
5
+ CANCELED = "CANCELED",
6
+ PROPOSING = "PROPOSING",
7
+ COMMITTING = "COMMITTING",
8
+ REVEALING = "REVEALING",
9
+ ACCEPTED = "ACCEPTED",
10
+ FINALIZED = "FINALIZED",
11
+ UNDETERMINED = "UNDETERMINED",
12
+ }
13
+
14
+ export type GenLayerTransaction = {
15
+ hash: TransactionHash;
16
+ status: TransactionStatus;
17
+ from_address?: string;
18
+ to_address?: string;
19
+ data?: Record<string, unknown>;
20
+ consensus_data?: Record<string, unknown>;
21
+ nonce?: number;
22
+ value?: number;
23
+ type?: number;
24
+ gaslimit?: bigint;
25
+ created_at?: Date;
26
+ r?: number;
27
+ s?: number;
28
+ v?: number;
29
+ };
@@ -0,0 +1,3 @@
1
+ export async function sleep(ms: number) {
2
+ return new Promise(resolve => setTimeout(resolve, ms));
3
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,119 @@
1
+ {
2
+ "compilerOptions": {
3
+ /* Visit https://aka.ms/tsconfig to read more about this file */
4
+
5
+ /* Projects */
6
+ // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
7
+ // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
8
+ // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
9
+ // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
10
+ // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
11
+ // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
12
+
13
+ /* Language and Environment */
14
+ "target": "ES2022" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
15
+ // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
16
+ // "jsx": "preserve", /* Specify what JSX code is generated. */
17
+ // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
18
+ // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
19
+ // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
20
+ // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
21
+ // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
22
+ // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
23
+ // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
24
+ // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
25
+ // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
26
+
27
+ /* Modules */
28
+ "module": "ES2022" /* Specify what module code is generated. */,
29
+ // "rootDir": /* Specify the root folder within your source files. */,
30
+ "moduleResolution": "node" /* Specify how TypeScript looks up a file from a given module specifier. */,
31
+ // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
32
+ "paths": {
33
+ "@/*": ["./src/*"],
34
+ "@@/tests/*": ["./tests/*"]
35
+ } /* Specify a set of entries that re-map imports to additional lookup locations. */,
36
+ "rootDirs": [
37
+ "./src",
38
+ "./tests"
39
+ ] /* Allow multiple folders to be treated as one when resolving modules. */,
40
+ // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
41
+ "types": [
42
+ "node",
43
+ "jest"
44
+ ] /* Specify type package names to be included without being referenced in a source file. */,
45
+ // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
46
+ // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
47
+ // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
48
+ // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */
49
+ // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */
50
+ // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
51
+ "resolveJsonModule": true /* Enable importing .json files. */,
52
+ // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */
53
+ // "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
54
+
55
+ /* JavaScript Support */
56
+ // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
57
+ // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
58
+ // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
59
+
60
+ /* Emit */
61
+ // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
62
+ // "declarationMap": true, /* Create sourcemaps for d.ts files. */
63
+ // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
64
+ "sourceMap": true /* Create source map files for emitted JavaScript files. */,
65
+ // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
66
+ // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
67
+ "outDir": "./dist" /* Specify an output folder for all emitted files. */,
68
+ // "removeComments": true, /* Disable emitting comments. */
69
+ // "noEmit": true, /* Disable emitting files from a compilation. */
70
+ // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
71
+ // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
72
+ // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
73
+ // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
74
+ // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
75
+ // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
76
+ // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
77
+ // "newLine": "crlf", /* Set the newline character for emitting files. */
78
+ // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
79
+ // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
80
+ // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
81
+ // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
82
+ // "declarationDir": "./", /* Specify the output directory for generated declaration files. */
83
+ // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
84
+
85
+ /* Interop Constraints */
86
+ // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
87
+ // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
88
+ // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
89
+ "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */,
90
+ // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
91
+ "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
92
+
93
+ /* Type Checking */
94
+ "strict": true /* Enable all strict type-checking options. */,
95
+ // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
96
+ // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
97
+ // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
98
+ // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
99
+ // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
100
+ // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
101
+ // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
102
+ // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
103
+ // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
104
+ // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
105
+ // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
106
+ // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
107
+ // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
108
+ // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
109
+ // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
110
+ // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
111
+ // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
112
+ // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
113
+
114
+ /* Completeness */
115
+ // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
116
+ "skipLibCheck": true /* Skip type checking all .d.ts files. */
117
+ },
118
+ "include": ["src/**/*", "tests/**/*"]
119
+ }
@@ -0,0 +1,12 @@
1
+ import { defineConfig } from "vitest/config";
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ globals: true,
6
+ environment: "node",
7
+ coverage: {
8
+ reporter: ["text", "json", "html"],
9
+ exclude: ["node_modules/"],
10
+ },
11
+ },
12
+ });