@thru/thru-sdk 0.0.4

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 (63) hide show
  1. package/README.md +7 -0
  2. package/buf.gen.yaml +12 -0
  3. package/buf.lock +9 -0
  4. package/buf.yaml +15 -0
  5. package/dist/sdk.d.ts +1354 -0
  6. package/dist/sdk.js +1130 -0
  7. package/dist/sdk.js.map +1 -0
  8. package/package.json +39 -0
  9. package/proto/thru/common/v1/consensus.proto +75 -0
  10. package/proto/thru/common/v1/errors.proto +67 -0
  11. package/proto/thru/common/v1/filters.proto +50 -0
  12. package/proto/thru/common/v1/pagination.proto +47 -0
  13. package/proto/thru/core/v1/account.proto +138 -0
  14. package/proto/thru/core/v1/block.proto +82 -0
  15. package/proto/thru/core/v1/state.proto +37 -0
  16. package/proto/thru/core/v1/transaction.proto +95 -0
  17. package/proto/thru/core/v1/types.proto +52 -0
  18. package/proto/thru/services/v1/command_service.proto +45 -0
  19. package/proto/thru/services/v1/query_service.proto +344 -0
  20. package/proto/thru/services/v1/streaming_service.proto +128 -0
  21. package/thru-ts-client-sdk/core/bound-client.ts +129 -0
  22. package/thru-ts-client-sdk/core/client.ts +38 -0
  23. package/thru-ts-client-sdk/counter.ts +216 -0
  24. package/thru-ts-client-sdk/create-account.ts +78 -0
  25. package/thru-ts-client-sdk/defaults.ts +17 -0
  26. package/thru-ts-client-sdk/get-height.ts +52 -0
  27. package/thru-ts-client-sdk/modules/accounts.ts +137 -0
  28. package/thru-ts-client-sdk/modules/blocks.ts +75 -0
  29. package/thru-ts-client-sdk/modules/events.ts +20 -0
  30. package/thru-ts-client-sdk/modules/height.ts +9 -0
  31. package/thru-ts-client-sdk/modules/helpers.ts +340 -0
  32. package/thru-ts-client-sdk/modules/proofs.ts +20 -0
  33. package/thru-ts-client-sdk/modules/streaming.ts +34 -0
  34. package/thru-ts-client-sdk/modules/transactions.ts +274 -0
  35. package/thru-ts-client-sdk/proto/buf/validate/validate_pb.ts +4761 -0
  36. package/thru-ts-client-sdk/proto/google/api/annotations_pb.ts +39 -0
  37. package/thru-ts-client-sdk/proto/google/api/client_pb.ts +953 -0
  38. package/thru-ts-client-sdk/proto/google/api/field_behavior_pb.ts +157 -0
  39. package/thru-ts-client-sdk/proto/google/api/http_pb.ts +474 -0
  40. package/thru-ts-client-sdk/proto/google/api/launch_stage_pb.ts +118 -0
  41. package/thru-ts-client-sdk/proto/thru/common/v1/consensus_pb.ts +163 -0
  42. package/thru-ts-client-sdk/proto/thru/common/v1/errors_pb.ts +130 -0
  43. package/thru-ts-client-sdk/proto/thru/common/v1/filters_pb.ts +81 -0
  44. package/thru-ts-client-sdk/proto/thru/common/v1/pagination_pb.ts +80 -0
  45. package/thru-ts-client-sdk/proto/thru/core/v1/account_pb.ts +358 -0
  46. package/thru-ts-client-sdk/proto/thru/core/v1/block_pb.ts +260 -0
  47. package/thru-ts-client-sdk/proto/thru/core/v1/state_pb.ts +104 -0
  48. package/thru-ts-client-sdk/proto/thru/core/v1/transaction_pb.ts +327 -0
  49. package/thru-ts-client-sdk/proto/thru/core/v1/types_pb.ts +101 -0
  50. package/thru-ts-client-sdk/proto/thru/services/v1/command_service_pb.ts +81 -0
  51. package/thru-ts-client-sdk/proto/thru/services/v1/query_service_pb.ts +813 -0
  52. package/thru-ts-client-sdk/proto/thru/services/v1/streaming_service_pb.ts +391 -0
  53. package/thru-ts-client-sdk/sdk.ts +58 -0
  54. package/thru-ts-client-sdk/transactions/Transaction.ts +240 -0
  55. package/thru-ts-client-sdk/transactions/TransactionBuilder.ts +48 -0
  56. package/thru-ts-client-sdk/transactions/__tests__/transaction.test.ts +95 -0
  57. package/thru-ts-client-sdk/transactions/index.ts +3 -0
  58. package/thru-ts-client-sdk/transactions/types.ts +64 -0
  59. package/thru-ts-client-sdk/transactions/utils.ts +134 -0
  60. package/thru-ts-client-sdk/types/types.ts +8 -0
  61. package/thru-ts-client-sdk/utils/utils.ts +70 -0
  62. package/tsconfig.json +9 -0
  63. package/tsup.config.ts +10 -0
