genlayer-js 0.9.0 → 0.9.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.
Files changed (51) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/dist/chains/index.cjs +2 -2
  3. package/dist/chains/index.d.cts +2 -2
  4. package/dist/chains/index.d.ts +2 -2
  5. package/dist/chains/index.js +3 -3
  6. package/dist/chains-BYSCF33g.d.cts +18 -0
  7. package/dist/chains-BYSCF33g.d.ts +18 -0
  8. package/dist/chunk-7YZQQWJZ.js +4056 -0
  9. package/dist/chunk-AZSICIZ3.cjs +132 -0
  10. package/dist/chunk-FPFZLPXI.cjs +4056 -0
  11. package/dist/chunk-RS7NCSOQ.js +132 -0
  12. package/dist/index-BM9hOtGg.d.cts +13 -0
  13. package/dist/index-C7Colsnk.d.ts +13 -0
  14. package/dist/index-DvSbRKD5.d.ts +370 -0
  15. package/dist/index-kDM_9wW1.d.cts +370 -0
  16. package/dist/index.cjs +315 -130
  17. package/dist/index.d.cts +6 -6
  18. package/dist/index.d.ts +6 -6
  19. package/dist/index.js +306 -121
  20. package/dist/types/index.cjs +18 -2
  21. package/dist/types/index.d.cts +3 -3
  22. package/dist/types/index.d.ts +3 -3
  23. package/dist/types/index.js +19 -3
  24. package/package.json +2 -2
  25. package/src/accounts/IAccountActions.ts +2 -2
  26. package/src/accounts/actions.ts +10 -4
  27. package/src/chains/actions.ts +5 -5
  28. package/src/chains/index.ts +1 -1
  29. package/src/chains/localnet.ts +4 -3
  30. package/src/chains/testnet.ts +4015 -0
  31. package/src/client/client.ts +64 -21
  32. package/src/contracts/actions.ts +185 -137
  33. package/src/transactions/actions.ts +145 -21
  34. package/src/types/accounts.ts +1 -2
  35. package/src/types/chains.ts +8 -2
  36. package/src/types/clients.ts +14 -13
  37. package/src/types/transactions.ts +249 -8
  38. package/src/wallet/actions.ts +4 -4
  39. package/src/wallet/connect.ts +12 -14
  40. package/tests/client.test.ts +105 -45
  41. package/dist/chains-C5PI_Nr_.d.cts +0 -13
  42. package/dist/chains-C5PI_Nr_.d.ts +0 -13
  43. package/dist/chunk-I6HC44KD.cjs +0 -72
  44. package/dist/chunk-K72OSU5N.js +0 -28
  45. package/dist/chunk-WEXFFND6.js +0 -72
  46. package/dist/chunk-YDFRDDP5.cjs +0 -28
  47. package/dist/index-B8E0qiOq.d.cts +0 -13
  48. package/dist/index-BCbofn6t.d.cts +0 -188
  49. package/dist/index-Ctmshvtv.d.ts +0 -188
  50. package/dist/index-ZoW0HQ_m.d.ts +0 -13
  51. package/src/chains/simulator.ts +0 -30
@@ -1,9 +1,20 @@
1
- import {Account, createClient as createViemClient, publicActions, custom, Address, walletActions} from "viem";
1
+ import {
2
+ Account,
3
+ createClient as createViemClient,
4
+ createPublicClient as createPublicViemClient,
5
+ publicActions,
6
+ custom,
7
+ Address,
8
+ walletActions,
9
+ Transport,
10
+ PublicClient,
11
+ Chain,
12
+ } from "viem";
2
13
  import {accountActions} from "../accounts/actions";
3
- import {contractActions, overrideContractActions} from "../contracts/actions";
4
- import {transactionActions} from "../transactions/actions";
14
+ import {contractActions} from "../contracts/actions";
15
+ import {receiptActions, transactionActions} from "../transactions/actions";
5
16
  import {walletActions as genlayerWalletActions} from "../wallet/actions";
