@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,199 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it, vi } from "vitest";
|
|
2
|
-
import { createMockBlock, createMockContext, createMockListBlocksResponse } from "../../__tests__/helpers/test-utils";
|
|
3
|
-
import { ConsensusStatus } from "../../proto/thru/common/v1/consensus_pb";
|
|
4
|
-
import { BlockView } from "../../proto/thru/core/v1/block_pb";
|
|
5
|
-
import { getBlock, getRawBlock, listBlocks } from "../blocks";
|
|
6
|
-
|
|
7
|
-
describe("blocks", () => {
|
|
8
|
-
describe("getBlock", () => {
|
|
9
|
-
it("should get block by slot (number)", async () => {
|
|
10
|
-
const ctx = createMockContext();
|
|
11
|
-
const mockBlock = createMockBlock({ header: { slot: 1000n } });
|
|
12
|
-
vi.spyOn(ctx.query, "getBlock").mockResolvedValue(mockBlock);
|
|
13
|
-
|
|
14
|
-
const result = await getBlock(ctx, { slot: 1000 });
|
|
15
|
-
|
|
16
|
-
expect(result).toBe(mockBlock);
|
|
17
|
-
expect(ctx.query.getBlock).toHaveBeenCalledTimes(1);
|
|
18
|
-
const callArgs = (ctx.query.getBlock as any).mock.calls[0][0];
|
|
19
|
-
expect(callArgs.selector.case).toBe("slot");
|
|
20
|
-
expect(callArgs.selector.value).toBe(1000n);
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it("should get block by slot (bigint)", async () => {
|
|
24
|
-
const ctx = createMockContext();
|
|
25
|
-
const mockBlock = createMockBlock({ header: { slot: 1000n } });
|
|
26
|
-
vi.spyOn(ctx.query, "getBlock").mockResolvedValue(mockBlock);
|
|
27
|
-
|
|
28
|
-
const result = await getBlock(ctx, { slot: 1000n });
|
|
29
|
-
|
|
30
|
-
expect(result).toBe(mockBlock);
|
|
31
|
-
const callArgs = (ctx.query.getBlock as any).mock.calls[0][0];
|
|
32
|
-
expect(callArgs.selector.case).toBe("slot");
|
|
33
|
-
expect(callArgs.selector.value).toBe(1000n);
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
it("should get block by blockHash", async () => {
|
|
37
|
-
const ctx = createMockContext();
|
|
38
|
-
const mockBlock = createMockBlock();
|
|
39
|
-
const blockHash = new Uint8Array(32);
|
|
40
|
-
blockHash.fill(0x42);
|
|
41
|
-
vi.spyOn(ctx.query, "getBlock").mockResolvedValue(mockBlock);
|
|
42
|
-
|
|
43
|
-
const result = await getBlock(ctx, { blockHash });
|
|
44
|
-
|
|
45
|
-
expect(result).toBe(mockBlock);
|
|
46
|
-
const callArgs = (ctx.query.getBlock as any).mock.calls[0][0];
|
|
47
|
-
expect(callArgs.selector.case).toBe("blockHash");
|
|
48
|
-
expect(callArgs.selector.value.value).toEqual(blockHash);
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
it("should use default view when not provided", async () => {
|
|
52
|
-
const ctx = createMockContext();
|
|
53
|
-
const mockBlock = createMockBlock();
|
|
54
|
-
vi.spyOn(ctx.query, "getBlock").mockResolvedValue(mockBlock);
|
|
55
|
-
|
|
56
|
-
await getBlock(ctx, { slot: 1000 });
|
|
57
|
-
|
|
58
|
-
const callArgs = (ctx.query.getBlock as any).mock.calls[0][0];
|
|
59
|
-
expect(callArgs.view).toBe(BlockView.FULL);
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it("should use custom view when provided", async () => {
|
|
63
|
-
const ctx = createMockContext();
|
|
64
|
-
const mockBlock = createMockBlock();
|
|
65
|
-
vi.spyOn(ctx.query, "getBlock").mockResolvedValue(mockBlock);
|
|
66
|
-
|
|
67
|
-
await getBlock(ctx, { slot: 1000 }, { view: BlockView.HEADER_ONLY });
|
|
68
|
-
|
|
69
|
-
const callArgs = (ctx.query.getBlock as any).mock.calls[0][0];
|
|
70
|
-
expect(callArgs.view).toBe(BlockView.HEADER_ONLY);
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
it("should use default minConsensus when not provided", async () => {
|
|
74
|
-
const ctx = createMockContext();
|
|
75
|
-
const mockBlock = createMockBlock();
|
|
76
|
-
vi.spyOn(ctx.query, "getBlock").mockResolvedValue(mockBlock);
|
|
77
|
-
|
|
78
|
-
await getBlock(ctx, { slot: 1000 });
|
|
79
|
-
|
|
80
|
-
const callArgs = (ctx.query.getBlock as any).mock.calls[0][0];
|
|
81
|
-
expect(callArgs.minConsensus).toBe(ConsensusStatus.UNSPECIFIED);
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
it("should use custom minConsensus when provided", async () => {
|
|
85
|
-
const ctx = createMockContext();
|
|
86
|
-
const mockBlock = createMockBlock();
|
|
87
|
-
vi.spyOn(ctx.query, "getBlock").mockResolvedValue(mockBlock);
|
|
88
|
-
|
|
89
|
-
await getBlock(ctx, { slot: 1000 }, { minConsensus: ConsensusStatus.FINALIZED });
|
|
90
|
-
|
|
91
|
-
const callArgs = (ctx.query.getBlock as any).mock.calls[0][0];
|
|
92
|
-
expect(callArgs.minConsensus).toBe(ConsensusStatus.FINALIZED);
|
|
93
|
-
});
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
describe("getRawBlock", () => {
|
|
97
|
-
it("should get raw block by slot", async () => {
|
|
98
|
-
const ctx = createMockContext();
|
|
99
|
-
const mockRawBlock = { slot: 1000n, rawBlock: new Uint8Array([1, 2, 3]) };
|
|
100
|
-
vi.spyOn(ctx.query, "getRawBlock").mockResolvedValue(mockRawBlock as any);
|
|
101
|
-
|
|
102
|
-
const result = await getRawBlock(ctx, { slot: 1000 });
|
|
103
|
-
|
|
104
|
-
expect(result).toBe(mockRawBlock);
|
|
105
|
-
expect(ctx.query.getRawBlock).toHaveBeenCalledTimes(1);
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
it("should get raw block by blockHash", async () => {
|
|
109
|
-
const ctx = createMockContext();
|
|
110
|
-
const blockHash = new Uint8Array(32);
|
|
111
|
-
blockHash.fill(0x42);
|
|
112
|
-
const mockRawBlock = { slot: 1000n, rawBlock: new Uint8Array([1, 2, 3]) };
|
|
113
|
-
vi.spyOn(ctx.query, "getRawBlock").mockResolvedValue(mockRawBlock as any);
|
|
114
|
-
|
|
115
|
-
const result = await getRawBlock(ctx, { blockHash });
|
|
116
|
-
|
|
117
|
-
expect(result).toBe(mockRawBlock);
|
|
118
|
-
const callArgs = (ctx.query.getRawBlock as any).mock.calls[0][0];
|
|
119
|
-
expect(callArgs.selector.case).toBe("blockHash");
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
it("should use default minConsensus", async () => {
|
|
123
|
-
const ctx = createMockContext();
|
|
124
|
-
const mockRawBlock = { slot: 1000n, rawBlock: new Uint8Array() };
|
|
125
|
-
vi.spyOn(ctx.query, "getRawBlock").mockResolvedValue(mockRawBlock as any);
|
|
126
|
-
|
|
127
|
-
await getRawBlock(ctx, { slot: 1000 });
|
|
128
|
-
|
|
129
|
-
const callArgs = (ctx.query.getRawBlock as any).mock.calls[0][0];
|
|
130
|
-
expect(callArgs.minConsensus).toBe(ConsensusStatus.UNSPECIFIED);
|
|
131
|
-
});
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
describe("listBlocks", () => {
|
|
135
|
-
it("should list blocks with default options", async () => {
|
|
136
|
-
const ctx = createMockContext();
|
|
137
|
-
const mockResponse = createMockListBlocksResponse();
|
|
138
|
-
vi.spyOn(ctx.query, "listBlocks").mockResolvedValue(mockResponse);
|
|
139
|
-
|
|
140
|
-
const result = await listBlocks(ctx);
|
|
141
|
-
|
|
142
|
-
expect(result).toBe(mockResponse);
|
|
143
|
-
expect(ctx.query.listBlocks).toHaveBeenCalledTimes(1);
|
|
144
|
-
const callArgs = (ctx.query.listBlocks as any).mock.calls[0][0];
|
|
145
|
-
expect(callArgs.view).toBe(BlockView.FULL);
|
|
146
|
-
expect(callArgs.minConsensus).toBe(ConsensusStatus.UNSPECIFIED);
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
it("should list blocks with custom view", async () => {
|
|
150
|
-
const ctx = createMockContext();
|
|
151
|
-
const mockResponse = createMockListBlocksResponse();
|
|
152
|
-
vi.spyOn(ctx.query, "listBlocks").mockResolvedValue(mockResponse);
|
|
153
|
-
|
|
154
|
-
await listBlocks(ctx, { view: BlockView.HEADER_ONLY });
|
|
155
|
-
|
|
156
|
-
const callArgs = (ctx.query.listBlocks as any).mock.calls[0][0];
|
|
157
|
-
expect(callArgs.view).toBe(BlockView.HEADER_ONLY);
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
it("should list blocks with filter", async () => {
|
|
161
|
-
const ctx = createMockContext();
|
|
162
|
-
const mockResponse = createMockListBlocksResponse();
|
|
163
|
-
const filter = { expression: "slot > 1000" };
|
|
164
|
-
vi.spyOn(ctx.query, "listBlocks").mockResolvedValue(mockResponse);
|
|
165
|
-
|
|
166
|
-
await listBlocks(ctx, { filter: filter as any });
|
|
167
|
-
|
|
168
|
-
const callArgs = (ctx.query.listBlocks as any).mock.calls[0][0];
|
|
169
|
-
expect(callArgs.filter).toBeDefined();
|
|
170
|
-
expect(callArgs.filter.expression).toBe("slot > 1000");
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
it("should list blocks with pagination", async () => {
|
|
174
|
-
const ctx = createMockContext();
|
|
175
|
-
const mockResponse = createMockListBlocksResponse();
|
|
176
|
-
const page = { pageSize: 10, pageToken: "token" };
|
|
177
|
-
vi.spyOn(ctx.query, "listBlocks").mockResolvedValue(mockResponse);
|
|
178
|
-
|
|
179
|
-
await listBlocks(ctx, { page: page as any });
|
|
180
|
-
|
|
181
|
-
const callArgs = (ctx.query.listBlocks as any).mock.calls[0][0];
|
|
182
|
-
expect(callArgs.page).toBeDefined();
|
|
183
|
-
expect(callArgs.page.pageSize).toBe(10);
|
|
184
|
-
expect(callArgs.page.pageToken).toBe("token");
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
it("should list blocks with custom minConsensus", async () => {
|
|
188
|
-
const ctx = createMockContext();
|
|
189
|
-
const mockResponse = createMockListBlocksResponse();
|
|
190
|
-
vi.spyOn(ctx.query, "listBlocks").mockResolvedValue(mockResponse);
|
|
191
|
-
|
|
192
|
-
await listBlocks(ctx, { minConsensus: ConsensusStatus.FINALIZED });
|
|
193
|
-
|
|
194
|
-
const callArgs = (ctx.query.listBlocks as any).mock.calls[0][0];
|
|
195
|
-
expect(callArgs.minConsensus).toBe(ConsensusStatus.FINALIZED);
|
|
196
|
-
});
|
|
197
|
-
});
|
|
198
|
-
});
|
|
199
|
-
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { create } from "@bufbuild/protobuf";
|
|
2
|
-
import { describe, expect, it, vi } from "vitest";
|
|
3
|
-
import { createMockContext } from "../../__tests__/helpers/test-utils";
|
|
4
|
-
import { CurrentVersionSchema, VersionContextSchema } from "../../proto/thru/common/v1/consensus_pb";
|
|
5
|
-
import { EventSchema } from "../../proto/thru/services/v1/query_service_pb";
|
|
6
|
-
import { getEvent } from "../events";
|
|
7
|
-
|
|
8
|
-
describe("events", () => {
|
|
9
|
-
describe("getEvent", () => {
|
|
10
|
-
it("should return event with valid eventId", async () => {
|
|
11
|
-
const ctx = createMockContext();
|
|
12
|
-
const mockEvent = create(EventSchema, {
|
|
13
|
-
eventId: "test-event-id",
|
|
14
|
-
slot: 1000n,
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
vi.spyOn(ctx.query, "getEvent").mockResolvedValue(mockEvent);
|
|
18
|
-
|
|
19
|
-
const result = await getEvent(ctx, "test-event-id");
|
|
20
|
-
|
|
21
|
-
expect(result).toBe(mockEvent);
|
|
22
|
-
expect(result.eventId).toBe("test-event-id");
|
|
23
|
-
expect(ctx.query.getEvent).toHaveBeenCalledTimes(1);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it("should include eventId in request", async () => {
|
|
27
|
-
const ctx = createMockContext();
|
|
28
|
-
const mockEvent = create(EventSchema, { eventId: "test-event-id" });
|
|
29
|
-
vi.spyOn(ctx.query, "getEvent").mockResolvedValue(mockEvent);
|
|
30
|
-
|
|
31
|
-
await getEvent(ctx, "test-event-id");
|
|
32
|
-
|
|
33
|
-
const callArgs = (ctx.query.getEvent as any).mock.calls[0][0];
|
|
34
|
-
expect(callArgs.eventId).toBe("test-event-id");
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it("should include version context when provided", async () => {
|
|
38
|
-
const ctx = createMockContext();
|
|
39
|
-
const mockEvent = create(EventSchema, { eventId: "test-event-id" });
|
|
40
|
-
vi.spyOn(ctx.query, "getEvent").mockResolvedValue(mockEvent);
|
|
41
|
-
|
|
42
|
-
const versionContext = create(VersionContextSchema, {
|
|
43
|
-
version: {
|
|
44
|
-
case: "current",
|
|
45
|
-
value: create(CurrentVersionSchema, {}),
|
|
46
|
-
},
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
await getEvent(ctx, "test-event-id", { versionContext });
|
|
50
|
-
|
|
51
|
-
const callArgs = (ctx.query.getEvent as any).mock.calls[0][0];
|
|
52
|
-
expect(callArgs.versionContext).toBeDefined();
|
|
53
|
-
expect(callArgs.versionContext.version?.case).toBe("current");
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it("should throw error for empty eventId", () => {
|
|
57
|
-
const ctx = createMockContext();
|
|
58
|
-
|
|
59
|
-
expect(() => getEvent(ctx, "")).toThrow("eventId is required");
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it("should not include version context when not provided", async () => {
|
|
63
|
-
const ctx = createMockContext();
|
|
64
|
-
const mockEvent = create(EventSchema, { eventId: "test-event-id" });
|
|
65
|
-
vi.spyOn(ctx.query, "getEvent").mockResolvedValue(mockEvent);
|
|
66
|
-
|
|
67
|
-
await getEvent(ctx, "test-event-id");
|
|
68
|
-
|
|
69
|
-
const callArgs = (ctx.query.getEvent as any).mock.calls[0][0];
|
|
70
|
-
expect(callArgs.versionContext).toBeUndefined();
|
|
71
|
-
});
|
|
72
|
-
});
|
|
73
|
-
});
|
|
74
|
-
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it, vi } from "vitest";
|
|
2
|
-
import { createMockContext, createMockHeightResponse } from "../../__tests__/helpers/test-utils";
|
|
3
|
-
import { getBlockHeight } from "../height";
|
|
4
|
-
|
|
5
|
-
describe("height", () => {
|
|
6
|
-
describe("getBlockHeight", () => {
|
|
7
|
-
it("should return height response", async () => {
|
|
8
|
-
const ctx = createMockContext();
|
|
9
|
-
const mockResponse = createMockHeightResponse({
|
|
10
|
-
finalized: 1000n,
|
|
11
|
-
locallyExecuted: 1001n,
|
|
12
|
-
clusterExecuted: 1002n,
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
vi.spyOn(ctx.query, "getHeight").mockResolvedValue(mockResponse);
|
|
16
|
-
|
|
17
|
-
const result = await getBlockHeight(ctx);
|
|
18
|
-
|
|
19
|
-
expect(result).toBe(mockResponse);
|
|
20
|
-
expect(result.finalized).toBe(1000n);
|
|
21
|
-
expect(result.locallyExecuted).toBe(1001n);
|
|
22
|
-
expect(result.clusterExecuted).toBe(1002n);
|
|
23
|
-
expect(ctx.query.getHeight).toHaveBeenCalledTimes(1);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it("should create empty request", async () => {
|
|
27
|
-
const ctx = createMockContext();
|
|
28
|
-
const mockResponse = createMockHeightResponse();
|
|
29
|
-
vi.spyOn(ctx.query, "getHeight").mockResolvedValue(mockResponse);
|
|
30
|
-
|
|
31
|
-
await getBlockHeight(ctx);
|
|
32
|
-
|
|
33
|
-
const callArgs = (ctx.query.getHeight as any).mock.calls[0][0];
|
|
34
|
-
// Request should be created (empty GetHeightRequest)
|
|
35
|
-
expect(callArgs).toBeDefined();
|
|
36
|
-
});
|
|
37
|
-
});
|
|
38
|
-
});
|
|
39
|
-
|
|
@@ -1,288 +0,0 @@
|
|
|
1
|
-
import { decodeAddress, decodeSignature } from "@thru/helpers";
|
|
2
|
-
import { describe, expect, it } from "vitest";
|
|
3
|
-
import { generateTestAddress, generateTestPubkey, generateTestSignature, generateTestSignatureString } from "../../__tests__/helpers/test-utils";
|
|
4
|
-
import {
|
|
5
|
-
deriveProgramAddress,
|
|
6
|
-
toBlockHash,
|
|
7
|
-
toPubkey,
|
|
8
|
-
toSignature,
|
|
9
|
-
} from "../helpers";
|
|
10
|
-
|
|
11
|
-
describe("helpers", () => {
|
|
12
|
-
describe("toSignature", () => {
|
|
13
|
-
it("should accept Uint8Array with 64 bytes", () => {
|
|
14
|
-
const sigBytes = generateTestSignature();
|
|
15
|
-
const result = toSignature(sigBytes);
|
|
16
|
-
|
|
17
|
-
expect(result.value).toEqual(sigBytes);
|
|
18
|
-
expect(result.value.length).toBe(64);
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
it("should accept ts- prefixed signature string", () => {
|
|
22
|
-
const sigString = generateTestSignatureString();
|
|
23
|
-
const result = toSignature(sigString);
|
|
24
|
-
|
|
25
|
-
expect(result.value.length).toBe(64);
|
|
26
|
-
// Verify it decodes correctly
|
|
27
|
-
const decoded = decodeSignature(sigString);
|
|
28
|
-
expect(result.value).toEqual(decoded);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
it("should accept base64 signature string", () => {
|
|
32
|
-
const sigBytes = generateTestSignature();
|
|
33
|
-
const base64 = btoa(String.fromCharCode(...sigBytes));
|
|
34
|
-
const result = toSignature(base64);
|
|
35
|
-
|
|
36
|
-
expect(result.value.length).toBe(64);
|
|
37
|
-
expect(result.value).toEqual(sigBytes);
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
it("should throw error for Uint8Array with wrong length", () => {
|
|
41
|
-
const invalidSig = new Uint8Array(32); // Should be 64
|
|
42
|
-
|
|
43
|
-
expect(() => toSignature(invalidSig)).toThrow("signature must contain 64 bytes");
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
it("should throw error for invalid input type", () => {
|
|
47
|
-
expect(() => toSignature(null as any)).toThrow("signature is required");
|
|
48
|
-
expect(() => toSignature(undefined as any)).toThrow("signature is required");
|
|
49
|
-
});
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
describe("toPubkey", () => {
|
|
53
|
-
it("should accept Uint8Array with 32 bytes", () => {
|
|
54
|
-
const pubkeyBytes = generateTestPubkey();
|
|
55
|
-
const result = toPubkey(pubkeyBytes, "testField");
|
|
56
|
-
|
|
57
|
-
expect(result.value).toEqual(pubkeyBytes);
|
|
58
|
-
expect(result.value.length).toBe(32);
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
it("should accept ta- prefixed address string", () => {
|
|
62
|
-
const address = generateTestAddress();
|
|
63
|
-
const result = toPubkey(address, "testField");
|
|
64
|
-
|
|
65
|
-
expect(result.value.length).toBe(32);
|
|
66
|
-
// Verify it decodes correctly
|
|
67
|
-
const decoded = decodeAddress(address);
|
|
68
|
-
expect(result.value).toEqual(decoded);
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it("should accept base64 pubkey string", () => {
|
|
72
|
-
const pubkeyBytes = generateTestPubkey();
|
|
73
|
-
const base64 = btoa(String.fromCharCode(...pubkeyBytes));
|
|
74
|
-
const result = toPubkey(base64, "testField");
|
|
75
|
-
|
|
76
|
-
expect(result.value.length).toBe(32);
|
|
77
|
-
expect(result.value).toEqual(pubkeyBytes);
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
it("should throw error for Uint8Array with wrong length", () => {
|
|
81
|
-
const invalidPubkey = new Uint8Array(64); // Should be 32
|
|
82
|
-
|
|
83
|
-
expect(() => toPubkey(invalidPubkey, "testField")).toThrow("testField must contain 32 bytes");
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
it("should throw error for invalid input type", () => {
|
|
87
|
-
expect(() => toPubkey(null as any, "testField")).toThrow("testField is required");
|
|
88
|
-
expect(() => toPubkey(undefined as any, "testField")).toThrow("testField is required");
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
it("should include field name in error message", () => {
|
|
92
|
-
const invalidPubkey = new Uint8Array(64);
|
|
93
|
-
|
|
94
|
-
expect(() => toPubkey(invalidPubkey, "myCustomField")).toThrow("myCustomField must contain 32 bytes");
|
|
95
|
-
});
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
describe("toBlockHash", () => {
|
|
99
|
-
it("should accept Uint8Array", () => {
|
|
100
|
-
const hashBytes = new Uint8Array([1, 2, 3, 4]);
|
|
101
|
-
const result = toBlockHash(hashBytes);
|
|
102
|
-
|
|
103
|
-
expect(result.value).toEqual(hashBytes);
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
it("should accept base64 string", () => {
|
|
107
|
-
const hashBytes = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
|
|
108
|
-
const base64 = btoa(String.fromCharCode(...hashBytes));
|
|
109
|
-
const result = toBlockHash(base64);
|
|
110
|
-
|
|
111
|
-
expect(result.value).toBeInstanceOf(Uint8Array);
|
|
112
|
-
expect(result.value).toEqual(hashBytes);
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
it("should accept hex string", () => {
|
|
116
|
-
const hashBytes = new Uint8Array([0x01, 0x02, 0x03, 0x04]);
|
|
117
|
-
const hexString = Array.from(hashBytes)
|
|
118
|
-
.map(b => b.toString(16).padStart(2, "0"))
|
|
119
|
-
.join("");
|
|
120
|
-
const result = toBlockHash(hexString);
|
|
121
|
-
|
|
122
|
-
expect(result.value).toBeInstanceOf(Uint8Array);
|
|
123
|
-
// Note: ensureBytes may handle hex differently, so we just verify it works
|
|
124
|
-
expect(result.value.length).toBeGreaterThan(0);
|
|
125
|
-
});
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
describe("deriveProgramAddress", () => {
|
|
129
|
-
it("should derive address from program address and seed (Uint8Array)", () => {
|
|
130
|
-
const programAddress = generateTestPubkey(0x01);
|
|
131
|
-
const seed = new Uint8Array([0x02, 0x03]);
|
|
132
|
-
|
|
133
|
-
const result = deriveProgramAddress({
|
|
134
|
-
programAddress,
|
|
135
|
-
seed,
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
expect(result.bytes).toBeInstanceOf(Uint8Array);
|
|
139
|
-
expect(result.bytes.length).toBe(32);
|
|
140
|
-
expect(result.address).toBeTruthy();
|
|
141
|
-
expect(result.address.startsWith("ta")).toBe(true);
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
it("should derive address with ephemeral flag set", () => {
|
|
145
|
-
const programAddress = generateTestPubkey(0x01);
|
|
146
|
-
const seed = new Uint8Array([0x02, 0x03]);
|
|
147
|
-
|
|
148
|
-
const resultEphemeral = deriveProgramAddress({
|
|
149
|
-
programAddress,
|
|
150
|
-
seed,
|
|
151
|
-
ephemeral: true,
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
const resultNonEphemeral = deriveProgramAddress({
|
|
155
|
-
programAddress,
|
|
156
|
-
seed,
|
|
157
|
-
ephemeral: false,
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
// Ephemeral and non-ephemeral should produce different addresses
|
|
161
|
-
expect(resultEphemeral.bytes).not.toEqual(resultNonEphemeral.bytes);
|
|
162
|
-
expect(resultEphemeral.address).not.toBe(resultNonEphemeral.address);
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
it("should be deterministic for same inputs", () => {
|
|
166
|
-
const programAddress = generateTestPubkey(0x01);
|
|
167
|
-
const seed = new Uint8Array([0x02, 0x03]);
|
|
168
|
-
|
|
169
|
-
const result1 = deriveProgramAddress({
|
|
170
|
-
programAddress,
|
|
171
|
-
seed,
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
const result2 = deriveProgramAddress({
|
|
175
|
-
programAddress,
|
|
176
|
-
seed,
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
expect(result1.bytes).toEqual(result2.bytes);
|
|
180
|
-
expect(result1.address).toBe(result2.address);
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
it("should accept program address as ta- prefixed string", () => {
|
|
184
|
-
const programAddress = generateTestAddress(0x01);
|
|
185
|
-
const seed = new Uint8Array([0x02, 0x03]);
|
|
186
|
-
|
|
187
|
-
const result = deriveProgramAddress({
|
|
188
|
-
programAddress,
|
|
189
|
-
seed,
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
expect(result.bytes.length).toBe(32);
|
|
193
|
-
expect(result.address).toBeTruthy();
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
it("should accept program address as hex string", () => {
|
|
197
|
-
const programAddressBytes = generateTestPubkey(0x01);
|
|
198
|
-
const programAddressHex = Array.from(programAddressBytes)
|
|
199
|
-
.map(b => b.toString(16).padStart(2, "0"))
|
|
200
|
-
.join("");
|
|
201
|
-
|
|
202
|
-
const seed = new Uint8Array([0x02, 0x03]);
|
|
203
|
-
|
|
204
|
-
const result = deriveProgramAddress({
|
|
205
|
-
programAddress: programAddressHex,
|
|
206
|
-
seed,
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
expect(result.bytes.length).toBe(32);
|
|
210
|
-
expect(result.address).toBeTruthy();
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
it("should accept seed as string", () => {
|
|
214
|
-
const programAddress = generateTestPubkey(0x01);
|
|
215
|
-
const seed = "my-seed-string";
|
|
216
|
-
|
|
217
|
-
const result = deriveProgramAddress({
|
|
218
|
-
programAddress,
|
|
219
|
-
seed,
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
expect(result.bytes.length).toBe(32);
|
|
223
|
-
expect(result.address).toBeTruthy();
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
it("should accept seed as hex string", () => {
|
|
227
|
-
const programAddress = generateTestPubkey(0x01);
|
|
228
|
-
const seedBytes = new Uint8Array(32);
|
|
229
|
-
seedBytes.fill(0x42);
|
|
230
|
-
const seedHex = Array.from(seedBytes)
|
|
231
|
-
.map(b => b.toString(16).padStart(2, "0"))
|
|
232
|
-
.join("");
|
|
233
|
-
|
|
234
|
-
const result = deriveProgramAddress({
|
|
235
|
-
programAddress,
|
|
236
|
-
seed: seedHex,
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
expect(result.bytes.length).toBe(32);
|
|
240
|
-
expect(result.address).toBeTruthy();
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
it("should throw error for invalid program address length", () => {
|
|
244
|
-
const invalidProgramAddress = new Uint8Array(31); // Should be 32
|
|
245
|
-
const seed = new Uint8Array([0x02]);
|
|
246
|
-
|
|
247
|
-
expect(() => deriveProgramAddress({
|
|
248
|
-
programAddress: invalidProgramAddress,
|
|
249
|
-
seed,
|
|
250
|
-
})).toThrow("Program address must contain 32 bytes");
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
it("should throw error for empty seed", () => {
|
|
254
|
-
const programAddress = generateTestPubkey(0x01);
|
|
255
|
-
|
|
256
|
-
expect(() => deriveProgramAddress({
|
|
257
|
-
programAddress,
|
|
258
|
-
seed: "",
|
|
259
|
-
})).toThrow("Seed cannot be empty");
|
|
260
|
-
|
|
261
|
-
expect(() => deriveProgramAddress({
|
|
262
|
-
programAddress,
|
|
263
|
-
seed: new Uint8Array(0),
|
|
264
|
-
})).toThrow("Seed cannot be empty");
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
it("should throw error for seed too long", () => {
|
|
268
|
-
const programAddress = generateTestPubkey(0x01);
|
|
269
|
-
const longSeed = new Uint8Array(33); // Max is 32
|
|
270
|
-
|
|
271
|
-
expect(() => deriveProgramAddress({
|
|
272
|
-
programAddress,
|
|
273
|
-
seed: longSeed,
|
|
274
|
-
})).toThrow("Seed cannot exceed 32 bytes");
|
|
275
|
-
});
|
|
276
|
-
|
|
277
|
-
it("should throw error for invalid program address format", () => {
|
|
278
|
-
const invalidProgramAddress = "invalid-format";
|
|
279
|
-
const seed = new Uint8Array([0x02]);
|
|
280
|
-
|
|
281
|
-
expect(() => deriveProgramAddress({
|
|
282
|
-
programAddress: invalidProgramAddress,
|
|
283
|
-
seed,
|
|
284
|
-
})).toThrow("Program address must be a 32-byte value, ta-address, or 64-character hex string");
|
|
285
|
-
});
|
|
286
|
-
});
|
|
287
|
-
});
|
|
288
|
-
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import { generateKeyPair } from "../keys";
|
|
3
|
-
|
|
4
|
-
describe("keys", () => {
|
|
5
|
-
describe("generateKeyPair", () => {
|
|
6
|
-
it("should generate valid keypair", async () => {
|
|
7
|
-
const result = await generateKeyPair();
|
|
8
|
-
|
|
9
|
-
expect(result).toBeDefined();
|
|
10
|
-
expect(result.address).toBeTruthy();
|
|
11
|
-
expect(result.publicKey).toBeInstanceOf(Uint8Array);
|
|
12
|
-
expect(result.privateKey).toBeInstanceOf(Uint8Array);
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
it("should generate 32-byte public key", async () => {
|
|
16
|
-
const result = await generateKeyPair();
|
|
17
|
-
|
|
18
|
-
expect(result.publicKey.length).toBe(32);
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
it("should generate 32-byte private key (Ed25519 seed)", async () => {
|
|
22
|
-
const result = await generateKeyPair();
|
|
23
|
-
|
|
24
|
-
expect(result.privateKey.length).toBe(32);
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
it("should generate address starting with 'ta'", async () => {
|
|
28
|
-
const result = await generateKeyPair();
|
|
29
|
-
|
|
30
|
-
expect(result.address.startsWith("ta")).toBe(true);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it("should generate different keypairs on each call", async () => {
|
|
34
|
-
const result1 = await generateKeyPair();
|
|
35
|
-
const result2 = await generateKeyPair();
|
|
36
|
-
|
|
37
|
-
// All fields should be different (very unlikely to be same)
|
|
38
|
-
expect(result1.address).not.toBe(result2.address);
|
|
39
|
-
expect(result1.publicKey).not.toEqual(result2.publicKey);
|
|
40
|
-
expect(result1.privateKey).not.toEqual(result2.privateKey);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it("should generate valid Ed25519 keypair format", async () => {
|
|
44
|
-
const result = await generateKeyPair();
|
|
45
|
-
|
|
46
|
-
// Public key should be 32 bytes
|
|
47
|
-
expect(result.publicKey.length).toBe(32);
|
|
48
|
-
// Private key should be 32 bytes (Ed25519 seed)
|
|
49
|
-
expect(result.privateKey.length).toBe(32);
|
|
50
|
-
// Address should be valid format
|
|
51
|
-
expect(result.address.length).toBeGreaterThan(0);
|
|
52
|
-
});
|
|
53
|
-
});
|
|
54
|
-
});
|
|
55
|
-
|