@thru/thru-sdk 0.1.19 → 0.1.21
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/README.md +19 -0
- package/dist/{chunk-PH7P5EEU.js → chunk-SHMREHP5.js} +13 -9
- package/dist/chunk-SHMREHP5.js.map +1 -0
- package/dist/client.d.ts +2 -1
- package/dist/client.js +3 -2
- package/dist/client.js.map +1 -1
- package/dist/metafile-esm.json +1 -1
- package/dist/sdk.d.ts +3 -3
- package/dist/sdk.js +1 -1
- package/dist/{transactions-BzD9hYlc.d.ts → transactions-CLezIeXO.d.ts} +20 -18
- package/package.json +7 -3
- package/buf.gen.yaml +0 -12
- package/buf.lock +0 -9
- package/buf.yaml +0 -15
- package/dist/chunk-PH7P5EEU.js.map +0 -1
- package/proto/thru/common/v1/consensus.proto +0 -73
- package/proto/thru/common/v1/errors.proto +0 -65
- package/proto/thru/common/v1/filters.proto +0 -60
- package/proto/thru/common/v1/pagination.proto +0 -45
- package/proto/thru/core/v1/account.proto +0 -137
- package/proto/thru/core/v1/block.proto +0 -80
- package/proto/thru/core/v1/state.proto +0 -35
- package/proto/thru/core/v1/transaction.proto +0 -136
- package/proto/thru/core/v1/types.proto +0 -50
- package/proto/thru/services/v1/command_service.proto +0 -70
- package/proto/thru/services/v1/query_service.proto +0 -344
- package/proto/thru/services/v1/streaming_service.proto +0 -126
- package/thru-ts-client-sdk/__tests__/helpers/test-utils.ts +0 -228
- package/thru-ts-client-sdk/client.ts +0 -10
- package/thru-ts-client-sdk/core/__tests__/bound-client.test.ts +0 -354
- package/thru-ts-client-sdk/core/__tests__/client.test.ts +0 -53
- package/thru-ts-client-sdk/core/bound-client.ts +0 -156
- package/thru-ts-client-sdk/core/client.ts +0 -38
- package/thru-ts-client-sdk/defaults.ts +0 -26
- package/thru-ts-client-sdk/modules/__tests__/accounts.test.ts +0 -406
- package/thru-ts-client-sdk/modules/__tests__/blocks.test.ts +0 -199
- package/thru-ts-client-sdk/modules/__tests__/events.test.ts +0 -74
- package/thru-ts-client-sdk/modules/__tests__/height.test.ts +0 -39
- package/thru-ts-client-sdk/modules/__tests__/helpers.test.ts +0 -288
- package/thru-ts-client-sdk/modules/__tests__/keys.test.ts +0 -55
- package/thru-ts-client-sdk/modules/__tests__/proofs.test.ts +0 -119
- package/thru-ts-client-sdk/modules/__tests__/streaming.test.ts +0 -152
- package/thru-ts-client-sdk/modules/__tests__/transactions.test.ts +0 -730
- package/thru-ts-client-sdk/modules/__tests__/version.test.ts +0 -40
- package/thru-ts-client-sdk/modules/accounts.ts +0 -141
- package/thru-ts-client-sdk/modules/blocks.ts +0 -75
- package/thru-ts-client-sdk/modules/events.ts +0 -20
- package/thru-ts-client-sdk/modules/height.ts +0 -9
- package/thru-ts-client-sdk/modules/helpers.ts +0 -131
- package/thru-ts-client-sdk/modules/keys.ts +0 -29
- package/thru-ts-client-sdk/modules/proofs.ts +0 -20
- package/thru-ts-client-sdk/modules/streaming.ts +0 -133
- package/thru-ts-client-sdk/modules/transactions.ts +0 -374
- package/thru-ts-client-sdk/modules/version.ts +0 -10
- package/thru-ts-client-sdk/proto/buf/validate/validate_pb.ts +0 -4761
- package/thru-ts-client-sdk/proto/google/api/annotations_pb.ts +0 -39
- package/thru-ts-client-sdk/proto/google/api/client_pb.ts +0 -953
- package/thru-ts-client-sdk/proto/google/api/field_behavior_pb.ts +0 -157
- package/thru-ts-client-sdk/proto/google/api/http_pb.ts +0 -474
- package/thru-ts-client-sdk/proto/google/api/launch_stage_pb.ts +0 -118
- package/thru-ts-client-sdk/proto/thru/common/v1/consensus_pb.ts +0 -162
- package/thru-ts-client-sdk/proto/thru/common/v1/errors_pb.ts +0 -129
- package/thru-ts-client-sdk/proto/thru/common/v1/filters_pb.ts +0 -129
- package/thru-ts-client-sdk/proto/thru/common/v1/pagination_pb.ts +0 -79
- package/thru-ts-client-sdk/proto/thru/core/v1/account_pb.ts +0 -359
- package/thru-ts-client-sdk/proto/thru/core/v1/block_pb.ts +0 -259
- package/thru-ts-client-sdk/proto/thru/core/v1/state_pb.ts +0 -103
- package/thru-ts-client-sdk/proto/thru/core/v1/transaction_pb.ts +0 -528
- package/thru-ts-client-sdk/proto/thru/core/v1/types_pb.ts +0 -100
- package/thru-ts-client-sdk/proto/thru/services/v1/command_service_pb.ts +0 -146
- package/thru-ts-client-sdk/proto/thru/services/v1/query_service_pb.ts +0 -819
- package/thru-ts-client-sdk/proto/thru/services/v1/streaming_service_pb.ts +0 -390
- package/thru-ts-client-sdk/sdk.ts +0 -42
- package/thru-ts-client-sdk/test-scripts/counter.ts +0 -469
- package/thru-ts-client-sdk/test-scripts/create-account.ts +0 -74
- package/thru-ts-client-sdk/test-scripts/get-height.ts +0 -52
- package/thru-ts-client-sdk/transactions/Transaction.ts +0 -240
- package/thru-ts-client-sdk/transactions/TransactionBuilder.ts +0 -53
- package/thru-ts-client-sdk/transactions/__tests__/TransactionBuilder.test.ts +0 -411
- package/thru-ts-client-sdk/transactions/__tests__/utils.test.ts +0 -214
- package/thru-ts-client-sdk/transactions/index.ts +0 -3
- package/thru-ts-client-sdk/transactions/types.ts +0 -74
- package/thru-ts-client-sdk/transactions/utils.ts +0 -132
- package/thru-ts-client-sdk/types/types.ts +0 -8
- package/thru-ts-client-sdk/utils/utils.ts +0 -27
- package/tsconfig.json +0 -9
- package/tsup.config.ts +0 -14
- package/vitest.config.ts +0 -31
|
@@ -1,469 +0,0 @@
|
|
|
1
|
-
import { createThruClient } from "../client";
|
|
2
|
-
import { ConsensusStatus } from "../proto/thru/common/v1/consensus_pb";
|
|
3
|
-
import { StateProofType } from "../proto/thru/core/v1/state_pb";
|
|
4
|
-
import type { TransactionBuilderContext } from "../transactions";
|
|
5
|
-
|
|
6
|
-
const sdk = createThruClient({
|
|
7
|
-
// Configure the SDK to connect to the desired Thru cluster
|
|
8
|
-
// endpoint: "https://api.thru.network", // Example endpoint
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
const counterProgramAddress = 'taLNrGlb3VsLLXIlT61QtUwVsrI7M5432DxpJRBfY1tOF3'
|
|
12
|
-
const seed = 'counter'
|
|
13
|
-
const derived = sdk.helpers.deriveProgramAddress({ programAddress: counterProgramAddress, seed: seed })
|
|
14
|
-
const derivedAddress = derived.address
|
|
15
|
-
|
|
16
|
-
const feePayerAddress = 'talmzQqocEh4cR481QpbOjiGoTiFsJLlZqqAQ8TL2PEiGz'
|
|
17
|
-
const feePayerPrivateKeyHex = '76d399fc76ed24691594db813c47b5cbd582c14c89b05ff9c4b49df992050259'
|
|
18
|
-
|
|
19
|
-
const DEFAULT_COMPUTE_UNITS = 300_000_000;
|
|
20
|
-
const DEFAULT_STATE_UNITS = 10_000;
|
|
21
|
-
const DEFAULT_MEMORY_UNITS = 10_000;
|
|
22
|
-
const DEFAULT_EXPIRY_AFTER = 100;
|
|
23
|
-
|
|
24
|
-
// Turn an unsigned integer into a little-endian hex string padded to byteLength bytes
|
|
25
|
-
export function toLittleEndianHex(value: number | bigint, byteLength: number): string {
|
|
26
|
-
let v = typeof value === "bigint" ? value : BigInt(value);
|
|
27
|
-
const bytes = new Uint8Array(byteLength);
|
|
28
|
-
for (let i = 0; i < byteLength; i++) {
|
|
29
|
-
bytes[i] = Number(v & 0xffn);
|
|
30
|
-
v >>= 8n;
|
|
31
|
-
}
|
|
32
|
-
return Array.from(bytes, b => b.toString(16).padStart(2, "0")).join("");
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// Convenience wrappers matching the screenshot
|
|
36
|
-
export const u32ToHexLE = (value: number | bigint) => toLittleEndianHex(value, 4);
|
|
37
|
-
export const u16ToHexLE = (value: number | bigint) => toLittleEndianHex(value, 2);
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const getIncrementCounterAccountInstructionDataHex = async () => {
|
|
41
|
-
const instructionCreate = u32ToHexLE(1)
|
|
42
|
-
const accountIndex = u16ToHexLE(2)
|
|
43
|
-
const instructionData = instructionCreate + accountIndex
|
|
44
|
-
return instructionData;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const accountDataToHex = (data: Uint8Array): string => {
|
|
48
|
-
let dataToHex = Array.from(data, b => b.toString(16).padStart(2, "0")).join("");
|
|
49
|
-
return dataToHex;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function hexToBytes(hex: string): Uint8Array {
|
|
53
|
-
const normalized = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
54
|
-
if (normalized.length % 2 !== 0) {
|
|
55
|
-
throw new Error("Private key hex must contain an even number of characters");
|
|
56
|
-
}
|
|
57
|
-
const bytes = new Uint8Array(normalized.length / 2);
|
|
58
|
-
for (let i = 0; i < normalized.length; i += 2) {
|
|
59
|
-
bytes[i / 2] = parseInt(normalized.substring(i, i + 2), 16);
|
|
60
|
-
}
|
|
61
|
-
return bytes;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Test 1: Using instructionData as a hex string (backward compatible)
|
|
65
|
-
const incrementCounterAccountInstructionWithString = async () => {
|
|
66
|
-
const instructionDataHex = await getIncrementCounterAccountInstructionDataHex();
|
|
67
|
-
const feePayerPublicKey = sdk.helpers.decodeAddress(feePayerAddress);
|
|
68
|
-
const feePayerPrivateKey = hexToBytes(feePayerPrivateKeyHex);
|
|
69
|
-
|
|
70
|
-
console.log("\n=== Test 1: Using instructionData as hex string ===");
|
|
71
|
-
const transaction = await sdk.transactions.build({
|
|
72
|
-
feePayer: {
|
|
73
|
-
publicKey: feePayerPublicKey,
|
|
74
|
-
privateKey: feePayerPrivateKey,
|
|
75
|
-
},
|
|
76
|
-
program: counterProgramAddress,
|
|
77
|
-
header: {
|
|
78
|
-
fee: 0n,
|
|
79
|
-
computeUnits: DEFAULT_COMPUTE_UNITS,
|
|
80
|
-
stateUnits: DEFAULT_STATE_UNITS,
|
|
81
|
-
memoryUnits: DEFAULT_MEMORY_UNITS,
|
|
82
|
-
expiryAfter: DEFAULT_EXPIRY_AFTER,
|
|
83
|
-
},
|
|
84
|
-
accounts: {
|
|
85
|
-
readWrite: [derivedAddress],
|
|
86
|
-
},
|
|
87
|
-
instructionData: instructionDataHex,
|
|
88
|
-
})
|
|
89
|
-
|
|
90
|
-
await transaction.sign(feePayerPrivateKey);
|
|
91
|
-
const rawTransaction = transaction.toWire();
|
|
92
|
-
const submittedSignature = await sdk.transactions.send(rawTransaction);
|
|
93
|
-
console.log("Submitted transaction signature:", submittedSignature);
|
|
94
|
-
return submittedSignature;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// Test 2: Using instructionData as a function (new capability)
|
|
98
|
-
const incrementCounterAccountInstructionWithFunction = async () => {
|
|
99
|
-
const feePayerPublicKey = sdk.helpers.decodeAddress(feePayerAddress);
|
|
100
|
-
const feePayerPrivateKey = hexToBytes(feePayerPrivateKeyHex);
|
|
101
|
-
const derivedAddressBytes = sdk.helpers.decodeAddress(derivedAddress);
|
|
102
|
-
|
|
103
|
-
console.log("\n=== Test 2: Using instructionData as a function ===");
|
|
104
|
-
|
|
105
|
-
// This function dynamically calculates the account index based on the transaction context
|
|
106
|
-
const instructionDataFunction = (context: TransactionBuilderContext): Uint8Array => {
|
|
107
|
-
console.log("Function called with context:");
|
|
108
|
-
console.log(` - Total accounts: ${context.accounts.length}`);
|
|
109
|
-
// Log account addresses as hex for debugging
|
|
110
|
-
context.accounts.forEach((acc, i) => {
|
|
111
|
-
const hex = Array.from(acc).map(b => b.toString(16).padStart(2, "0")).join("");
|
|
112
|
-
console.log(` - Account [${i}]: ${hex.substring(0, 16)}...`);
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
// Find the index of the derivedAddress account
|
|
116
|
-
const accountIndex = context.getAccountIndex(derivedAddressBytes);
|
|
117
|
-
console.log(` - Derived address index (should be 2): ${accountIndex}`);
|
|
118
|
-
|
|
119
|
-
// Build instruction data: instructionCreate (u32) + accountIndex (u16)
|
|
120
|
-
const instructionCreate = 1; // Increment instruction
|
|
121
|
-
const instructionBytes = new Uint8Array(6); // 4 bytes for u32 + 2 bytes for u16
|
|
122
|
-
|
|
123
|
-
// Write u32 instructionCreate (little-endian)
|
|
124
|
-
instructionBytes[0] = instructionCreate & 0xff;
|
|
125
|
-
instructionBytes[1] = (instructionCreate >> 8) & 0xff;
|
|
126
|
-
instructionBytes[2] = (instructionCreate >> 16) & 0xff;
|
|
127
|
-
instructionBytes[3] = (instructionCreate >> 24) & 0xff;
|
|
128
|
-
|
|
129
|
-
// Write u16 accountIndex (little-endian)
|
|
130
|
-
instructionBytes[4] = accountIndex & 0xff;
|
|
131
|
-
instructionBytes[5] = (accountIndex >> 8) & 0xff;
|
|
132
|
-
|
|
133
|
-
const instructionHex = Array.from(instructionBytes).map(b => b.toString(16).padStart(2, "0")).join("");
|
|
134
|
-
console.log(` - Generated instruction data: ${instructionHex}`);
|
|
135
|
-
console.log(` - Expected format: 01000000 (instruction=1) + ${u16ToHexLE(accountIndex)} (accountIndex)`);
|
|
136
|
-
|
|
137
|
-
return instructionBytes;
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
const transaction = await sdk.transactions.build({
|
|
141
|
-
feePayer: {
|
|
142
|
-
publicKey: feePayerPublicKey,
|
|
143
|
-
privateKey: feePayerPrivateKey,
|
|
144
|
-
},
|
|
145
|
-
program: counterProgramAddress,
|
|
146
|
-
header: {
|
|
147
|
-
fee: 0n,
|
|
148
|
-
computeUnits: DEFAULT_COMPUTE_UNITS,
|
|
149
|
-
stateUnits: DEFAULT_STATE_UNITS,
|
|
150
|
-
memoryUnits: DEFAULT_MEMORY_UNITS,
|
|
151
|
-
expiryAfter: DEFAULT_EXPIRY_AFTER,
|
|
152
|
-
},
|
|
153
|
-
accounts: {
|
|
154
|
-
readWrite: [derivedAddress],
|
|
155
|
-
},
|
|
156
|
-
instructionData: instructionDataFunction,
|
|
157
|
-
})
|
|
158
|
-
|
|
159
|
-
await transaction.sign(feePayerPrivateKey);
|
|
160
|
-
const rawTransaction = transaction.toWire();
|
|
161
|
-
const submittedSignature = await sdk.transactions.send(rawTransaction);
|
|
162
|
-
console.log("Submitted transaction signature:", submittedSignature);
|
|
163
|
-
return submittedSignature;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
const incrementCounterAccountInstruction = async () => {
|
|
167
|
-
// Run both tests to show both APIs work
|
|
168
|
-
await incrementCounterAccountInstructionWithString();
|
|
169
|
-
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
170
|
-
await incrementCounterAccountInstructionWithFunction();
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
async function main() {
|
|
175
|
-
// Check if counter account exists
|
|
176
|
-
let accountData1;
|
|
177
|
-
let accountExists = false;
|
|
178
|
-
|
|
179
|
-
try {
|
|
180
|
-
accountData1 = await sdk.accounts.get(derivedAddress);
|
|
181
|
-
accountExists = accountData1.data !== undefined;
|
|
182
|
-
} catch (error: any) {
|
|
183
|
-
// Account doesn't exist - this is expected for new accounts
|
|
184
|
-
if (error?.code === 5 || error?.rawMessage?.includes("not found")) {
|
|
185
|
-
accountExists = false;
|
|
186
|
-
console.log("Counter account does not exist yet");
|
|
187
|
-
} else {
|
|
188
|
-
throw error; // Re-throw unexpected errors
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
if (accountExists && accountData1) {
|
|
193
|
-
console.log("Counter account already exists");
|
|
194
|
-
if (accountData1.data?.data) {
|
|
195
|
-
console.log("Account Data:", accountDataToHex(accountData1.data.data));
|
|
196
|
-
}
|
|
197
|
-
} else {
|
|
198
|
-
console.log("Counter account does not exist, creating it...");
|
|
199
|
-
|
|
200
|
-
// Choose which method to use (function or string)
|
|
201
|
-
// Using function method to demonstrate the new capability
|
|
202
|
-
await createCounterAccountWithFunction();
|
|
203
|
-
|
|
204
|
-
// Wait for account to be created
|
|
205
|
-
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
206
|
-
|
|
207
|
-
// Verify account was created
|
|
208
|
-
try {
|
|
209
|
-
accountData1 = await sdk.accounts.get(derivedAddress);
|
|
210
|
-
if (accountData1.data) {
|
|
211
|
-
console.log("Counter account created successfully!");
|
|
212
|
-
if (accountData1.data?.data) {
|
|
213
|
-
console.log("Account Data:", accountDataToHex(accountData1.data.data));
|
|
214
|
-
} else {
|
|
215
|
-
console.error("Failed to get account data");
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
} else {
|
|
219
|
-
console.error("Failed to create counter account");
|
|
220
|
-
return;
|
|
221
|
-
}
|
|
222
|
-
} catch (error: any) {
|
|
223
|
-
console.error("Failed to verify counter account creation:", error);
|
|
224
|
-
return;
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
// Now increment the counter
|
|
229
|
-
console.log("\n=== Incrementing Counter ===");
|
|
230
|
-
await incrementCounterAccountInstruction();
|
|
231
|
-
|
|
232
|
-
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
233
|
-
|
|
234
|
-
try {
|
|
235
|
-
const accountData2 = await sdk.accounts.get(derivedAddress);
|
|
236
|
-
if (accountData2.data?.data) {
|
|
237
|
-
console.log("Incremented Account Data:", accountDataToHex(accountData2.data!.data));
|
|
238
|
-
}
|
|
239
|
-
} catch (error: any) {
|
|
240
|
-
console.warn("Failed to fetch account data after increment:", error);
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
console.log("Starting counter script");
|
|
245
|
-
main()
|
|
246
|
-
|
|
247
|
-
function seedToHex32Padded(seed: string): string {
|
|
248
|
-
const bytes = new TextEncoder().encode(seed);
|
|
249
|
-
const padded = new Uint8Array(32);
|
|
250
|
-
padded.set(bytes.slice(0, 32));
|
|
251
|
-
return Array.from(padded, b => b.toString(16).padStart(2, "0")).join("");
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
// Create counter account instruction data (instruction 0)
|
|
255
|
-
const getCreateCounterAccountInstructionData = async (): Promise<Uint8Array> => {
|
|
256
|
-
const instructionCreate = 0; // Create instruction
|
|
257
|
-
const blockHeight = await sdk.blocks.getBlockHeight();
|
|
258
|
-
const stateProof = await sdk.proofs.generate({
|
|
259
|
-
proofType: StateProofType.CREATING,
|
|
260
|
-
address: derivedAddress,
|
|
261
|
-
targetSlot: blockHeight.finalized,
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
if (!stateProof.proof || stateProof.proof.proof.length === 0) {
|
|
265
|
-
throw new Error("No state proof returned");
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
const seedBytes = new TextEncoder().encode(seed);
|
|
269
|
-
const seedPadded = new Uint8Array(32);
|
|
270
|
-
seedPadded.set(seedBytes.slice(0, 32));
|
|
271
|
-
|
|
272
|
-
// Build instruction data:
|
|
273
|
-
// - instructionCreate (u32, 4 bytes)
|
|
274
|
-
// - accountIndex (u16, 2 bytes) - will be set dynamically via function
|
|
275
|
-
// - seed (32 bytes)
|
|
276
|
-
// - stateProofSize (u32, 4 bytes)
|
|
277
|
-
// - stateProof (variable length)
|
|
278
|
-
const stateProofBytes = new Uint8Array(stateProof.proof.proof);
|
|
279
|
-
const instructionData = new Uint8Array(4 + 2 + 32 + 4 + stateProofBytes.length);
|
|
280
|
-
let offset = 0;
|
|
281
|
-
|
|
282
|
-
// Write instructionCreate (u32, little-endian)
|
|
283
|
-
instructionData[offset++] = instructionCreate & 0xff;
|
|
284
|
-
instructionData[offset++] = (instructionCreate >> 8) & 0xff;
|
|
285
|
-
instructionData[offset++] = (instructionCreate >> 16) & 0xff;
|
|
286
|
-
instructionData[offset++] = (instructionCreate >> 24) & 0xff;
|
|
287
|
-
|
|
288
|
-
// accountIndex will be written by the function
|
|
289
|
-
offset += 2;
|
|
290
|
-
|
|
291
|
-
// Write seed (32 bytes)
|
|
292
|
-
instructionData.set(seedPadded, offset);
|
|
293
|
-
offset += 32;
|
|
294
|
-
|
|
295
|
-
// Write stateProofSize (u32, little-endian)
|
|
296
|
-
const proofSize = stateProofBytes.length;
|
|
297
|
-
instructionData[offset++] = proofSize & 0xff;
|
|
298
|
-
instructionData[offset++] = (proofSize >> 8) & 0xff;
|
|
299
|
-
instructionData[offset++] = (proofSize >> 16) & 0xff;
|
|
300
|
-
instructionData[offset++] = (proofSize >> 24) & 0xff;
|
|
301
|
-
|
|
302
|
-
// Write stateProof
|
|
303
|
-
instructionData.set(stateProofBytes, offset);
|
|
304
|
-
|
|
305
|
-
return instructionData;
|
|
306
|
-
};
|
|
307
|
-
|
|
308
|
-
// Create counter account using instructionData as a function
|
|
309
|
-
const createCounterAccountWithFunction = async (): Promise<string> => {
|
|
310
|
-
const feePayerPublicKey = sdk.helpers.decodeAddress(feePayerAddress);
|
|
311
|
-
const feePayerPrivateKey = hexToBytes(feePayerPrivateKeyHex);
|
|
312
|
-
const derivedAddressBytes = sdk.helpers.decodeAddress(derivedAddress);
|
|
313
|
-
|
|
314
|
-
console.log("\n=== Creating Counter Account (using function) ===");
|
|
315
|
-
|
|
316
|
-
// Get the base instruction data (without accountIndex)
|
|
317
|
-
const baseInstructionData = await getCreateCounterAccountInstructionData();
|
|
318
|
-
|
|
319
|
-
// Function that dynamically sets the account index
|
|
320
|
-
const instructionDataFunction = (context: TransactionBuilderContext): Uint8Array => {
|
|
321
|
-
console.log("Function called with context:");
|
|
322
|
-
console.log(` - Total accounts: ${context.accounts.length}`);
|
|
323
|
-
|
|
324
|
-
// Find the index of the derivedAddress account
|
|
325
|
-
const accountIndex = context.getAccountIndex(derivedAddressBytes);
|
|
326
|
-
console.log(` - Derived address index: ${accountIndex}`);
|
|
327
|
-
|
|
328
|
-
// Copy the base instruction data and set the account index
|
|
329
|
-
const instructionData = new Uint8Array(baseInstructionData);
|
|
330
|
-
|
|
331
|
-
// Write accountIndex at offset 4 (after the 4-byte instructionCreate)
|
|
332
|
-
instructionData[4] = accountIndex & 0xff;
|
|
333
|
-
instructionData[5] = (accountIndex >> 8) & 0xff;
|
|
334
|
-
|
|
335
|
-
const instructionHex = Array.from(instructionData).map(b => b.toString(16).padStart(2, "0")).join("");
|
|
336
|
-
console.log(` - Generated instruction data (first 100 chars): ${instructionHex.substring(0, 100)}...`);
|
|
337
|
-
|
|
338
|
-
return instructionData;
|
|
339
|
-
};
|
|
340
|
-
|
|
341
|
-
const { transaction, signature, rawTransaction } = await sdk.transactions.buildAndSign({
|
|
342
|
-
feePayer: {
|
|
343
|
-
publicKey: feePayerPublicKey,
|
|
344
|
-
privateKey: feePayerPrivateKey,
|
|
345
|
-
},
|
|
346
|
-
program: counterProgramAddress,
|
|
347
|
-
header: {
|
|
348
|
-
fee: 0n,
|
|
349
|
-
computeUnits: DEFAULT_COMPUTE_UNITS,
|
|
350
|
-
stateUnits: DEFAULT_STATE_UNITS,
|
|
351
|
-
memoryUnits: DEFAULT_MEMORY_UNITS,
|
|
352
|
-
expiryAfter: DEFAULT_EXPIRY_AFTER,
|
|
353
|
-
},
|
|
354
|
-
accounts: {
|
|
355
|
-
readWrite: [derivedAddress],
|
|
356
|
-
},
|
|
357
|
-
instructionData: instructionDataFunction,
|
|
358
|
-
});
|
|
359
|
-
|
|
360
|
-
console.log("Local signature:", Array.from(signature, b => b.toString(16).padStart(2, "0")).join(""));
|
|
361
|
-
|
|
362
|
-
const submittedSignature = await sdk.transactions.send(rawTransaction);
|
|
363
|
-
console.log("Submitted transaction signature:", submittedSignature);
|
|
364
|
-
|
|
365
|
-
// Wait for transaction to be processed
|
|
366
|
-
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
367
|
-
|
|
368
|
-
// Track the transaction
|
|
369
|
-
let finalized = false;
|
|
370
|
-
try {
|
|
371
|
-
for await (const update of sdk.transactions.track(submittedSignature, { timeoutMs: 60000 })) {
|
|
372
|
-
const consumed = update.executionResult?.consumedComputeUnits ?? 0;
|
|
373
|
-
const statusKey = ConsensusStatus[update.consensusStatus];
|
|
374
|
-
console.log("Track update:", statusKey, "consumed CU:", consumed);
|
|
375
|
-
if (update.executionResult) {
|
|
376
|
-
finalized = true;
|
|
377
|
-
}
|
|
378
|
-
if (
|
|
379
|
-
update.consensusStatus === ConsensusStatus.FINALIZED ||
|
|
380
|
-
update.consensusStatus === ConsensusStatus.CLUSTER_EXECUTED
|
|
381
|
-
) {
|
|
382
|
-
finalized = true;
|
|
383
|
-
break;
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
} catch (err) {
|
|
387
|
-
console.warn("Track transaction stream ended with error:", err);
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
if (!finalized) {
|
|
391
|
-
console.warn("Transaction not finalized before timeout");
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
const transactionStatus = await sdk.transactions.getStatus(submittedSignature);
|
|
395
|
-
console.log("Submitted transaction status:", transactionStatus);
|
|
396
|
-
|
|
397
|
-
return submittedSignature;
|
|
398
|
-
};
|
|
399
|
-
|
|
400
|
-
// Create counter account using instructionData as hex string
|
|
401
|
-
const createCounterAccountWithString = async (): Promise<string> => {
|
|
402
|
-
const feePayerPublicKey = sdk.helpers.decodeAddress(feePayerAddress);
|
|
403
|
-
const feePayerPrivateKey = hexToBytes(feePayerPrivateKeyHex);
|
|
404
|
-
|
|
405
|
-
console.log("\n=== Creating Counter Account (using hex string) ===");
|
|
406
|
-
|
|
407
|
-
// Get the base instruction data
|
|
408
|
-
const baseInstructionData = await getCreateCounterAccountInstructionData();
|
|
409
|
-
|
|
410
|
-
// For hex string version, we need to know the account index ahead of time
|
|
411
|
-
// Account order: [feePayer (0), program (1), derivedAddress (2)]
|
|
412
|
-
const accountIndex = 2;
|
|
413
|
-
|
|
414
|
-
// Set the account index in the instruction data
|
|
415
|
-
const instructionData = new Uint8Array(baseInstructionData);
|
|
416
|
-
instructionData[4] = accountIndex & 0xff;
|
|
417
|
-
instructionData[5] = (accountIndex >> 8) & 0xff;
|
|
418
|
-
|
|
419
|
-
// Convert to hex string
|
|
420
|
-
const instructionDataHex = Array.from(instructionData).map(b => b.toString(16).padStart(2, "0")).join("");
|
|
421
|
-
console.log(`Instruction Data Hex (first 100 chars): ${instructionDataHex.substring(0, 100)}...`);
|
|
422
|
-
|
|
423
|
-
const { transaction, signature, rawTransaction } = await sdk.transactions.buildAndSign({
|
|
424
|
-
feePayer: {
|
|
425
|
-
publicKey: feePayerPublicKey,
|
|
426
|
-
privateKey: feePayerPrivateKey,
|
|
427
|
-
},
|
|
428
|
-
program: counterProgramAddress,
|
|
429
|
-
header: {
|
|
430
|
-
fee: 0n,
|
|
431
|
-
computeUnits: DEFAULT_COMPUTE_UNITS,
|
|
432
|
-
stateUnits: DEFAULT_STATE_UNITS,
|
|
433
|
-
memoryUnits: DEFAULT_MEMORY_UNITS,
|
|
434
|
-
expiryAfter: DEFAULT_EXPIRY_AFTER,
|
|
435
|
-
},
|
|
436
|
-
accounts: {
|
|
437
|
-
readWrite: [derivedAddress],
|
|
438
|
-
},
|
|
439
|
-
instructionData: instructionDataHex,
|
|
440
|
-
});
|
|
441
|
-
|
|
442
|
-
console.log("Local signature:", Array.from(signature, b => b.toString(16).padStart(2, "0")).join(""));
|
|
443
|
-
|
|
444
|
-
const submittedSignature = await sdk.transactions.send(rawTransaction);
|
|
445
|
-
console.log("Submitted transaction signature:", submittedSignature);
|
|
446
|
-
|
|
447
|
-
// Wait and track
|
|
448
|
-
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
449
|
-
|
|
450
|
-
let finalized = false;
|
|
451
|
-
try {
|
|
452
|
-
for await (const update of sdk.transactions.track(submittedSignature, { timeoutMs: 60000 })) {
|
|
453
|
-
const consumed = update.executionResult?.consumedComputeUnits ?? 0;
|
|
454
|
-
const statusKey = ConsensusStatus[update.consensusStatus];
|
|
455
|
-
console.log("Track update:", statusKey, "consumed CU:", consumed);
|
|
456
|
-
if (
|
|
457
|
-
update.consensusStatus === ConsensusStatus.FINALIZED ||
|
|
458
|
-
update.consensusStatus === ConsensusStatus.CLUSTER_EXECUTED
|
|
459
|
-
) {
|
|
460
|
-
finalized = true;
|
|
461
|
-
break;
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
} catch (err) {
|
|
465
|
-
console.warn("Track transaction stream ended with error:", err);
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
return submittedSignature;
|
|
469
|
-
};
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { bytesToHex } from "@noble/hashes/utils";
|
|
2
|
-
import { createThruClient } from "../client";
|
|
3
|
-
import { ConsensusStatus } from "../proto/thru/common/v1/consensus_pb";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const sdk = createThruClient({
|
|
7
|
-
// endpoint: "https://api.thru.network", // Set to your cluster endpoint.
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
// Replace with the account you want to create and its 32-byte private key.
|
|
11
|
-
|
|
12
|
-
const keypair = await sdk.keys.generateKeyPair()
|
|
13
|
-
const targetAccountAddress = keypair.address
|
|
14
|
-
const targetAccountPrivateKey = keypair.privateKey
|
|
15
|
-
|
|
16
|
-
console.log("Target account address:", targetAccountAddress);
|
|
17
|
-
console.log("Target account private key:", targetAccountPrivateKey);
|
|
18
|
-
const targetAccountPrivateKeyHex = bytesToHex(targetAccountPrivateKey);
|
|
19
|
-
console.log("Target account private key hex:", targetAccountPrivateKeyHex);
|
|
20
|
-
|
|
21
|
-
async function fetchAccountSnapshot(label: string, address: string): Promise<void> {
|
|
22
|
-
try {
|
|
23
|
-
const account = await sdk.accounts.get(address);
|
|
24
|
-
const consensus = account.consensusStatus != null
|
|
25
|
-
? ConsensusStatus[account.consensusStatus]
|
|
26
|
-
: "UNKNOWN";
|
|
27
|
-
const slot = account.versionContext?.slot ?? 0n;
|
|
28
|
-
const balance = account.meta?.balance ?? 0n;
|
|
29
|
-
const stateCounter = account.meta?.stateCounter ?? 0n;
|
|
30
|
-
|
|
31
|
-
console.log(
|
|
32
|
-
`${label} account status: consensus=${consensus}, slot=${slot.toString()}, balance=${balance.toString()}, stateCounter=${stateCounter.toString()}`,
|
|
33
|
-
);
|
|
34
|
-
} catch (err) {
|
|
35
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
36
|
-
console.log(`${label} account lookup failed: ${message}`);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
async function run(): Promise<void> {
|
|
41
|
-
console.log("Preparing create account transaction");
|
|
42
|
-
|
|
43
|
-
await fetchAccountSnapshot("Pre-create", targetAccountAddress);
|
|
44
|
-
|
|
45
|
-
const feePayerPublicKey = sdk.helpers.decodeAddress(targetAccountAddress);
|
|
46
|
-
const feePayerPrivateKey = targetAccountPrivateKey
|
|
47
|
-
|
|
48
|
-
const transaction = await sdk.accounts.create({
|
|
49
|
-
publicKey: feePayerPublicKey,
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
await transaction.sign(feePayerPrivateKey);
|
|
53
|
-
|
|
54
|
-
const rawTransaction = transaction.toWire();
|
|
55
|
-
|
|
56
|
-
console.log("Submitting transaction");
|
|
57
|
-
const submittedSignature = await sdk.transactions.send(rawTransaction);
|
|
58
|
-
// Allow some time for the cluster to reflect the new account state.
|
|
59
|
-
await new Promise(resolve => setTimeout(resolve, 2_000));
|
|
60
|
-
const transactionStatus = await sdk.transactions.getStatus(submittedSignature);
|
|
61
|
-
console.log("Submitted transaction status:", transactionStatus);
|
|
62
|
-
console.log("Submitted transaction signature:", submittedSignature);
|
|
63
|
-
|
|
64
|
-
// await trackTransaction(submittedSignature);
|
|
65
|
-
|
|
66
|
-
// Allow some time for the cluster to reflect the new account state.
|
|
67
|
-
await new Promise(resolve => setTimeout(resolve, 2_000));
|
|
68
|
-
|
|
69
|
-
await fetchAccountSnapshot("Post-create", targetAccountAddress);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
run().catch(error => {
|
|
73
|
-
console.error("Create account script failed:", error);
|
|
74
|
-
});
|
|
@@ -1,52 +0,0 @@
|
|
|
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 = "https://grpc-web.alphanet.thruput.org";
|
|
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
|
-
});
|