6
- import {GenLayerClient, SimulatorChain} from "@/types";
17
+ import {GenLayerClient, GenLayerChain} from "@/types";
7
18
  import {chainActions} from "@/chains/actions";
8
19
  import {localnet} from "@/chains";
9
20
 
@@ -20,15 +31,11 @@ interface ClientConfig {
20
31
  account?: Account | Address;
21
32
  }
22
33
 
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
- }
34
+ const getCustomTransportConfig = (config: ClientConfig) => {
28
35
  const isAddress = typeof config.account !== "object";
29
36
 
30
- const customTransport = {
31
- async request({method, params}: {method: string; params: any[]}) {
37
+ return {
38
+ async request({method, params = []}: {method: string; params: any[]}) {
32
39
  if (method.startsWith("eth_") && isAddress) {
33
40
  try {
34
41
  return await window.ethereum?.request({method, params});
@@ -37,8 +44,12 @@ export const createClient = (config: ClientConfig = {chain: localnet}) => {
37
44
  throw err;
38
45
  }
39
46
  } else {
47
+ if (!config.chain) {
48
+ throw new Error("Chain is not set");
49
+ }
50
+
40
51
  try {
41
- const response = await fetch(chainConfig.rpcUrls.default.http[0], {
52
+ const response = await fetch(config.chain.rpcUrls.default.http[0], {
42
53
  method: "POST",
43
54
  headers: {
44
55
  "Content-Type": "application/json",
@@ -65,24 +76,56 @@ export const createClient = (config: ClientConfig = {chain: localnet}) => {
65
76
  }
66
77
  },
67
78
  };
79
+ };
80
+
81
+ export const createClient = (config: ClientConfig = {chain: localnet}): GenLayerClient<GenLayerChain> => {
82
+ const chainConfig = config.chain || localnet;
83
+ if (config.endpoint) {
84
+ chainConfig.rpcUrls.default.http = [config.endpoint];
85
+ }
86
+
87
+ const customTransport = custom(getCustomTransportConfig(config));
88
+ const publicClient = createPublicClient(chainConfig as GenLayerChain, customTransport).extend(
89
+ publicActions,
90
+ );
68
91
 
69
92
  const baseClient = createViemClient({
70
93
  chain: chainConfig,
71
- transport: custom(customTransport),
94
+ transport: customTransport,
72
95
  ...(config.account ? {account: config.account} : {}),
73
- })
96
+ });
97
+
98
+ // First extend with basic actions
99
+ const clientWithBasicActions = baseClient
74
100
  .extend(publicActions)
75
101
  .extend(walletActions)
76
- .extend(client => accountActions(client as unknown as GenLayerClient<SimulatorChain>))
77
- .extend(client => transactionActions(client as unknown as GenLayerClient<SimulatorChain>))
78
- .extend(client => contractActions(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>));
102
+ .extend(client => accountActions(client as unknown as GenLayerClient<GenLayerChain>));
103
+
104
+ // Create a client with all actions except transaction actions
105
+ const clientWithAllActions = {
106
+ ...clientWithBasicActions,
107
+ ...contractActions(clientWithBasicActions as unknown as GenLayerClient<GenLayerChain>, publicClient),
108
+ ...chainActions(clientWithBasicActions as unknown as GenLayerClient<GenLayerChain>),
109
+ ...genlayerWalletActions(clientWithBasicActions as unknown as GenLayerClient<GenLayerChain>),
110
+ ...transactionActions(clientWithBasicActions as unknown as GenLayerClient<GenLayerChain>, publicClient),
111
+ } as unknown as GenLayerClient<GenLayerChain>;
112
+
113
+ // Add transaction actions last, after all other actions are in place
114
+ const finalClient = {
115
+ ...clientWithAllActions,
116
+ ...receiptActions(clientWithAllActions as unknown as GenLayerClient<GenLayerChain>, publicClient),
117
+ } as unknown as GenLayerClient<GenLayerChain>;
81
118
 
82
119
  // Initialize in the background
83
- baseClient.initializeConsensusSmartContract().catch(error => {
120
+ finalClient.initializeConsensusSmartContract().catch(error => {
84
121
  console.error("Failed to initialize consensus smart contract:", error);
85
122
  });
123
+ return finalClient;
124
+ };
86
125
 
87
- return overrideContractActions(baseClient as unknown as GenLayerClient<SimulatorChain>);
126
+ export const createPublicClient = (
127
+ chainConfig: GenLayerChain,
128
+ customTransport: Transport,
129
+ ): PublicClient<Transport, Chain> => {
130
+ return createPublicViemClient({chain: chainConfig, transport: customTransport});
88
131
  };
@@ -1,15 +1,8 @@
1
1
  import * as calldata from "@/abi/calldata";
2
- import {serialize, serializeOne} from "@/abi/transactions";
3
- import {
4
- Account,
5
- ContractSchema,
6
- SimulatorChain,
7
- GenLayerClient,
8
- CalldataEncodable,
9
- Address,
10
- TransactionStatus,
11
- } from "@/types";
12
- import {fromHex, toHex, zeroAddress, encodeFunctionData} from "viem";
2
+ import {serialize} from "@/abi/transactions";
3
+ import {localnet} from "@/chains/localnet";
4
+ import {Account, ContractSchema, GenLayerChain, GenLayerClient, CalldataEncodable, Address} from "@/types";
5
+ import {fromHex, toHex, zeroAddress, encodeFunctionData, PublicClient, parseEventLogs} from "viem";
13
6
 
14
7
  function makeCalldataObject(
15
8
  method: string | undefined,
@@ -48,9 +41,12 @@ function makeCalldataObject(
48
41
  return ret;
49
42
  }
50
43
 
51
- export const contractActions = (client: GenLayerClient<SimulatorChain>) => {
44
+ export const contractActions = (client: GenLayerClient<GenLayerChain>, publicClient: PublicClient) => {
52
45
  return {
53
- getContractSchema: async (address: string): Promise<ContractSchema> => {
46
+ getContractSchema: async (address: Address): Promise<ContractSchema> => {
47
+ if (client.chain.id !== localnet.id) {
48
+ throw new Error("Contract schema is not supported on this network");
49
+ }
54
50
  const schema = (await client.request({
55
51
  method: "gen_getContractSchema",
56
52
  params: [address],
@@ -58,148 +54,200 @@ export const contractActions = (client: GenLayerClient<SimulatorChain>) => {
58
54
  return schema as unknown as ContractSchema;
59
55
  },
60
56
  getContractSchemaForCode: async (contractCode: string | Uint8Array): Promise<ContractSchema> => {
57
+ if (client.chain.id !== localnet.id) {
58
+ throw new Error("Contract schema is not supported on this network");
59
+ }
61
60
  const schema = (await client.request({
62
61
  method: "gen_getContractSchemaForCode",
63
62
  params: [toHex(contractCode)],
64
63
  })) as string;
65
64
  return schema as unknown as ContractSchema;
66
65
  },
67
- };
68
- };
69
-
70
- export const overrideContractActions = (client: GenLayerClient<SimulatorChain>) => {
71
- client.readContract = async <RawReturn extends boolean | undefined>(args: {
72
- account?: Account;
73
- address: Address;
74
- functionName: string;
75
- args?: CalldataEncodable[];
76
- kwargs?: Map<string, CalldataEncodable> | {[key: string]: CalldataEncodable};
77
- stateStatus?: TransactionStatus;
78
- rawReturn?: RawReturn;
79
- }): Promise<RawReturn extends true ? `0x${string}` : CalldataEncodable> => {
80
- const {
81
- account,
82
- address,
83
- functionName,
84
- args: callArgs,
85
- kwargs,
86
- stateStatus = TransactionStatus.ACCEPTED,
87
- } = args;
88
- const encodedData = calldata.encode(makeCalldataObject(functionName, callArgs, kwargs));
89
- const serializedData = serializeOne(encodedData);
90
-
91
- const senderAddress = account?.address ?? client.account?.address;
92
-
93
- const requestParams = {
94
- to: address,
95
- from: senderAddress,
96
- data: serializedData,
97
- };
98
- const result = await client.request({
99
- method: "eth_call",
100
- params: [requestParams, stateStatus == TransactionStatus.FINALIZED ? "finalized" : "latest"],
101
- });
102
-
103
- if (args.rawReturn) {
104
- return result;
105
- }
106
- const resultBinary = fromHex(result, "bytes");
107
- return calldata.decode(resultBinary) as any;
108
- };
66
+ readContract: async <RawReturn extends boolean | undefined>(args: {
67
+ account?: Account;
68
+ address: Address;
69
+ functionName: string;
70
+ args?: CalldataEncodable[];
71
+ kwargs?: Map<string, CalldataEncodable> | {[key: string]: CalldataEncodable};
72
+ rawReturn?: RawReturn;
73
+ leaderOnly?: boolean;
74
+ }): Promise<RawReturn extends true ? `0x${string}` : CalldataEncodable> => {
75
+ const {account, address, functionName, args: callArgs, kwargs, leaderOnly = false} = args;
76
+ const encodedData = [calldata.encode(makeCalldataObject(functionName, callArgs, kwargs)), leaderOnly];
77
+ const serializedData = serialize(encodedData);
78
+
79
+ const senderAddress = account?.address ?? client.account?.address;
80
+
81
+ const requestParams = {
82
+ type: "read",
83
+ to: address,
84
+ from: senderAddress,
85
+ data: serializedData,
86
+ transaction_hash_variant: "latest-final",
87
+ };
88
+ const result = await client.request({
89
+ method: "gen_call",
90
+ params: [requestParams],
91
+ });
92
+ const prefixedResult = `0x${result}` as `0x${string}`;
109
93
 
110
- client.writeContract = async (args: {
111
- account?: Account;
112
- address: Address;
113
- functionName: string;
114
- args?: CalldataEncodable[];
115
- kwargs?: Map<string, CalldataEncodable> | {[key: string]: CalldataEncodable};
116
- value: bigint;
117
- leaderOnly?: boolean;
118
- consensusMaxRotations?: number;
119
- }): Promise<`0x${string}`> => {
120
- const {account, address, functionName, args: callArgs, kwargs, value = 0n, leaderOnly = false, consensusMaxRotations = client.chain.defaultConsensusMaxRotations} = args;
121
- const data = [calldata.encode(makeCalldataObject(functionName, callArgs, kwargs)), leaderOnly];
122
- const serializedData = serialize(data);
123
- return _sendTransaction(address, serializedData, account || client.account, consensusMaxRotations, value);
94
+ if (args.rawReturn) {
95
+ return prefixedResult;
96
+ }
97
+ const resultBinary = fromHex(prefixedResult, "bytes");
98
+ return calldata.decode(resultBinary) as any;
99
+ },
100
+ writeContract: async (args: {
101
+ account?: Account;
102
+ address: Address;
103
+ functionName: string;
104
+ args?: CalldataEncodable[];
105
+ kwargs?: Map<string, CalldataEncodable> | {[key: string]: CalldataEncodable};
106
+ value: bigint;
107
+ leaderOnly?: boolean;
108
+ consensusMaxRotations?: number;
109
+ }): Promise<`0x${string}`> => {
110
+ const {
111
+ account,
112
+ address,
113
+ functionName,
114
+ args: callArgs,
115
+ kwargs,
116
+ value = 0n,
117
+ leaderOnly = false,
118
+ consensusMaxRotations = client.chain.defaultConsensusMaxRotations,
119
+ } = args;
120
+ const data = [calldata.encode(makeCalldataObject(functionName, callArgs, kwargs)), leaderOnly];
121
+ const serializedData = serialize(data);
122
+ return _sendTransaction({
123
+ client,
124
+ publicClient,
125
+ recipient: address,
126
+ data: serializedData,
127
+ senderAccount: account || client.account,
128
+ consensusMaxRotations,
129
+ value,
130
+ });
131
+ },
132
+ deployContract: async (args: {
133
+ account?: Account;
134
+ code: string | Uint8Array;
135
+ args?: CalldataEncodable[];
136
+ kwargs?: Map<string, CalldataEncodable> | {[key: string]: CalldataEncodable};
137
+ leaderOnly?: boolean;
138
+ consensusMaxRotations?: number;
139
+ }) => {
140
+ const {
141
+ account,
142
+ code,
143
+ args: constructorArgs,
144
+ kwargs,
145
+ leaderOnly = false,
146
+ consensusMaxRotations = client.chain.defaultConsensusMaxRotations,
147
+ } = args;
148
+ const data = [
149
+ code,
150
+ calldata.encode(makeCalldataObject(undefined, constructorArgs, kwargs)),
151
+ leaderOnly,
152
+ ];
153
+ const serializedData = serialize(data);
154
+ return _sendTransaction({
155
+ client,
156
+ publicClient: publicClient,
157
+ recipient: zeroAddress,
158
+ data: serializedData,
159
+ senderAccount: account || client.account,
160
+ consensusMaxRotations,
161
+ });
162
+ },
124
163
  };
164
+ };
125
165
 
126
- client.deployContract = async (args: {
127
- account?: Account;
128
- code: string | Uint8Array;
129
- args?: CalldataEncodable[];
130
- kwargs?: Map<string, CalldataEncodable> | {[key: string]: CalldataEncodable};
131
- leaderOnly?: boolean;
132
- consensusMaxRotations?: number;
133
- }) => {
134
- const {account, code, args: constructorArgs, kwargs, leaderOnly = false, consensusMaxRotations = client.chain.defaultConsensusMaxRotations} = args;
135
- const data = [code, calldata.encode(makeCalldataObject(undefined, constructorArgs, kwargs)), leaderOnly];
136
- const serializedData = serialize(data);
137
- return _sendTransaction(zeroAddress, serializedData, account || client.account, consensusMaxRotations);
138
- };
166
+ const _sendTransaction = async ({
167
+ client,
168
+ publicClient,
169
+ recipient,
170
+ data,
171
+ senderAccount,
172
+ consensusMaxRotations,
173
+ value,
174
+ }: {
175
+ client: GenLayerClient<GenLayerChain>;
176
+ publicClient: PublicClient;
177
+ recipient: `0x${string}`;
178
+ data: `0x${string}`;
179
+ senderAccount?: Account;
180
+ consensusMaxRotations?: number;
181
+ value?: bigint;
182
+ }) => {
183
+ if (!senderAccount) {
184
+ throw new Error(
185
+ "No account set. Configure the client with an account or pass an account to this function.",
186
+ );
187
+ }
139
188
 
140
- const _sendTransaction = async (
141
- recipient: `0x${string}`,
142
- data: `0x${string}`,
143
- senderAccount?: Account,
144
- consensusMaxRotations?: number,
145
- value?: bigint,
146
- ) => {
147
- if (!senderAccount) {
148
- throw new Error(
149
- "No account set. Configure the client with an account or pass an account to this function.",
150
- );
151
- }
189
+ if (!client.chain.consensusMainContract?.address) {
190
+ throw new Error("Consensus main contract not initialized. Please ensure client is properly initialized.");
191
+ }
152
192
 
153
- if (!client.chain.consensusMainContract?.address) {
154
- throw new Error(
155
- "Consensus main contract not initialized. Please ensure client is properly initialized.",
156
- );
157
- }
193
+ const encodedData = encodeFunctionData({
194
+ abi: client.chain.consensusMainContract?.abi as any,
195
+ functionName: "addTransaction",
196
+ args: [
197
+ senderAccount.address,
198
+ recipient,
199
+ client.chain.defaultNumberOfInitialValidators,
200
+ consensusMaxRotations,
201
+ data,
202
+ ],
203
+ });
204
+
205
+ const nonce = await client.getCurrentNonce({address: senderAccount.address});
206
+ const transactionRequest = await client.prepareTransactionRequest({
207
+ account: senderAccount,
208
+ to: client.chain.consensusMainContract?.address as Address,
209
+ data: encodedData,
210
+ type: "legacy",
211
+ nonce: Number(nonce),
212
+ value: value ?? 0n,
213
+ });
214
+
215
+ if (senderAccount?.type !== "local") {
216
+ const formattedRequest = {
217
+ from: transactionRequest.from,
218
+ to: transactionRequest.to,
219
+ data: encodedData,
220
+ value: transactionRequest.value ? `0x${transactionRequest.value.toString(16)}` : "0x0",
221
+ };
158
222
 
159
- const encodedData = encodeFunctionData({
160
- abi: client.chain.consensusMainContract?.abi as any,
161
- functionName: "addTransaction",
162
- args: [
163
- senderAccount.address,
164
- recipient,
165
- client.chain.defaultNumberOfInitialValidators,
166
- consensusMaxRotations,
167
- data,
168
- ],
223
+ return await client.request({
224
+ method: "eth_sendTransaction",
225
+ params: [formattedRequest as any],
169
226
  });
227
+ }
170
228
 
171
- const nonce = await client.getCurrentNonce({address: senderAccount.address});
172
- const transactionRequest = await client.prepareTransactionRequest({
173
- account: senderAccount,
174
- to: client.chain.consensusMainContract?.address as Address,
175
- data: encodedData,
176
- type: "legacy",
177
- nonce,
178
- value: value ?? 0n,
179
- });
229
+ if (!senderAccount?.signTransaction) {
230
+ throw new Error("Account does not support signTransaction");
231
+ }
180
232
 
181
- if (senderAccount?.type !== "local") {
182
- const formattedRequest = {
183
- from: transactionRequest.from,
184
- to: transactionRequest.to,
185
- data: encodedData,
186
- value: transactionRequest.value ? `0x${transactionRequest.value.toString(16)}` : "0x0",
187
- };
233
+ const serializedTransaction = await senderAccount.signTransaction(transactionRequest);
188
234
 
189
- return await client.request({
190
- method: "eth_sendTransaction",
191
- params: [formattedRequest as any],
192
- });
193
- }
235
+ const txHash = await client.sendRawTransaction({serializedTransaction: serializedTransaction});
236
+ const receipt = await publicClient.waitForTransactionReceipt({hash: txHash});
194
237
 
195
- if (!senderAccount?.signTransaction) {
196
- throw new Error("Account does not support signTransaction");
197
- }
238
+ if (receipt.status === "reverted") {
239
+ throw new Error("Transaction reverted");
240
+ }
198
241
 
199
- const serializedTransaction = await senderAccount.signTransaction(transactionRequest);
242
+ const newTxEvents = parseEventLogs({
243
+ abi: client.chain.consensusMainContract?.abi as any,
244
+ eventName: "NewTransaction",
245
+ logs: receipt.logs,
246
+ }) as unknown as {args: {txId: `0x${string}`}}[];
200
247
 
201
- return client.sendRawTransaction({serializedTransaction: serializedTransaction});
202
- };
248
+ if (newTxEvents.length === 0) {
249
+ throw new Error("Transaction not processed by consensus");
250
+ }
203
251
 
204
- return client;
252
+ return newTxEvents[0].args["txId"];
205
253
  };