@@ -0,0 +1,216 @@
1
+ import { ConsensusStatus } from "./proto/thru/common/v1/consensus_pb";
2
+ import { createThruClient } from "./sdk";
3
+
4
+ const sdk = createThruClient({
5
+ // Configure the SDK to connect to the desired Thru cluster
6
+ // endpoint: "https://api.thru.network", // Example endpoint
7
+ });
8
+
9
+ const counterProgramAddress = 'taXP9YQR-M_1xg_jCh61aVpnMzAy0nqIfMA6waQXUMqfrL'
10
+ const derivedAddress = 'taXu7Ka2B1UULjhCfyGb3MMJfHVMoA99Ii_KmgcYHHrsoY'
11
+ const seed = 'count1'
12
+
13
+ const feePayerAddress = 'takJg69_G9ESZ6IyEzYw97h8Xz6H-LdWTD7EF-qomr6Zv2'
14
+ const feePayerPrivateKeyHex = '9429cacf4e1faa2524d42aeda5d6daa2eab4ca6b56854ad4da35437911d8176a'
15
+
16
+ const DEFAULT_COMPUTE_UNITS = 300_000_000;
17
+ const DEFAULT_STATE_UNITS = 10_000;
18
+ const DEFAULT_MEMORY_UNITS = 10_000;
19
+ const DEFAULT_EXPIRY_AFTER = 100;
20
+
21
+ // Turn an unsigned integer into a little-endian hex string padded to byteLength bytes
22
+ export function toLittleEndianHex(value: number | bigint, byteLength: number): string {
23
+ let v = typeof value === "bigint" ? value : BigInt(value);
24
+ const bytes = new Uint8Array(byteLength);
25
+ for (let i = 0; i < byteLength; i++) {
26
+ bytes[i] = Number(v & 0xffn);
27
+ v >>= 8n;
28
+ }
29
+ return Array.from(bytes, b => b.toString(16).padStart(2, "0")).join("");
30
+ }
31
+
32
+ // Convenience wrappers matching the screenshot
33
+ export const u32ToHexLE = (value: number | bigint) => toLittleEndianHex(value, 4);
34
+ export const u16ToHexLE = (value: number | bigint) => toLittleEndianHex(value, 2);
35
+
36
+
37
+ const getIncrementCounterAccountInstructionDataHex = async () => {
38
+ const instructionCreate = u32ToHexLE(1)
39
+ const accountIndex = u16ToHexLE(2)
40
+ const instructionData = instructionCreate + accountIndex
41
+ return instructionData;
42
+ }
43
+
44
+ const accountDataToHex = (data: Uint8Array): string => {
45
+ let dataToHex = Array.from(data, b => b.toString(16).padStart(2, "0")).join("");
46
+ return dataToHex;
47
+ }
48
+
49
+ function hexToBytes(hex: string): Uint8Array {
50
+ const normalized = hex.startsWith("0x") ? hex.slice(2) : hex;
51
+ if (normalized.length % 2 !== 0) {
52
+ throw new Error("Private key hex must contain an even number of characters");
53
+ }
54
+ const bytes = new Uint8Array(normalized.length / 2);
55
+ for (let i = 0; i < normalized.length; i += 2) {
56
+ bytes[i / 2] = parseInt(normalized.substring(i, i + 2), 16);
57
+ }
58
+ return bytes;
59
+ }
60
+
61
+ const incrementCounterAccountInstruction = async () => {
62
+ const instructionDataHex = await getIncrementCounterAccountInstructionDataHex();
63
+ const feePayerPublicKey = sdk.helpers.decodeAddress(feePayerAddress);
64
+ const feePayerPrivateKey = hexToBytes(feePayerPrivateKeyHex);
65
+
66
+ const transaction = await sdk.transactions.build({
67
+ feePayer: {
68
+ publicKey: feePayerPublicKey,
69
+ privateKey: feePayerPrivateKey,
70
+ },
71
+ program: counterProgramAddress,
72
+ header: {
73
+ fee: 0n,
74
+ computeUnits: DEFAULT_COMPUTE_UNITS,
75
+ stateUnits: DEFAULT_STATE_UNITS,
76
+ memoryUnits: DEFAULT_MEMORY_UNITS,
77
+ expiryAfter: DEFAULT_EXPIRY_AFTER,
78
+ },
79
+ accounts: {
80
+ readWrite: [derivedAddress],
81
+ },
82
+ content: {
83
+ instructions: instructionDataHex,
84
+ },
85
+ })
86
+
87
+ await transaction.sign(feePayerPrivateKey);
88
+
89
+ const rawTransaction = transaction.toWire();
90
+
91
+ const submittedSignature = await sdk.transactions.send(rawTransaction);
92
+ console.log("Submitted transaction signature:", submittedSignature);
93
+
94
+ let finalized = false;
95
+ let executionUnits: number | undefined;
96
+
97
+ try {
98
+ for await (const update of sdk.transactions.track(submittedSignature, { timeoutMs: 60000 })) {
99
+ const consumed = update.executionResult?.consumedComputeUnits ?? 0;
100
+ const statusKey = ConsensusStatus[update.consensusStatus];
101
+ console.log("Track update:", statusKey, "consumed CU:", consumed);
102
+ if (update.executionResult) {
103
+ executionUnits = consumed;
104
+ }
105
+ if (
106
+ update.consensusStatus === ConsensusStatus.FINALIZED ||
107
+ update.consensusStatus === ConsensusStatus.CLUSTER_EXECUTED
108
+ ) {
109
+ finalized = true;
110
+ break;
111
+ }
112
+ }
113
+ } catch (err) {
114
+ console.warn("Track transaction stream ended with error:", err);
115
+ }
116
+
117
+ if (!finalized) {
118
+ console.warn("Transaction not finalized before timeout");
119
+ }
120
+ if (executionUnits !== undefined) {
121
+ console.log("Execution consumed compute units:", executionUnits);
122
+ }
123
+ }
124
+
125
+
126
+ async function main() {
127
+ const accountData1 = await sdk.accounts.get(derivedAddress);
128
+
129
+ if (accountData1.data) {
130
+ console.log("First Account Data:", accountDataToHex(accountData1.data.data));
131
+ }
132
+
133
+ await incrementCounterAccountInstruction();
134
+
135
+ await new Promise(resolve => setTimeout(resolve, 2000));
136
+
137
+ const accountData2 = await sdk.accounts.get(derivedAddress);
138
+
139
+ if (accountData2.data) {
140
+ console.log("Incremented Account Data:", accountDataToHex(accountData2.data.data));
141
+ }
142
+ }
143
+
144
+ console.log("Starting counter script");
145
+ main()
146
+
147
+ // function seedToHex32Padded(seed: string): string {
148
+ // const bytes = new TextEncoder().encode(seed);
149
+ // const padded = new Uint8Array(32);
150
+ // padded.set(bytes.slice(0, 32));
151
+ // return Array.from(padded, b => b.toString(16).padStart(2, "0")).join("");
152
+ // }
153
+
154
+ // const getCreateCounterAccountInstructionDataHex = async () => {
155
+ // const instructionCreate = u32ToHexLE(0)
156
+ // const accountIndex = u16ToHexLE(2)
157
+
158
+ // const blockHeight = await sdk.getBlockHeight();
159
+ // const stateProof = await sdk.generateStateProof({
160
+ // proofType: 1,
161
+ // address: derivedAddress,
162
+ // targetSlot: blockHeight.finalized
163
+ // })
164
+ // if (!stateProof.proof || stateProof.proof.proof.length === 0) {
165
+ // console.error("No state proof returned");
166
+ // return;
167
+ // }
168
+ // const stateProofSizeHex = u32ToHexLE(stateProof.proof.proof.length);
169
+ // const seedHex = seedToHex32Padded(seed);
170
+
171
+ // const stateProofHex = stateProof.proof.proof.reduce((acc, byte) => acc + byte.toString(16).padStart(2, "0"), "")
172
+
173
+ // console.log(instructionCreate, accountIndex, seedHex, stateProofSizeHex, stateProofHex)
174
+
175
+ // const instructionData = instructionCreate + accountIndex + seedHex + stateProofSizeHex + stateProofHex
176
+ // return instructionData;
177
+ // }
178
+
179
+ // const createCounterAccountInstruction = async () => {
180
+ // const instructionDataHex = await getCreateCounterAccountInstructionDataHex();
181
+ // console.log("Instruction Data Hex:", instructionDataHex);
182
+
183
+ // const feePayerPublicKey = sdk.decodeAddress(feePayerAddress);
184
+ // console.log("Fee Payer Public Key:", feePayerPublicKey);
185
+ // const feePayerPrivateKey = hexToBytes(feePayerPrivateKeyHex);
186
+
187
+ // const { rawTransaction, signature } = await sdk.buildAndSignTransaction({
188
+ // feePayer: {
189
+ // publicKey: feePayerPublicKey,
190
+ // privateKey: feePayerPrivateKey,
191
+ // },
192
+ // program: counterProgramAddress,
193
+ // header: {
194
+ // fee: 0n,
195
+ // },
196
+ // accounts: {
197
+ // readWrite: [derivedAddress],
198
+ // },
199
+ // content: {
200
+ // instructions: instructionDataHex,
201
+ // },
202
+ // });
203
+
204
+ // console.log("Local signature:", Array.from(signature, b => b.toString(16).padStart(2, "0")).join(""));
205
+
206
+ // const submittedSignature = await sdk.sendBuiltTransaction(rawTransaction);
207
+ // console.log("Submitted transaction signature:", submittedSignature);
208
+
209
+ // await new Promise(resolve => setTimeout(resolve, 4000));
210
+
211
+ // const submittedTransactionStatus = await sdk.getTransactionStatus(submittedSignature);
212
+ // console.log("Submitted transaction status:", submittedTransactionStatus);
213
+
214
+ // const submittedTransaction = await sdk.getTransaction(submittedSignature);
215
+ // console.log("Submitted transaction:", submittedTransaction);
216
+ // }
@@ -0,0 +1,78 @@
1
+ import { getPublicKeyAsync } from "@noble/ed25519";
2
+ import { ConsensusStatus } from "./proto/thru/common/v1/consensus_pb";
3
+ import { createThruClient } from "./sdk";
4
+
5
+ const sdk = createThruClient({
6
+ // endpoint: "https://api.thru.network", // Set to your cluster endpoint.
7
+ });
8
+
9
+ // Replace with the account you want to create and its 32-byte private key.
10
+ const targetAccountPrivateKeyHex = "da0abd760d32d319ad11069d2d56f8c61b03f28d4096947c5117a54f427e4d60";
11
+ const targetAccountAddress = sdk.helpers.encodeAddress(await getPublicKeyAsync(targetAccountPrivateKeyHex))
12
+
13
+ function hexToBytes(hex: string): Uint8Array {
14
+ const normalized = hex.startsWith("0x") ? hex.slice(2) : hex;
15
+ if (normalized.length % 2 !== 0) {
16
+ throw new Error("Private key hex must contain an even number of characters");
17
+ }
18
+ const bytes = new Uint8Array(normalized.length / 2);
19
+ for (let i = 0; i < normalized.length; i += 2) {
20
+ bytes[i / 2] = parseInt(normalized.substring(i, i + 2), 16);
21
+ }
22
+ return bytes;
23
+ }
24
+
25
+ async function fetchAccountSnapshot(label: string, address: string): Promise<void> {
26
+ try {
27
+ const account = await sdk.accounts.get(address);
28
+ const consensus = account.consensusStatus != null
29
+ ? ConsensusStatus[account.consensusStatus]
30
+ : "UNKNOWN";
31
+ const slot = account.versionContext?.slot ?? 0n;
32
+ const balance = account.meta?.balance ?? 0n;
33
+ const stateCounter = account.meta?.stateCounter ?? 0n;
34
+
35
+ console.log(
36
+ `${label} account status: consensus=${consensus}, slot=${slot.toString()}, balance=${balance.toString()}, stateCounter=${stateCounter.toString()}`,
37
+ );
38
+ } catch (err) {
39
+ const message = err instanceof Error ? err.message : String(err);
40
+ console.log(`${label} account lookup failed: ${message}`);
41
+ }
42
+ }
43
+
44
+ async function run(): Promise<void> {
45
+ console.log("Preparing create account transaction");
46
+
47
+ await fetchAccountSnapshot("Pre-create", targetAccountAddress);
48
+
49
+ const feePayerPublicKey = sdk.helpers.decodeAddress(targetAccountAddress);
50
+ const feePayerPrivateKey = hexToBytes(targetAccountPrivateKeyHex);
51
+
52
+ const transaction = await sdk.accounts.create({
53
+ publicKey: feePayerPublicKey
54
+ })
55
+
56
+ await transaction.sign(feePayerPrivateKey);
57
+
58
+ const rawTransaction = transaction.toWire();
59
+
60
+ console.log("Submitting transaction");
61
+ const submittedSignature = await sdk.transactions.send(rawTransaction);
62
+ // Allow some time for the cluster to reflect the new account state.
63
+ await new Promise(resolve => setTimeout(resolve, 2_000));
64
+ const transactionStatus = await sdk.transactions.getStatus(submittedSignature);
65
+ console.log("Submitted transaction status:", transactionStatus);
66
+ console.log("Submitted transaction signature:", submittedSignature);
67
+
68
+ // await trackTransaction(submittedSignature);
69
+
70
+ // Allow some time for the cluster to reflect the new account state.
71
+ await new Promise(resolve => setTimeout(resolve, 2_000));
72
+
73
+ await fetchAccountSnapshot("Post-create", targetAccountAddress);
74
+ }
75
+
76
+ run().catch(error => {
77
+ console.error("Create account script failed:", error);
78
+ });
@@ -0,0 +1,17 @@
1
+ import { ConsensusStatus } from "./proto/thru/common/v1/consensus_pb";
2
+ import { AccountView } from "./proto/thru/core/v1/account_pb";
3
+ import { BlockView } from "./proto/thru/core/v1/block_pb";
4
+ import { TransactionView } from "./proto/thru/core/v1/transaction_pb";
5
+
6
+ export const DEFAULT_HOST = "http://74.118.142.189:8080";
7
+
8
+ export const DEFAULT_ACCOUNT_VIEW = AccountView.FULL;
9
+ export const DEFAULT_BLOCK_VIEW = BlockView.FULL;
10
+ export const DEFAULT_TRANSACTION_VIEW = TransactionView.FULL;
11
+ export const DEFAULT_MIN_CONSENSUS = ConsensusStatus.UNSPECIFIED;
12
+
13
+ export const DEFAULT_FEE = 1n;
14
+ export const DEFAULT_COMPUTE_UNITS = 300_000_000;
15
+ export const DEFAULT_STATE_UNITS = 10_000;
16
+ export const DEFAULT_MEMORY_UNITS = 10_000;
17
+ export const DEFAULT_EXPIRY_AFTER = 100;
@@ -0,0 +1,52 @@
1
+ /* Polyfill XMLHttpRequest for Node.js */
2
+ import { createClient } from "@connectrpc/connect";
3
+
4
+ import { createGrpcWebTransport } from "@connectrpc/connect-web";
5
+ import { GetHeightRequestSchema, QueryService } from './proto/thru/services/v1/query_service_pb';
6
+
7
+ import { create } from "@bufbuild/protobuf";
8
+
9
+ /* Example script to get the current block height from a Thru node */
10
+ async function getBlockHeight(hostUrl: string): Promise<void> {
11
+ /* Create the gRPC client */
12
+ const transport = createGrpcWebTransport({
13
+ baseUrl: hostUrl,
14
+ });
15
+ const client = createClient(QueryService, transport);
16
+
17
+
18
+ try {
19
+ /* Create an empty request */
20
+ const request = create(GetHeightRequestSchema);
21
+
22
+ /* Call the GetHeight RPC method */
23
+ const response = await client.getHeight(request);
24
+
25
+ /* Extract height information from the response */
26
+ const finalized = response.finalized;
27
+ const locallyExecuted = response.locallyExecuted;
28
+ const clusterExecuted = response.clusterExecuted;
29
+
30
+ /* Display the results */
31
+ console.log('=== Block Height ===');
32
+ console.log(`Finalized: ${finalized}`);
33
+ console.log(`Locally Executed: ${locallyExecuted}`);
34
+ console.log(`Cluster Executed: ${clusterExecuted}`);
35
+ } catch (err) {
36
+ console.error('Error fetching block height:', err);
37
+ throw err;
38
+ }
39
+ }
40
+
41
+ /* Main execution */
42
+ const DEFAULT_HOST = 'http://74.118.142.189:8080';
43
+
44
+ console.log(`Connecting to Thru node at ${DEFAULT_HOST}...`);
45
+
46
+ getBlockHeight(DEFAULT_HOST)
47
+ .then(() => {
48
+ console.log('\nSuccess!');
49
+ })
50
+ .catch((err) => {
51
+ console.error('\nFailed to get block height:', err);
52
+ });
@@ -0,0 +1,137 @@
1
+ import { create } from "@bufbuild/protobuf";
2
+
3
+ import type { ThruClientContext } from "../core/client";
4
+ import { DEFAULT_ACCOUNT_VIEW, DEFAULT_MIN_CONSENSUS } from "../defaults";
5
+ import { ConsensusStatus, VersionContext } from "../proto/thru/common/v1/consensus_pb";
6
+ import type { Filter } from "../proto/thru/common/v1/filters_pb";
7
+ import type { PageRequest } from "../proto/thru/common/v1/pagination_pb";
8
+ import { Account, AccountView, DataSlice, RawAccount } from "../proto/thru/core/v1/account_pb";
9
+ import { StateProofType } from "../proto/thru/core/v1/state_pb";
10
+ import {
11
+ GetAccountRequestSchema,
12
+ GetRawAccountRequestSchema,
13
+ ListOwnedAccountsRequestSchema,
14
+ ListOwnedAccountsResponse,
15
+ } from "../proto/thru/services/v1/query_service_pb";
16
+ import type { Transaction } from "../transactions/Transaction";
17
+ import { TransactionBuilder } from "../transactions/TransactionBuilder";
18
+ import { getBlockHeight } from "./height";
19
+ import type { BytesLike } from "./helpers";
20
+ import { toPubkey } from "./helpers";
21
+ import { generateStateProof } from "./proofs";
22
+
23
+ export interface CreateAccountOptions {
24
+ /** The new account's public key (fee payer). */
25
+ publicKey: BytesLike;
26
+ }
27
+
28
+
29
+ export interface AccountQueryOptions {
30
+ view?: AccountView;
31
+ versionContext?: VersionContext;
32
+ minConsensus?: ConsensusStatus;
33
+ dataSlice?: DataSlice;
34
+ }
35
+
36
+ export interface RawAccountQueryOptions {
37
+ view?: AccountView;
38
+ versionContext?: VersionContext;
39
+ minConsensus?: ConsensusStatus;
40
+ }
41
+
42
+ export interface ListOwnedAccountsOptions {
43
+ view?: AccountView;
44
+ versionContext?: VersionContext;
45
+ filter?: Filter;
46
+ page?: PageRequest;
47
+ minConsensus?: ConsensusStatus;
48
+ }
49
+
50
+ export function getAccount(
51
+ ctx: ThruClientContext,
52
+ address: BytesLike,
53
+ options: AccountQueryOptions = {},
54
+ ): Promise<Account> {
55
+ const request = create(GetAccountRequestSchema, {
56
+ address: toPubkey(address, "address"),
57
+ view: options.view ?? DEFAULT_ACCOUNT_VIEW,
58
+ versionContext: options.versionContext,
59
+ minConsensus: options.minConsensus ?? DEFAULT_MIN_CONSENSUS,
60
+ dataSlice: options.dataSlice,
61
+ });
62
+ return ctx.query.getAccount(request);
63
+ }
64
+
65
+ export function getRawAccount(
66
+ ctx: ThruClientContext,
67
+ address: BytesLike,
68
+ options: RawAccountQueryOptions = {},
69
+ ): Promise<RawAccount> {
70
+ const request = create(GetRawAccountRequestSchema, {
71
+ address: toPubkey(address, "address"),
72
+ view: options.view ?? DEFAULT_ACCOUNT_VIEW,
73
+ versionContext: options.versionContext,
74
+ minConsensus: options.minConsensus ?? DEFAULT_MIN_CONSENSUS,
75
+ });
76
+ return ctx.query.getRawAccount(request);
77
+ }
78
+
79
+ export function listOwnedAccounts(
80
+ ctx: ThruClientContext,
81
+ owner: BytesLike,
82
+ options: ListOwnedAccountsOptions = {},
83
+ ): Promise<ListOwnedAccountsResponse> {
84
+ const request = create(ListOwnedAccountsRequestSchema, {
85
+ owner: toPubkey(owner, "owner"),
86
+ view: options.view ?? DEFAULT_ACCOUNT_VIEW,
87
+ versionContext: options.versionContext,
88
+ filter: options.filter,
89
+ page: options.page,
90
+ minConsensus: options.minConsensus ?? DEFAULT_MIN_CONSENSUS,
91
+ });
92
+ return ctx.query.listOwnedAccounts(request);
93
+ }
94
+
95
+ export async function createAccount(
96
+ ctx: ThruClientContext,
97
+ options: CreateAccountOptions,
98
+ ): Promise<Transaction> {
99
+ const feePayer = toPubkey(options.publicKey, "publicKey").value;
100
+
101
+ const height = await getBlockHeight(ctx);
102
+ const startSlot = height.finalized;
103
+
104
+ const proofResponse = await generateStateProof(ctx, {
105
+ address: options.publicKey,
106
+ proofType: StateProofType.CREATING,
107
+ targetSlot: startSlot,
108
+ });
109
+
110
+ const proofBytes = proofResponse.proof?.proof;
111
+ if (!proofBytes || proofBytes.length === 0) {
112
+ throw new Error("State proof generation returned empty proof");
113
+ }
114
+
115
+ const program = new Uint8Array(32);
116
+ program[31] = 0x02;
117
+
118
+ const builder = new TransactionBuilder();
119
+ const transaction = builder.build({
120
+ feePayer: { publicKey: feePayer },
121
+ program,
122
+ header: {
123
+ fee: 0n,
124
+ nonce: 0n,
125
+ startSlot,
126
+ expiryAfter: 100,
127
+ computeUnits: 10_000,
128
+ memoryUnits: 10_000,
129
+ stateUnits: 10_000,
130
+ },
131
+ content: {
132
+ proofs: { feePayerStateProof: proofBytes }
133
+ }
134
+ });
135
+
136
+ return transaction;
137
+ }
@@ -0,0 +1,75 @@
1
+ import { create } from "@bufbuild/protobuf";
2
+
3
+ import type { ThruClientContext } from "../core/client";
4
+ import { DEFAULT_BLOCK_VIEW, DEFAULT_MIN_CONSENSUS } from "../defaults";
5
+ import { ConsensusStatus } from "../proto/thru/common/v1/consensus_pb";
6
+ import type { Filter } from "../proto/thru/common/v1/filters_pb";
7
+ import type { PageRequest } from "../proto/thru/common/v1/pagination_pb";
8
+ import { Block, BlockView, RawBlock } from "../proto/thru/core/v1/block_pb";
9
+ import {
10
+ GetBlockRequestSchema,
11
+ GetRawBlockRequestSchema,
12
+ ListBlocksRequestSchema,
13
+ ListBlocksResponse,
14
+ } from "../proto/thru/services/v1/query_service_pb";
15
+ import { isSlotSelector } from "../utils/utils";
16
+ import type { BlockSelector } from "./helpers";
17
+ import { toBlockHash } from "./helpers";
18
+
19
+ export interface BlockQueryOptions {
20
+ view?: BlockView;
21
+ minConsensus?: ConsensusStatus;
22
+ }
23
+
24
+ export interface RawBlockQueryOptions {
25
+ minConsensus?: ConsensusStatus;
26
+ }
27
+
28
+ export interface ListBlocksOptions {
29
+ filter?: Filter;
30
+ page?: PageRequest;
31
+ view?: BlockView;
32
+ minConsensus?: ConsensusStatus;
33
+ }
34
+
35
+ export function getBlock(
36
+ ctx: ThruClientContext,
37
+ selector: BlockSelector,
38
+ options: BlockQueryOptions = {},
39
+ ): Promise<Block> {
40
+ const request = create(GetBlockRequestSchema, {
41
+ selector: isSlotSelector(selector)
42
+ ? { case: "slot", value: typeof selector.slot === "bigint" ? selector.slot : BigInt(selector.slot) }
43
+ : { case: "blockHash", value: toBlockHash(selector.blockHash) },
44
+ view: options.view ?? DEFAULT_BLOCK_VIEW,
45
+ minConsensus: options.minConsensus ?? DEFAULT_MIN_CONSENSUS,
46
+ });
47
+ return ctx.query.getBlock(request);
48
+ }
49
+
50
+ export function getRawBlock(
51
+ ctx: ThruClientContext,
52
+ selector: BlockSelector,
53
+ options: RawBlockQueryOptions = {},
54
+ ): Promise<RawBlock> {
55
+ const request = create(GetRawBlockRequestSchema, {
56
+ selector: isSlotSelector(selector)
57
+ ? { case: "slot", value: typeof selector.slot === "bigint" ? selector.slot : BigInt(selector.slot) }
58
+ : { case: "blockHash", value: toBlockHash(selector.blockHash) },
59
+ minConsensus: options.minConsensus ?? DEFAULT_MIN_CONSENSUS,
60
+ });
61
+ return ctx.query.getRawBlock(request);
62
+ }
63
+
64
+ export function listBlocks(
65
+ ctx: ThruClientContext,
66
+ options: ListBlocksOptions = {},
67
+ ): Promise<ListBlocksResponse> {
68
+ const request = create(ListBlocksRequestSchema, {
69
+ filter: options.filter,
70
+ page: options.page,
71
+ view: options.view ?? DEFAULT_BLOCK_VIEW,
72
+ minConsensus: options.minConsensus ?? DEFAULT_MIN_CONSENSUS,
73
+ });
74
+ return ctx.query.listBlocks(request);
75
+ }
@@ -0,0 +1,20 @@
1
+ import { create } from "@bufbuild/protobuf";
2
+
3
+ import type { ThruClientContext } from "../core/client";
4
+ import type { VersionContext } from "../proto/thru/common/v1/consensus_pb";
5
+ import { Event, GetEventRequestSchema } from "../proto/thru/services/v1/query_service_pb";
6
+
7
+ export interface GetEventOptions {
8
+ versionContext?: VersionContext;
9
+ }
10
+
11
+ export function getEvent(ctx: ThruClientContext, eventId: string, options: GetEventOptions = {}): Promise<Event> {
12
+ if (!eventId) {
13
+ throw new Error("eventId is required");
14
+ }
15
+ const request = create(GetEventRequestSchema, {
16
+ eventId,
17
+ versionContext: options.versionContext,
18
+ });
19
+ return ctx.query.getEvent(request);
20
+ }
@@ -0,0 +1,9 @@
1
+ import { create } from "@bufbuild/protobuf";
2
+
3
+ import type { ThruClientContext } from "../core/client";
4
+ import { GetHeightRequestSchema, GetHeightResponse } from "../proto/thru/services/v1/query_service_pb";
5
+
6
+ export function getBlockHeight(ctx: ThruClientContext): Promise<GetHeightResponse> {
7
+ const request = create(GetHeightRequestSchema);
8
+ return ctx.query.getHeight(request);
9
+ }